summaryrefslogtreecommitdiff
path: root/auth2.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2017-10-04 11:23:58 +0100
committerColin Watson <cjwatson@debian.org>2017-10-04 11:23:58 +0100
commit62f54f20bf351468e0124f63cc2902ee40d9b0e9 (patch)
tree3e090f2711b94ca5029d3fa3e8047b1ed1448b1f /auth2.c
parent6fabaf6fd9b07cc8bc6a17c9c4a5b76849cfc874 (diff)
parent66bf74a92131b7effe49fb0eefe5225151869dc5 (diff)
Import openssh_7.6p1.orig.tar.gz
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 97dd2ef0a..862e09960 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;
@@ -87,8 +89,8 @@ Authmethod *authmethods[] = {
87 89
88/* protocol */ 90/* protocol */
89 91
90static int input_service_request(int, u_int32_t, void *); 92static int input_service_request(int, u_int32_t, struct ssh *);
91static int input_userauth_request(int, u_int32_t, void *); 93static int input_userauth_request(int, u_int32_t, struct ssh *);
92 94
93/* helper */ 95/* helper */
94static Authmethod *authmethod_lookup(Authctxt *, const char *); 96static Authmethod *authmethod_lookup(Authctxt *, const char *);
@@ -168,16 +170,19 @@ done:
168void 170void
169do_authentication2(Authctxt *authctxt) 171do_authentication2(Authctxt *authctxt)
170{ 172{
171 dispatch_init(&dispatch_protocol_error); 173 struct ssh *ssh = active_state; /* XXX */
172 dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request); 174 ssh->authctxt = authctxt; /* XXX move to caller */
173 dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt); 175 ssh_dispatch_init(ssh, &dispatch_protocol_error);
176 ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_REQUEST, &input_service_request);
177 ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt->success);
178 ssh->authctxt = NULL;
174} 179}
175 180
176/*ARGSUSED*/ 181/*ARGSUSED*/
177static int 182static int
178input_service_request(int type, u_int32_t seq, void *ctxt) 183input_service_request(int type, u_int32_t seq, struct ssh *ssh)
179{ 184{
180 Authctxt *authctxt = ctxt; 185 Authctxt *authctxt = ssh->authctxt;
181 u_int len; 186 u_int len;
182 int acceptit = 0; 187 int acceptit = 0;
183 char *service = packet_get_cstring(&len); 188 char *service = packet_get_cstring(&len);
@@ -190,7 +195,7 @@ input_service_request(int type, u_int32_t seq, void *ctxt)
190 if (!authctxt->success) { 195 if (!authctxt->success) {
191 acceptit = 1; 196 acceptit = 1;
192 /* now we can handle user-auth requests */ 197 /* now we can handle user-auth requests */
193 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request); 198 ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
194 } 199 }
195 } 200 }
196 /* XXX all other service requests are denied */ 201 /* XXX all other service requests are denied */
@@ -210,10 +215,9 @@ input_service_request(int type, u_int32_t seq, void *ctxt)
210 215
211/*ARGSUSED*/ 216/*ARGSUSED*/
212static int 217static int
213input_userauth_request(int type, u_int32_t seq, void *ctxt) 218input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
214{ 219{
215 struct ssh *ssh = active_state; /* XXX */ 220 Authctxt *authctxt = ssh->authctxt;
216 Authctxt *authctxt = ctxt;
217 Authmethod *m = NULL; 221 Authmethod *m = NULL;
218 char *user, *service, *method, *style = NULL; 222 char *user, *service, *method, *style = NULL;
219 int authenticated = 0; 223 int authenticated = 0;
@@ -267,14 +271,15 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
267 authctxt->user, authctxt->service, user, service); 271 authctxt->user, authctxt->service, user, service);
268 } 272 }
269 /* reset state */ 273 /* reset state */
270 auth2_challenge_stop(authctxt); 274 auth2_challenge_stop(ssh);
271 275
272#ifdef GSSAPI 276#ifdef GSSAPI
273 /* XXX move to auth2_gssapi_stop() */ 277 /* XXX move to auth2_gssapi_stop() */
274 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); 278 ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
275 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); 279 ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
276#endif 280#endif
277 281
282 auth2_authctxt_reset_info(authctxt);
278 authctxt->postponed = 0; 283 authctxt->postponed = 0;
279 authctxt->server_caused_failure = 0; 284 authctxt->server_caused_failure = 0;
280 285
@@ -282,9 +287,9 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
282 m = authmethod_lookup(authctxt, method); 287 m = authmethod_lookup(authctxt, method);
283 if (m != NULL && authctxt->failures < options.max_authtries) { 288 if (m != NULL && authctxt->failures < options.max_authtries) {
284 debug2("input_userauth_request: try method %s", method); 289 debug2("input_userauth_request: try method %s", method);
285 authenticated = m->userauth(authctxt); 290 authenticated = m->userauth(ssh);
286 } 291 }
287 userauth_finish(authctxt, authenticated, method, NULL); 292 userauth_finish(ssh, authenticated, method, NULL);
288 293
289 free(service); 294 free(service);
290 free(user); 295 free(user);
@@ -293,10 +298,10 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
293} 298}
294 299
295void 300void
296userauth_finish(Authctxt *authctxt, int authenticated, const char *method, 301userauth_finish(struct ssh *ssh, int authenticated, const char *method,
297 const char *submethod) 302 const char *submethod)
298{ 303{
299 struct ssh *ssh = active_state; /* XXX */ 304 Authctxt *authctxt = ssh->authctxt;
300 char *methods; 305 char *methods;
301 int partial = 0; 306 int partial = 0;
302 307
@@ -325,6 +330,10 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
325 /* Log before sending the reply */ 330 /* Log before sending the reply */
326 auth_log(authctxt, authenticated, partial, method, submethod); 331 auth_log(authctxt, authenticated, partial, method, submethod);
327 332
333 /* Update information exposed to session */
334 if (authenticated || partial)
335 auth2_update_session_info(authctxt, method, submethod);
336
328 if (authctxt->postponed) 337 if (authctxt->postponed)
329 return; 338 return;
330 339
@@ -352,7 +361,7 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
352 361
353 if (authenticated == 1) { 362 if (authenticated == 1) {
354 /* turn off userauth */ 363 /* turn off userauth */
355 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore); 364 ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
356 packet_start(SSH2_MSG_USERAUTH_SUCCESS); 365 packet_start(SSH2_MSG_USERAUTH_SUCCESS);
357 packet_send(); 366 packet_send();
358 packet_write_wait(); 367 packet_write_wait();
@@ -622,4 +631,128 @@ auth2_update_methods_lists(Authctxt *authctxt, const char *method,
622 return 0; 631 return 0;
623} 632}
624 633
634/* Reset method-specific information */
635void auth2_authctxt_reset_info(Authctxt *authctxt)
636{
637 sshkey_free(authctxt->auth_method_key);
638 free(authctxt->auth_method_info);
639 authctxt->auth_method_key = NULL;
640 authctxt->auth_method_info = NULL;
641}
642
643/* Record auth method-specific information for logs */
644void
645auth2_record_info(Authctxt *authctxt, const char *fmt, ...)
646{
647 va_list ap;
648 int i;
649
650 free(authctxt->auth_method_info);
651 authctxt->auth_method_info = NULL;
652
653 va_start(ap, fmt);
654 i = vasprintf(&authctxt->auth_method_info, fmt, ap);
655 va_end(ap);
656
657 if (i < 0 || authctxt->auth_method_info == NULL)
658 fatal("%s: vasprintf failed", __func__);
659}
660
661/*
662 * Records a public key used in authentication. This is used for logging
663 * and to ensure that the same key is not subsequently accepted again for
664 * multiple authentication.
665 */
666void
667auth2_record_key(Authctxt *authctxt, int authenticated,
668 const struct sshkey *key)
669{
670 struct sshkey **tmp, *dup;
671 int r;
672
673 if ((r = sshkey_demote(key, &dup)) != 0)
674 fatal("%s: copy key: %s", __func__, ssh_err(r));
675 sshkey_free(authctxt->auth_method_key);
676 authctxt->auth_method_key = dup;
677
678 if (!authenticated)
679 return;
680
681 /* If authenticated, make sure we don't accept this key again */
682 if ((r = sshkey_demote(key, &dup)) != 0)
683 fatal("%s: copy key: %s", __func__, ssh_err(r));
684 if (authctxt->nprev_keys >= INT_MAX ||
685 (tmp = recallocarray(authctxt->prev_keys, authctxt->nprev_keys,
686 authctxt->nprev_keys + 1, sizeof(*authctxt->prev_keys))) == NULL)
687 fatal("%s: reallocarray failed", __func__);
688 authctxt->prev_keys = tmp;
689 authctxt->prev_keys[authctxt->nprev_keys] = dup;
690 authctxt->nprev_keys++;
691
692}
693
694/* Checks whether a key has already been previously used for authentication */
695int
696auth2_key_already_used(Authctxt *authctxt, const struct sshkey *key)
697{
698 u_int i;
699 char *fp;
700
701 for (i = 0; i < authctxt->nprev_keys; i++) {
702 if (sshkey_equal_public(key, authctxt->prev_keys[i])) {
703 fp = sshkey_fingerprint(authctxt->prev_keys[i],
704 options.fingerprint_hash, SSH_FP_DEFAULT);
705 debug3("%s: key already used: %s %s", __func__,
706 sshkey_type(authctxt->prev_keys[i]),
707 fp == NULL ? "UNKNOWN" : fp);
708 free(fp);
709 return 1;
710 }
711 }
712 return 0;
713}
714
715/*
716 * Updates authctxt->session_info with details of authentication. Should be
717 * whenever an authentication method succeeds.
718 */
719void
720auth2_update_session_info(Authctxt *authctxt, const char *method,
721 const char *submethod)
722{
723 int r;
724
725 if (authctxt->session_info == NULL) {
726 if ((authctxt->session_info = sshbuf_new()) == NULL)
727 fatal("%s: sshbuf_new", __func__);
728 }
729
730 /* Append method[/submethod] */
731 if ((r = sshbuf_putf(authctxt->session_info, "%s%s%s",
732 method, submethod == NULL ? "" : "/",
733 submethod == NULL ? "" : submethod)) != 0)
734 fatal("%s: append method: %s", __func__, ssh_err(r));
735
736 /* Append key if present */
737 if (authctxt->auth_method_key != NULL) {
738 if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 ||
739 (r = sshkey_format_text(authctxt->auth_method_key,
740 authctxt->session_info)) != 0)
741 fatal("%s: append key: %s", __func__, ssh_err(r));
742 }
743
744 if (authctxt->auth_method_info != NULL) {
745 /* Ensure no ambiguity here */
746 if (strchr(authctxt->auth_method_info, '\n') != NULL)
747 fatal("%s: auth_method_info contains \\n", __func__);
748 if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 ||
749 (r = sshbuf_putf(authctxt->session_info, "%s",
750 authctxt->auth_method_info)) != 0) {
751 fatal("%s: append method info: %s",
752 __func__, ssh_err(r));
753 }
754 }
755 if ((r = sshbuf_put_u8(authctxt->session_info, '\n')) != 0)
756 fatal("%s: append: %s", __func__, ssh_err(r));
757}
625 758