summaryrefslogtreecommitdiff
path: root/auth2.c
diff options
context:
space:
mode:
Diffstat (limited to 'auth2.c')
-rw-r--r--auth2.c173
1 files changed, 153 insertions, 20 deletions
diff --git a/auth2.c b/auth2.c
index 2f51be232..1f9ec6327 100644
--- a/auth2.c
+++ b/auth2.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2.c,v 1.137 2017/02/03 23:05:57 djm Exp $ */ 1/* $OpenBSD: auth2.c,v 1.143 2017/06/24 06:34:38 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -30,6 +30,7 @@
30#include <sys/uio.h> 30#include <sys/uio.h>
31 31
32#include <fcntl.h> 32#include <fcntl.h>
33#include <limits.h>
33#include <pwd.h> 34#include <pwd.h>
34#include <stdarg.h> 35#include <stdarg.h>
35#include <string.h> 36#include <string.h>
@@ -55,6 +56,7 @@
55#include "ssh-gss.h" 56#include "ssh-gss.h"
56#endif 57#endif
57#include "monitor_wrap.h" 58#include "monitor_wrap.h"
59#include "ssherr.h"
58 60
59/* import */ 61/* import */
60extern ServerOptions options; 62extern ServerOptions options;
@@ -89,8 +91,8 @@ Authmethod *authmethods[] = {
89 91
90/* protocol */ 92/* protocol */
91 93
92static int input_service_request(int, u_int32_t, void *); 94static int input_service_request(int, u_int32_t, struct ssh *);
93static int input_userauth_request(int, u_int32_t, void *); 95static int input_userauth_request(int, u_int32_t, struct ssh *);
94 96
95/* helper */ 97/* helper */
96static Authmethod *authmethod_lookup(Authctxt *, const char *); 98static Authmethod *authmethod_lookup(Authctxt *, const char *);
@@ -170,16 +172,19 @@ done:
170void 172void
171do_authentication2(Authctxt *authctxt) 173do_authentication2(Authctxt *authctxt)
172{ 174{
173 dispatch_init(&dispatch_protocol_error); 175 struct ssh *ssh = active_state; /* XXX */
174 dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request); 176 ssh->authctxt = authctxt; /* XXX move to caller */
175 dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt); 177 ssh_dispatch_init(ssh, &dispatch_protocol_error);
178 ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_REQUEST, &input_service_request);
179 ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt->success);
180 ssh->authctxt = NULL;
176} 181}
177 182
178/*ARGSUSED*/ 183/*ARGSUSED*/
179static int 184static int
180input_service_request(int type, u_int32_t seq, void *ctxt) 185input_service_request(int type, u_int32_t seq, struct ssh *ssh)
181{ 186{
182 Authctxt *authctxt = ctxt; 187 Authctxt *authctxt = ssh->authctxt;
183 u_int len; 188 u_int len;
184 int acceptit = 0; 189 int acceptit = 0;
185 char *service = packet_get_cstring(&len); 190 char *service = packet_get_cstring(&len);
@@ -192,7 +197,7 @@ input_service_request(int type, u_int32_t seq, void *ctxt)
192 if (!authctxt->success) { 197 if (!authctxt->success) {
193 acceptit = 1; 198 acceptit = 1;
194 /* now we can handle user-auth requests */ 199 /* now we can handle user-auth requests */
195 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request); 200 ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
196 } 201 }
197 } 202 }
198 /* XXX all other service requests are denied */ 203 /* XXX all other service requests are denied */
@@ -212,10 +217,9 @@ input_service_request(int type, u_int32_t seq, void *ctxt)
212 217
213/*ARGSUSED*/ 218/*ARGSUSED*/
214static int 219static int
215input_userauth_request(int type, u_int32_t seq, void *ctxt) 220input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
216{ 221{
217 struct ssh *ssh = active_state; /* XXX */ 222 Authctxt *authctxt = ssh->authctxt;
218 Authctxt *authctxt = ctxt;
219 Authmethod *m = NULL; 223 Authmethod *m = NULL;
220 char *user, *service, *method, *style = NULL, *role = NULL; 224 char *user, *service, *method, *style = NULL, *role = NULL;
221 int authenticated = 0; 225 int authenticated = 0;
@@ -275,14 +279,15 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
275 authctxt->user, authctxt->service, user, service); 279 authctxt->user, authctxt->service, user, service);
276 } 280 }
277 /* reset state */ 281 /* reset state */
278 auth2_challenge_stop(authctxt); 282 auth2_challenge_stop(ssh);
279 283
280#ifdef GSSAPI 284#ifdef GSSAPI
281 /* XXX move to auth2_gssapi_stop() */ 285 /* XXX move to auth2_gssapi_stop() */
282 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); 286 ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
283 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); 287 ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
284#endif 288#endif
285 289
290 auth2_authctxt_reset_info(authctxt);
286 authctxt->postponed = 0; 291 authctxt->postponed = 0;
287 authctxt->server_caused_failure = 0; 292 authctxt->server_caused_failure = 0;
288 293
@@ -290,9 +295,9 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
290 m = authmethod_lookup(authctxt, method); 295 m = authmethod_lookup(authctxt, method);
291 if (m != NULL && authctxt->failures < options.max_authtries) { 296 if (m != NULL && authctxt->failures < options.max_authtries) {
292 debug2("input_userauth_request: try method %s", method); 297 debug2("input_userauth_request: try method %s", method);
293 authenticated = m->userauth(authctxt); 298 authenticated = m->userauth(ssh);
294 } 299 }
295 userauth_finish(authctxt, authenticated, method, NULL); 300 userauth_finish(ssh, authenticated, method, NULL);
296 301
297 free(service); 302 free(service);
298 free(user); 303 free(user);
@@ -301,10 +306,10 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
301} 306}
302 307
303void 308void
304userauth_finish(Authctxt *authctxt, int authenticated, const char *method, 309userauth_finish(struct ssh *ssh, int authenticated, const char *method,
305 const char *submethod) 310 const char *submethod)
306{ 311{
307 struct ssh *ssh = active_state; /* XXX */ 312 Authctxt *authctxt = ssh->authctxt;
308 char *methods; 313 char *methods;
309 int partial = 0; 314 int partial = 0;
310 315
@@ -333,6 +338,10 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
333 /* Log before sending the reply */ 338 /* Log before sending the reply */
334 auth_log(authctxt, authenticated, partial, method, submethod); 339 auth_log(authctxt, authenticated, partial, method, submethod);
335 340
341 /* Update information exposed to session */
342 if (authenticated || partial)
343 auth2_update_session_info(authctxt, method, submethod);
344
336 if (authctxt->postponed) 345 if (authctxt->postponed)
337 return; 346 return;
338 347
@@ -360,7 +369,7 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
360 369
361 if (authenticated == 1) { 370 if (authenticated == 1) {
362 /* turn off userauth */ 371 /* turn off userauth */
363 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore); 372 ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
364 packet_start(SSH2_MSG_USERAUTH_SUCCESS); 373 packet_start(SSH2_MSG_USERAUTH_SUCCESS);
365 packet_send(); 374 packet_send();
366 packet_write_wait(); 375 packet_write_wait();
@@ -630,4 +639,128 @@ auth2_update_methods_lists(Authctxt *authctxt, const char *method,
630 return 0; 639 return 0;
631} 640}
632 641
642/* Reset method-specific information */
643void auth2_authctxt_reset_info(Authctxt *authctxt)
644{
645 sshkey_free(authctxt->auth_method_key);
646 free(authctxt->auth_method_info);
647 authctxt->auth_method_key = NULL;
648 authctxt->auth_method_info = NULL;
649}
650
651/* Record auth method-specific information for logs */
652void
653auth2_record_info(Authctxt *authctxt, const char *fmt, ...)
654{
655 va_list ap;
656 int i;
657
658 free(authctxt->auth_method_info);
659 authctxt->auth_method_info = NULL;
660
661 va_start(ap, fmt);
662 i = vasprintf(&authctxt->auth_method_info, fmt, ap);
663 va_end(ap);
664
665 if (i < 0 || authctxt->auth_method_info == NULL)
666 fatal("%s: vasprintf failed", __func__);
667}
668
669/*
670 * Records a public key used in authentication. This is used for logging
671 * and to ensure that the same key is not subsequently accepted again for
672 * multiple authentication.
673 */
674void
675auth2_record_key(Authctxt *authctxt, int authenticated,
676 const struct sshkey *key)
677{
678 struct sshkey **tmp, *dup;
679 int r;
680
681 if ((r = sshkey_demote(key, &dup)) != 0)
682 fatal("%s: copy key: %s", __func__, ssh_err(r));
683 sshkey_free(authctxt->auth_method_key);
684 authctxt->auth_method_key = dup;
685
686 if (!authenticated)
687 return;
688
689 /* If authenticated, make sure we don't accept this key again */
690 if ((r = sshkey_demote(key, &dup)) != 0)
691 fatal("%s: copy key: %s", __func__, ssh_err(r));
692 if (authctxt->nprev_keys >= INT_MAX ||
693 (tmp = recallocarray(authctxt->prev_keys, authctxt->nprev_keys,
694 authctxt->nprev_keys + 1, sizeof(*authctxt->prev_keys))) == NULL)
695 fatal("%s: reallocarray failed", __func__);
696 authctxt->prev_keys = tmp;
697 authctxt->prev_keys[authctxt->nprev_keys] = dup;
698 authctxt->nprev_keys++;
699
700}
701
702/* Checks whether a key has already been previously used for authentication */
703int
704auth2_key_already_used(Authctxt *authctxt, const struct sshkey *key)
705{
706 u_int i;
707 char *fp;
708
709 for (i = 0; i < authctxt->nprev_keys; i++) {
710 if (sshkey_equal_public(key, authctxt->prev_keys[i])) {
711 fp = sshkey_fingerprint(authctxt->prev_keys[i],
712 options.fingerprint_hash, SSH_FP_DEFAULT);
713 debug3("%s: key already used: %s %s", __func__,
714 sshkey_type(authctxt->prev_keys[i]),
715 fp == NULL ? "UNKNOWN" : fp);
716 free(fp);
717 return 1;
718 }
719 }
720 return 0;
721}
722
723/*
724 * Updates authctxt->session_info with details of authentication. Should be
725 * whenever an authentication method succeeds.
726 */
727void
728auth2_update_session_info(Authctxt *authctxt, const char *method,
729 const char *submethod)
730{
731 int r;
732
733 if (authctxt->session_info == NULL) {
734 if ((authctxt->session_info = sshbuf_new()) == NULL)
735 fatal("%s: sshbuf_new", __func__);
736 }
737
738 /* Append method[/submethod] */
739 if ((r = sshbuf_putf(authctxt->session_info, "%s%s%s",
740 method, submethod == NULL ? "" : "/",
741 submethod == NULL ? "" : submethod)) != 0)
742 fatal("%s: append method: %s", __func__, ssh_err(r));
743
744 /* Append key if present */
745 if (authctxt->auth_method_key != NULL) {
746 if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 ||
747 (r = sshkey_format_text(authctxt->auth_method_key,
748 authctxt->session_info)) != 0)
749 fatal("%s: append key: %s", __func__, ssh_err(r));
750 }
751
752 if (authctxt->auth_method_info != NULL) {
753 /* Ensure no ambiguity here */
754 if (strchr(authctxt->auth_method_info, '\n') != NULL)
755 fatal("%s: auth_method_info contains \\n", __func__);
756 if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 ||
757 (r = sshbuf_putf(authctxt->session_info, "%s",
758 authctxt->auth_method_info)) != 0) {
759 fatal("%s: append method info: %s",
760 __func__, ssh_err(r));
761 }
762 }
763 if ((r = sshbuf_put_u8(authctxt->session_info, '\n')) != 0)
764 fatal("%s: append: %s", __func__, ssh_err(r));
765}
633 766