diff options
Diffstat (limited to 'auth2-pubkey.c')
-rw-r--r-- | auth2-pubkey.c | 82 |
1 files changed, 67 insertions, 15 deletions
diff --git a/auth2-pubkey.c b/auth2-pubkey.c index f78b046b8..0bda5c9dd 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth2-pubkey.c,v 1.41 2014/07/15 15:54:14 millert Exp $ */ | 1 | /* $OpenBSD: auth2-pubkey.c,v 1.47 2015/02/17 00:14:05 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -41,6 +41,7 @@ | |||
41 | #include <string.h> | 41 | #include <string.h> |
42 | #include <time.h> | 42 | #include <time.h> |
43 | #include <unistd.h> | 43 | #include <unistd.h> |
44 | #include <limits.h> | ||
44 | 45 | ||
45 | #include "xmalloc.h" | 46 | #include "xmalloc.h" |
46 | #include "ssh.h" | 47 | #include "ssh.h" |
@@ -122,6 +123,17 @@ userauth_pubkey(Authctxt *authctxt) | |||
122 | "signature scheme"); | 123 | "signature scheme"); |
123 | goto done; | 124 | goto done; |
124 | } | 125 | } |
126 | if (auth2_userkey_already_used(authctxt, key)) { | ||
127 | logit("refusing previously-used %s key", key_type(key)); | ||
128 | goto done; | ||
129 | } | ||
130 | if (match_pattern_list(sshkey_ssh_name(key), options.pubkey_key_types, | ||
131 | strlen(options.pubkey_key_types), 0) != 1) { | ||
132 | logit("%s: key type %s not in PubkeyAcceptedKeyTypes", | ||
133 | __func__, sshkey_ssh_name(key)); | ||
134 | goto done; | ||
135 | } | ||
136 | |||
125 | if (have_sig) { | 137 | if (have_sig) { |
126 | sig = packet_get_string(&slen); | 138 | sig = packet_get_string(&slen); |
127 | packet_check_eom(); | 139 | packet_check_eom(); |
@@ -159,8 +171,12 @@ userauth_pubkey(Authctxt *authctxt) | |||
159 | authenticated = 0; | 171 | authenticated = 0; |
160 | if (PRIVSEP(user_key_allowed(authctxt->pw, key)) && | 172 | if (PRIVSEP(user_key_allowed(authctxt->pw, key)) && |
161 | PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), | 173 | PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), |
162 | buffer_len(&b))) == 1) | 174 | buffer_len(&b))) == 1) { |
163 | authenticated = 1; | 175 | authenticated = 1; |
176 | /* Record the successful key to prevent reuse */ | ||
177 | auth2_record_userkey(authctxt, key); | ||
178 | key = NULL; /* Don't free below */ | ||
179 | } | ||
164 | buffer_free(&b); | 180 | buffer_free(&b); |
165 | free(sig); | 181 | free(sig); |
166 | } else { | 182 | } else { |
@@ -212,17 +228,20 @@ pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...) | |||
212 | } | 228 | } |
213 | 229 | ||
214 | if (key_is_cert(key)) { | 230 | if (key_is_cert(key)) { |
215 | fp = key_fingerprint(key->cert->signature_key, | 231 | fp = sshkey_fingerprint(key->cert->signature_key, |
216 | SSH_FP_MD5, SSH_FP_HEX); | 232 | options.fingerprint_hash, SSH_FP_DEFAULT); |
217 | auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s", | 233 | auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s", |
218 | key_type(key), key->cert->key_id, | 234 | key_type(key), key->cert->key_id, |
219 | (unsigned long long)key->cert->serial, | 235 | (unsigned long long)key->cert->serial, |
220 | key_type(key->cert->signature_key), fp, | 236 | key_type(key->cert->signature_key), |
237 | fp == NULL ? "(null)" : fp, | ||
221 | extra == NULL ? "" : ", ", extra == NULL ? "" : extra); | 238 | extra == NULL ? "" : ", ", extra == NULL ? "" : extra); |
222 | free(fp); | 239 | free(fp); |
223 | } else { | 240 | } else { |
224 | fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); | 241 | fp = sshkey_fingerprint(key, options.fingerprint_hash, |
225 | auth_info(authctxt, "%s %s%s%s", key_type(key), fp, | 242 | SSH_FP_DEFAULT); |
243 | auth_info(authctxt, "%s %s%s%s", key_type(key), | ||
244 | fp == NULL ? "(null)" : fp, | ||
226 | extra == NULL ? "" : ", ", extra == NULL ? "" : extra); | 245 | extra == NULL ? "" : ", ", extra == NULL ? "" : extra); |
227 | free(fp); | 246 | free(fp); |
228 | } | 247 | } |
@@ -367,8 +386,9 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) | |||
367 | continue; | 386 | continue; |
368 | if (!key_is_cert_authority) | 387 | if (!key_is_cert_authority) |
369 | continue; | 388 | continue; |
370 | fp = key_fingerprint(found, SSH_FP_MD5, | 389 | if ((fp = sshkey_fingerprint(found, |
371 | SSH_FP_HEX); | 390 | options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) |
391 | continue; | ||
372 | debug("matching CA found: file %s, line %lu, %s %s", | 392 | debug("matching CA found: file %s, line %lu, %s %s", |
373 | file, linenum, key_type(found), fp); | 393 | file, linenum, key_type(found), fp); |
374 | /* | 394 | /* |
@@ -407,11 +427,13 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) | |||
407 | continue; | 427 | continue; |
408 | if (key_is_cert_authority) | 428 | if (key_is_cert_authority) |
409 | continue; | 429 | continue; |
410 | found_key = 1; | 430 | if ((fp = sshkey_fingerprint(found, |
411 | fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); | 431 | options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) |
432 | continue; | ||
412 | debug("matching key found: file %s, line %lu %s %s", | 433 | debug("matching key found: file %s, line %lu %s %s", |
413 | file, linenum, key_type(found), fp); | 434 | file, linenum, key_type(found), fp); |
414 | free(fp); | 435 | free(fp); |
436 | found_key = 1; | ||
415 | break; | 437 | break; |
416 | } | 438 | } |
417 | } | 439 | } |
@@ -433,11 +455,12 @@ user_cert_trusted_ca(struct passwd *pw, Key *key) | |||
433 | if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL) | 455 | if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL) |
434 | return 0; | 456 | return 0; |
435 | 457 | ||
436 | ca_fp = key_fingerprint(key->cert->signature_key, | 458 | if ((ca_fp = sshkey_fingerprint(key->cert->signature_key, |
437 | SSH_FP_MD5, SSH_FP_HEX); | 459 | options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) |
460 | return 0; | ||
438 | 461 | ||
439 | if (key_in_file(key->cert->signature_key, | 462 | if (sshkey_in_file(key->cert->signature_key, |
440 | options.trusted_user_ca_keys, 1) != 1) { | 463 | options.trusted_user_ca_keys, 1, 0) != 0) { |
441 | debug2("%s: CA %s %s is not listed in %s", __func__, | 464 | debug2("%s: CA %s %s is not listed in %s", __func__, |
442 | key_type(key->cert->signature_key), ca_fp, | 465 | key_type(key->cert->signature_key), ca_fp, |
443 | options.trusted_user_ca_keys); | 466 | options.trusted_user_ca_keys); |
@@ -683,6 +706,35 @@ user_key_allowed(struct passwd *pw, Key *key) | |||
683 | return success; | 706 | return success; |
684 | } | 707 | } |
685 | 708 | ||
709 | /* Records a public key in the list of previously-successful keys */ | ||
710 | void | ||
711 | auth2_record_userkey(Authctxt *authctxt, struct sshkey *key) | ||
712 | { | ||
713 | struct sshkey **tmp; | ||
714 | |||
715 | if (authctxt->nprev_userkeys >= INT_MAX || | ||
716 | (tmp = reallocarray(authctxt->prev_userkeys, | ||
717 | authctxt->nprev_userkeys + 1, sizeof(*tmp))) == NULL) | ||
718 | fatal("%s: reallocarray failed", __func__); | ||
719 | authctxt->prev_userkeys = tmp; | ||
720 | authctxt->prev_userkeys[authctxt->nprev_userkeys] = key; | ||
721 | authctxt->nprev_userkeys++; | ||
722 | } | ||
723 | |||
724 | /* Checks whether a key has already been used successfully for authentication */ | ||
725 | int | ||
726 | auth2_userkey_already_used(Authctxt *authctxt, struct sshkey *key) | ||
727 | { | ||
728 | u_int i; | ||
729 | |||
730 | for (i = 0; i < authctxt->nprev_userkeys; i++) { | ||
731 | if (sshkey_equal_public(key, authctxt->prev_userkeys[i])) { | ||
732 | return 1; | ||
733 | } | ||
734 | } | ||
735 | return 0; | ||
736 | } | ||
737 | |||
686 | Authmethod method_pubkey = { | 738 | Authmethod method_pubkey = { |
687 | "publickey", | 739 | "publickey", |
688 | userauth_pubkey, | 740 | userauth_pubkey, |