summaryrefslogtreecommitdiff
path: root/auth2-pubkey.c
diff options
context:
space:
mode:
Diffstat (limited to 'auth2-pubkey.c')
-rw-r--r--auth2-pubkey.c82
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 */
710void
711auth2_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 */
725int
726auth2_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
686Authmethod method_pubkey = { 738Authmethod method_pubkey = {
687 "publickey", 739 "publickey",
688 userauth_pubkey, 740 userauth_pubkey,