diff options
author | djm@openbsd.org <djm@openbsd.org> | 2014-12-04 02:24:32 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2014-12-05 09:29:47 +1100 |
commit | 5e39a49930d885aac9c76af3129332b6e772cd75 (patch) | |
tree | 0d3613d35ba5478ff9f7889cc1912a70ee3b2e32 /authfile.c | |
parent | 74de254bb92c684cf53461da97f52d5ba34ded80 (diff) |
upstream commit
add RevokedHostKeys option for the client
Allow textfile or KRL-based revocation of hostkeys.
Diffstat (limited to 'authfile.c')
-rw-r--r-- | authfile.c | 58 |
1 files changed, 48 insertions, 10 deletions
diff --git a/authfile.c b/authfile.c index e93d86738..95877e159 100644 --- a/authfile.c +++ b/authfile.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: authfile.c,v 1.107 2014/06/24 01:13:21 djm Exp $ */ | 1 | /* $OpenBSD: authfile.c,v 1.108 2014/12/04 02:24:32 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -48,6 +48,7 @@ | |||
48 | #include "atomicio.h" | 48 | #include "atomicio.h" |
49 | #include "sshbuf.h" | 49 | #include "sshbuf.h" |
50 | #include "ssherr.h" | 50 | #include "ssherr.h" |
51 | #include "krl.h" | ||
51 | 52 | ||
52 | #define MAX_KEY_FILE_SIZE (1024 * 1024) | 53 | #define MAX_KEY_FILE_SIZE (1024 * 1024) |
53 | 54 | ||
@@ -494,11 +495,14 @@ sshkey_load_private_cert(int type, const char *filename, const char *passphrase, | |||
494 | /* | 495 | /* |
495 | * Returns success if the specified "key" is listed in the file "filename", | 496 | * Returns success if the specified "key" is listed in the file "filename", |
496 | * SSH_ERR_KEY_NOT_FOUND: if the key is not listed or another error. | 497 | * SSH_ERR_KEY_NOT_FOUND: if the key is not listed or another error. |
497 | * If strict_type is set then the key type must match exactly, | 498 | * If "strict_type" is set then the key type must match exactly, |
498 | * otherwise a comparison that ignores certficiate data is performed. | 499 | * otherwise a comparison that ignores certficiate data is performed. |
500 | * If "check_ca" is set and "key" is a certificate, then its CA key is | ||
501 | * also checked and sshkey_in_file() will return success if either is found. | ||
499 | */ | 502 | */ |
500 | int | 503 | int |
501 | sshkey_in_file(struct sshkey *key, const char *filename, int strict_type) | 504 | sshkey_in_file(struct sshkey *key, const char *filename, int strict_type, |
505 | int check_ca) | ||
502 | { | 506 | { |
503 | FILE *f; | 507 | FILE *f; |
504 | char line[SSH_MAX_PUBKEY_BYTES]; | 508 | char line[SSH_MAX_PUBKEY_BYTES]; |
@@ -509,12 +513,8 @@ sshkey_in_file(struct sshkey *key, const char *filename, int strict_type) | |||
509 | int (*sshkey_compare)(const struct sshkey *, const struct sshkey *) = | 513 | int (*sshkey_compare)(const struct sshkey *, const struct sshkey *) = |
510 | strict_type ? sshkey_equal : sshkey_equal_public; | 514 | strict_type ? sshkey_equal : sshkey_equal_public; |
511 | 515 | ||
512 | if ((f = fopen(filename, "r")) == NULL) { | 516 | if ((f = fopen(filename, "r")) == NULL) |
513 | if (errno == ENOENT) | 517 | return SSH_ERR_SYSTEM_ERROR; |
514 | return SSH_ERR_KEY_NOT_FOUND; | ||
515 | else | ||
516 | return SSH_ERR_SYSTEM_ERROR; | ||
517 | } | ||
518 | 518 | ||
519 | while (read_keyfile_line(f, filename, line, sizeof(line), | 519 | while (read_keyfile_line(f, filename, line, sizeof(line), |
520 | &linenum) != -1) { | 520 | &linenum) != -1) { |
@@ -538,7 +538,9 @@ sshkey_in_file(struct sshkey *key, const char *filename, int strict_type) | |||
538 | } | 538 | } |
539 | if ((r = sshkey_read(pub, &cp)) != 0) | 539 | if ((r = sshkey_read(pub, &cp)) != 0) |
540 | goto out; | 540 | goto out; |
541 | if (sshkey_compare(key, pub)) { | 541 | if (sshkey_compare(key, pub) || |
542 | (check_ca && sshkey_is_cert(key) && | ||
543 | sshkey_compare(key->cert->signature_key, pub))) { | ||
542 | r = 0; | 544 | r = 0; |
543 | goto out; | 545 | goto out; |
544 | } | 546 | } |
@@ -553,3 +555,39 @@ sshkey_in_file(struct sshkey *key, const char *filename, int strict_type) | |||
553 | return r; | 555 | return r; |
554 | } | 556 | } |
555 | 557 | ||
558 | /* | ||
559 | * Checks whether the specified key is revoked, returning 0 if not, | ||
560 | * SSH_ERR_KEY_REVOKED if it is or another error code if something | ||
561 | * unexpected happened. | ||
562 | * This will check both the key and, if it is a certificate, its CA key too. | ||
563 | * "revoked_keys_file" may be a KRL or a one-per-line list of public keys. | ||
564 | */ | ||
565 | int | ||
566 | sshkey_check_revoked(struct sshkey *key, const char *revoked_keys_file) | ||
567 | { | ||
568 | int r; | ||
569 | |||
570 | #ifdef WITH_OPENSSL | ||
571 | r = ssh_krl_file_contains_key(revoked_keys_file, key); | ||
572 | /* If this was not a KRL to begin with then continue below */ | ||
573 | if (r != SSH_ERR_KRL_BAD_MAGIC) | ||
574 | return r; | ||
575 | #endif | ||
576 | |||
577 | /* | ||
578 | * If the file is not a KRL or we can't handle KRLs then attempt to | ||
579 | * parse the file as a flat list of keys. | ||
580 | */ | ||
581 | switch ((r = sshkey_in_file(key, revoked_keys_file, 0, 1))) { | ||
582 | case 0: | ||
583 | /* Key found => revoked */ | ||
584 | return SSH_ERR_KEY_REVOKED; | ||
585 | case SSH_ERR_KEY_NOT_FOUND: | ||
586 | /* Key not found => not revoked */ | ||
587 | return 0; | ||
588 | default: | ||
589 | /* Some other error occurred */ | ||
590 | return r; | ||
591 | } | ||
592 | } | ||
593 | |||