1 /* $OpenBSD: authfile.c,v 1.92 2011/06/14 22:49:18 markus Exp $ */
3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
6 * This file contains functions for reading and writing identity files, and
7 * for reading the passphrase from the user.
9 * As far as I am concerned, the code I have written for this software
10 * can be used freely for any purpose. Any derived versions of this
11 * software must be clearly marked as such, and if the derived work is
12 * incompatible with the protocol description in the RFC file, it must be
13 * called by a name other than "ssh" or "Secure Shell".
16 * Copyright (c) 2000 Markus Friedl. All rights reserved.
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
21 * 1. Redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in the
25 * documentation and/or other materials provided with the distribution.
27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
28 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
29 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
31 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
32 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 #include <sys/types.h>
43 #include <sys/param.h>
46 #include <openssl/err.h>
47 #include <openssl/evp.h>
48 #include <openssl/pem.h>
50 /* compatibility with old or broken OpenSSL versions */
51 #include "openbsd-compat/openssl-compat.h"
71 #include "pathnames.h"
73 #define MAX_KEY_FILE_SIZE (1024 * 1024)
75 /* Version identification string for SSH v1 identity files. */
76 static const char authfile_id_string
[] =
77 "SSH PRIVATE KEY FILE FORMAT 1.1\n";
80 * Serialises the authentication (private) key to a blob, encrypting it with
81 * passphrase. The identification of the blob (lowest 64 bits of n) will
82 * precede the key to provide identification of the key without needing a
86 key_private_rsa1_to_blob(Key
*key
, Buffer
*blob
, const char *passphrase
,
89 Buffer buffer
, encrypted
;
92 CipherContext ciphercontext
;
97 * If the passphrase is empty, use SSH_CIPHER_NONE to ease converting
98 * to another cipher; otherwise use SSH_AUTHFILE_CIPHER.
100 cipher_num
= (strcmp(passphrase
, "") == 0) ?
101 SSH_CIPHER_NONE
: SSH_AUTHFILE_CIPHER
;
102 if ((cipher
= cipher_by_number(cipher_num
)) == NULL
)
103 fatal("save_private_key_rsa: bad cipher");
105 /* This buffer is used to built the secret part of the private key. */
106 buffer_init(&buffer
);
108 /* Put checkbytes for checking passphrase validity. */
111 buf
[1] = (rnd
>> 8) & 0xff;
114 buffer_append(&buffer
, buf
, 4);
117 * Store the private key (n and e will not be stored because they
118 * will be stored in plain text, and storing them also in encrypted
119 * format would just give known plaintext).
121 buffer_put_bignum(&buffer
, key
->rsa
->d
);
122 buffer_put_bignum(&buffer
, key
->rsa
->iqmp
);
123 buffer_put_bignum(&buffer
, key
->rsa
->q
); /* reverse from SSL p */
124 buffer_put_bignum(&buffer
, key
->rsa
->p
); /* reverse from SSL q */
126 /* Pad the part to be encrypted until its size is a multiple of 8. */
127 while (buffer_len(&buffer
) % 8 != 0)
128 buffer_put_char(&buffer
, 0);
130 /* This buffer will be used to contain the data in the file. */
131 buffer_init(&encrypted
);
133 /* First store keyfile id string. */
134 for (i
= 0; authfile_id_string
[i
]; i
++)
135 buffer_put_char(&encrypted
, authfile_id_string
[i
]);
136 buffer_put_char(&encrypted
, 0);
138 /* Store cipher type. */
139 buffer_put_char(&encrypted
, cipher_num
);
140 buffer_put_int(&encrypted
, 0); /* For future extension */
142 /* Store public key. This will be in plain text. */
143 buffer_put_int(&encrypted
, BN_num_bits(key
->rsa
->n
));
144 buffer_put_bignum(&encrypted
, key
->rsa
->n
);
145 buffer_put_bignum(&encrypted
, key
->rsa
->e
);
146 buffer_put_cstring(&encrypted
, comment
);
148 /* Allocate space for the private part of the key in the buffer. */
149 cp
= buffer_append_space(&encrypted
, buffer_len(&buffer
));
151 cipher_set_key_string(&ciphercontext
, cipher
, passphrase
,
153 cipher_crypt(&ciphercontext
, cp
,
154 buffer_ptr(&buffer
), buffer_len(&buffer
));
155 cipher_cleanup(&ciphercontext
);
156 memset(&ciphercontext
, 0, sizeof(ciphercontext
));
158 /* Destroy temporary data. */
159 memset(buf
, 0, sizeof(buf
));
160 buffer_free(&buffer
);
162 buffer_append(blob
, buffer_ptr(&encrypted
), buffer_len(&encrypted
));
163 buffer_free(&encrypted
);
168 /* convert SSH v2 key in OpenSSL PEM format */
170 key_private_pem_to_blob(Key
*key
, Buffer
*blob
, const char *_passphrase
,
174 int blen
, len
= strlen(_passphrase
);
175 u_char
*passphrase
= (len
> 0) ? (u_char
*)_passphrase
: NULL
;
176 #if (OPENSSL_VERSION_NUMBER < 0x00907000L)
177 const EVP_CIPHER
*cipher
= (len
> 0) ? EVP_des_ede3_cbc() : NULL
;
179 const EVP_CIPHER
*cipher
= (len
> 0) ? EVP_aes_128_cbc() : NULL
;
184 if (len
> 0 && len
<= 4) {
185 error("passphrase too short: have %d bytes, need > 4", len
);
188 if ((bio
= BIO_new(BIO_s_mem())) == NULL
) {
189 error("%s: BIO_new failed", __func__
);
194 success
= PEM_write_bio_DSAPrivateKey(bio
, key
->dsa
,
195 cipher
, passphrase
, len
, NULL
, NULL
);
197 #ifdef OPENSSL_HAS_ECC
199 success
= PEM_write_bio_ECPrivateKey(bio
, key
->ecdsa
,
200 cipher
, passphrase
, len
, NULL
, NULL
);
204 success
= PEM_write_bio_RSAPrivateKey(bio
, key
->rsa
,
205 cipher
, passphrase
, len
, NULL
, NULL
);
209 if ((blen
= BIO_get_mem_data(bio
, &bptr
)) <= 0)
212 buffer_append(blob
, bptr
, blen
);
218 /* Save a key blob to a file */
220 key_save_private_blob(Buffer
*keybuf
, const char *filename
)
224 if ((fd
= open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
, 0600)) < 0) {
225 error("open %s failed: %s.", filename
, strerror(errno
));
228 if (atomicio(vwrite
, fd
, buffer_ptr(keybuf
),
229 buffer_len(keybuf
)) != buffer_len(keybuf
)) {
230 error("write to key file %s failed: %s", filename
,
240 /* Serialise "key" to buffer "blob" */
242 key_private_to_blob(Key
*key
, Buffer
*blob
, const char *passphrase
,
247 return key_private_rsa1_to_blob(key
, blob
, passphrase
, comment
);
251 return key_private_pem_to_blob(key
, blob
, passphrase
, comment
);
253 error("%s: cannot save key type %d", __func__
, key
->type
);
259 key_save_private(Key
*key
, const char *filename
, const char *passphrase
,
265 buffer_init(&keyblob
);
266 if (!key_private_to_blob(key
, &keyblob
, passphrase
, comment
))
268 if (!key_save_private_blob(&keyblob
, filename
))
272 buffer_free(&keyblob
);
277 * Parse the public, unencrypted portion of a RSA1 key.
280 key_parse_public_rsa1(Buffer
*blob
, char **commentp
)
285 /* Check that it is at least big enough to contain the ID string. */
286 if (buffer_len(blob
) < sizeof(authfile_id_string
)) {
287 debug3("Truncated RSA1 identifier");
292 * Make sure it begins with the id string. Consume the id string
295 if (memcmp(buffer_ptr(blob
), authfile_id_string
,
296 sizeof(authfile_id_string
)) != 0) {
297 debug3("Incorrect RSA1 identifier");
301 buffer_append(©
, buffer_ptr(blob
), buffer_len(blob
));
302 buffer_consume(©
, sizeof(authfile_id_string
));
304 /* Skip cipher type and reserved data. */
305 (void) buffer_get_char(©
); /* cipher type */
306 (void) buffer_get_int(©
); /* reserved */
308 /* Read the public key from the buffer. */
309 (void) buffer_get_int(©
);
310 pub
= key_new(KEY_RSA1
);
311 buffer_get_bignum(©
, pub
->rsa
->n
);
312 buffer_get_bignum(©
, pub
->rsa
->e
);
314 *commentp
= buffer_get_string(©
, NULL
);
315 /* The encrypted private part is not parsed by this function. */
321 /* Load a key from a fd into a buffer */
323 key_load_file(int fd
, const char *filename
, Buffer
*blob
)
329 if (fstat(fd
, &st
) < 0) {
330 error("%s: fstat of key file %.200s%sfailed: %.100s", __func__
,
331 filename
== NULL
? "" : filename
,
332 filename
== NULL
? "" : " ",
336 if ((st
.st_mode
& (S_IFSOCK
|S_IFCHR
|S_IFIFO
)) == 0 &&
337 st
.st_size
> MAX_KEY_FILE_SIZE
) {
339 error("%s: key file %.200s%stoo large", __func__
,
340 filename
== NULL
? "" : filename
,
341 filename
== NULL
? "" : " ");
346 if ((len
= atomicio(read
, fd
, buf
, sizeof(buf
))) == 0) {
349 debug("%s: read from key file %.200s%sfailed: %.100s",
350 __func__
, filename
== NULL
? "" : filename
,
351 filename
== NULL
? "" : " ", strerror(errno
));
353 bzero(buf
, sizeof(buf
));
356 buffer_append(blob
, buf
, len
);
357 if (buffer_len(blob
) > MAX_KEY_FILE_SIZE
) {
359 bzero(buf
, sizeof(buf
));
363 bzero(buf
, sizeof(buf
));
364 if ((st
.st_mode
& (S_IFSOCK
|S_IFCHR
|S_IFIFO
)) == 0 &&
365 st
.st_size
!= buffer_len(blob
)) {
366 debug("%s: key file %.200s%schanged size while reading",
367 __func__
, filename
== NULL
? "" : filename
,
368 filename
== NULL
? "" : " ");
377 * Loads the public part of the ssh v1 key file. Returns NULL if an error was
378 * encountered (the file does not exist or is not readable), and the key
382 key_load_public_rsa1(int fd
, const char *filename
, char **commentp
)
387 buffer_init(&buffer
);
388 if (!key_load_file(fd
, filename
, &buffer
)) {
389 buffer_free(&buffer
);
393 pub
= key_parse_public_rsa1(&buffer
, commentp
);
395 debug3("Could not load \"%s\" as a RSA1 public key", filename
);
396 buffer_free(&buffer
);
400 /* load public key from private-key file, works only for SSH v1 */
402 key_load_public_type(int type
, const char *filename
, char **commentp
)
407 if (type
== KEY_RSA1
) {
408 fd
= open(filename
, O_RDONLY
);
411 pub
= key_load_public_rsa1(fd
, filename
, commentp
);
419 key_parse_private_rsa1(Buffer
*blob
, const char *passphrase
, char **commentp
)
421 int check1
, check2
, cipher_type
;
424 CipherContext ciphercontext
;
429 /* Check that it is at least big enough to contain the ID string. */
430 if (buffer_len(blob
) < sizeof(authfile_id_string
)) {
431 debug3("Truncated RSA1 identifier");
436 * Make sure it begins with the id string. Consume the id string
439 if (memcmp(buffer_ptr(blob
), authfile_id_string
,
440 sizeof(authfile_id_string
)) != 0) {
441 debug3("Incorrect RSA1 identifier");
445 buffer_append(©
, buffer_ptr(blob
), buffer_len(blob
));
446 buffer_consume(©
, sizeof(authfile_id_string
));
448 /* Read cipher type. */
449 cipher_type
= buffer_get_char(©
);
450 (void) buffer_get_int(©
); /* Reserved data. */
452 /* Read the public key from the buffer. */
453 (void) buffer_get_int(©
);
454 prv
= key_new_private(KEY_RSA1
);
456 buffer_get_bignum(©
, prv
->rsa
->n
);
457 buffer_get_bignum(©
, prv
->rsa
->e
);
459 *commentp
= buffer_get_string(©
, NULL
);
461 (void)buffer_get_string_ptr(©
, NULL
);
463 /* Check that it is a supported cipher. */
464 cipher
= cipher_by_number(cipher_type
);
465 if (cipher
== NULL
) {
466 debug("Unsupported RSA1 cipher %d", cipher_type
);
470 /* Initialize space for decrypted data. */
471 buffer_init(&decrypted
);
472 cp
= buffer_append_space(&decrypted
, buffer_len(©
));
474 /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
475 cipher_set_key_string(&ciphercontext
, cipher
, passphrase
,
477 cipher_crypt(&ciphercontext
, cp
,
478 buffer_ptr(©
), buffer_len(©
));
479 cipher_cleanup(&ciphercontext
);
480 memset(&ciphercontext
, 0, sizeof(ciphercontext
));
483 check1
= buffer_get_char(&decrypted
);
484 check2
= buffer_get_char(&decrypted
);
485 if (check1
!= buffer_get_char(&decrypted
) ||
486 check2
!= buffer_get_char(&decrypted
)) {
487 if (strcmp(passphrase
, "") != 0)
488 debug("Bad passphrase supplied for RSA1 key");
489 /* Bad passphrase. */
490 buffer_free(&decrypted
);
493 /* Read the rest of the private key. */
494 buffer_get_bignum(&decrypted
, prv
->rsa
->d
);
495 buffer_get_bignum(&decrypted
, prv
->rsa
->iqmp
); /* u */
496 /* in SSL and SSH v1 p and q are exchanged */
497 buffer_get_bignum(&decrypted
, prv
->rsa
->q
); /* p */
498 buffer_get_bignum(&decrypted
, prv
->rsa
->p
); /* q */
500 /* calculate p-1 and q-1 */
501 rsa_generate_additional_parameters(prv
->rsa
);
503 buffer_free(&decrypted
);
505 /* enable blinding */
506 if (RSA_blinding_on(prv
->rsa
, NULL
) != 1) {
507 error("%s: RSA_blinding_on failed", __func__
);
520 key_parse_private_pem(Buffer
*blob
, int type
, const char *passphrase
,
525 char *name
= "<no key>";
528 if ((bio
= BIO_new_mem_buf(buffer_ptr(blob
),
529 buffer_len(blob
))) == NULL
) {
530 error("%s: BIO_new_mem_buf failed", __func__
);
534 pk
= PEM_read_bio_PrivateKey(bio
, NULL
, NULL
, (char *)passphrase
);
537 debug("%s: PEM_read_PrivateKey failed", __func__
);
538 (void)ERR_get_error();
539 } else if (pk
->type
== EVP_PKEY_RSA
&&
540 (type
== KEY_UNSPEC
||type
==KEY_RSA
)) {
541 prv
= key_new(KEY_UNSPEC
);
542 prv
->rsa
= EVP_PKEY_get1_RSA(pk
);
544 name
= "rsa w/o comment";
546 RSA_print_fp(stderr
, prv
->rsa
, 8);
548 if (RSA_blinding_on(prv
->rsa
, NULL
) != 1) {
549 error("%s: RSA_blinding_on failed", __func__
);
553 } else if (pk
->type
== EVP_PKEY_DSA
&&
554 (type
== KEY_UNSPEC
||type
==KEY_DSA
)) {
555 prv
= key_new(KEY_UNSPEC
);
556 prv
->dsa
= EVP_PKEY_get1_DSA(pk
);
558 name
= "dsa w/o comment";
560 DSA_print_fp(stderr
, prv
->dsa
, 8);
562 #ifdef OPENSSL_HAS_ECC
563 } else if (pk
->type
== EVP_PKEY_EC
&&
564 (type
== KEY_UNSPEC
||type
==KEY_ECDSA
)) {
565 prv
= key_new(KEY_UNSPEC
);
566 prv
->ecdsa
= EVP_PKEY_get1_EC_KEY(pk
);
567 prv
->type
= KEY_ECDSA
;
568 if ((prv
->ecdsa_nid
= key_ecdsa_key_to_nid(prv
->ecdsa
)) == -1 ||
569 key_curve_nid_to_name(prv
->ecdsa_nid
) == NULL
||
570 key_ec_validate_public(EC_KEY_get0_group(prv
->ecdsa
),
571 EC_KEY_get0_public_key(prv
->ecdsa
)) != 0 ||
572 key_ec_validate_private(prv
->ecdsa
) != 0) {
573 error("%s: bad ECDSA key", __func__
);
577 name
= "ecdsa w/o comment";
579 if (prv
!= NULL
&& prv
->ecdsa
!= NULL
)
580 key_dump_ec_key(prv
->ecdsa
);
582 #endif /* OPENSSL_HAS_ECC */
584 error("%s: PEM_read_PrivateKey: mismatch or "
585 "unknown EVP_PKEY save_type %d", __func__
, pk
->save_type
);
589 if (prv
!= NULL
&& commentp
)
590 *commentp
= xstrdup(name
);
591 debug("read PEM private key done: type %s",
592 prv
? key_type(prv
) : "<unknown>");
597 key_load_private_pem(int fd
, int type
, const char *passphrase
,
603 buffer_init(&buffer
);
604 if (!key_load_file(fd
, NULL
, &buffer
)) {
605 buffer_free(&buffer
);
608 prv
= key_parse_private_pem(&buffer
, type
, passphrase
, commentp
);
609 buffer_free(&buffer
);
614 key_perm_ok(int fd
, const char *filename
)
618 if (fstat(fd
, &st
) < 0)
621 * if a key owned by the user is accessed, then we check the
622 * permissions of the file. if the key owned by a different user,
623 * then we don't care.
626 if (check_ntsec(filename
))
628 if ((st
.st_uid
== getuid()) && (st
.st_mode
& 077) != 0) {
629 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
630 error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @");
631 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
632 error("Permissions 0%3.3o for '%s' are too open.",
633 (u_int
)st
.st_mode
& 0777, filename
);
634 error("It is required that your private key files are NOT accessible by others.");
635 error("This private key will be ignored.");
642 key_parse_private_type(Buffer
*blob
, int type
, const char *passphrase
,
647 return key_parse_private_rsa1(blob
, passphrase
, commentp
);
652 return key_parse_private_pem(blob
, type
, passphrase
, commentp
);
654 error("%s: cannot parse key type %d", __func__
, type
);
661 key_load_private_type(int type
, const char *filename
, const char *passphrase
,
662 char **commentp
, int *perm_ok
)
668 fd
= open(filename
, O_RDONLY
);
670 debug("could not open key file '%s': %s", filename
,
676 if (!key_perm_ok(fd
, filename
)) {
679 error("bad permissions: ignore key: %s", filename
);
686 buffer_init(&buffer
);
687 if (!key_load_file(fd
, filename
, &buffer
)) {
688 buffer_free(&buffer
);
693 ret
= key_parse_private_type(&buffer
, type
, passphrase
, commentp
);
694 buffer_free(&buffer
);
699 key_parse_private(Buffer
*buffer
, const char *filename
,
700 const char *passphrase
, char **commentp
)
704 /* it's a SSH v1 key if the public key part is readable */
705 pub
= key_parse_public_rsa1(buffer
, commentp
);
707 prv
= key_parse_private_type(buffer
, KEY_UNSPEC
,
709 /* use the filename as a comment for PEM */
711 *commentp
= xstrdup(filename
);
714 /* key_parse_public_rsa1() has already loaded the comment */
715 prv
= key_parse_private_type(buffer
, KEY_RSA1
, passphrase
,
722 key_load_private(const char *filename
, const char *passphrase
,
729 fd
= open(filename
, O_RDONLY
);
731 debug("could not open key file '%s': %s", filename
,
735 if (!key_perm_ok(fd
, filename
)) {
736 error("bad permissions: ignore key: %s", filename
);
741 buffer_init(&buffer
);
742 if (!key_load_file(fd
, filename
, &buffer
)) {
743 buffer_free(&buffer
);
749 prv
= key_parse_private(&buffer
, filename
, passphrase
, commentp
);
750 buffer_free(&buffer
);
755 key_try_load_public(Key
*k
, const char *filename
, char **commentp
)
758 char line
[SSH_MAX_PUBKEY_BYTES
];
762 f
= fopen(filename
, "r");
764 while (read_keyfile_line(f
, filename
, line
, sizeof(line
),
773 /* Abort loading if this looks like a private key */
774 if (strncmp(cp
, "-----BEGIN", 10) == 0)
776 /* Skip leading whitespace. */
777 for (; *cp
&& (*cp
== ' ' || *cp
== '\t'); cp
++)
780 if (key_read(k
, &cp
) == 1) {
781 cp
[strcspn(cp
, "\r\n")] = '\0';
783 *commentp
= xstrdup(*cp
?
796 /* load public key from ssh v1 private or any pubkey file */
798 key_load_public(const char *filename
, char **commentp
)
801 char file
[MAXPATHLEN
];
803 /* try rsa1 private key */
804 pub
= key_load_public_type(KEY_RSA1
, filename
, commentp
);
808 /* try rsa1 public key */
809 pub
= key_new(KEY_RSA1
);
810 if (key_try_load_public(pub
, filename
, commentp
) == 1)
814 /* try ssh2 public key */
815 pub
= key_new(KEY_UNSPEC
);
816 if (key_try_load_public(pub
, filename
, commentp
) == 1)
818 if ((strlcpy(file
, filename
, sizeof file
) < sizeof(file
)) &&
819 (strlcat(file
, ".pub", sizeof file
) < sizeof(file
)) &&
820 (key_try_load_public(pub
, file
, commentp
) == 1))
827 blacklist_filename(const Key
*key
)
831 xasprintf(&name
, "%s.%s-%u",
832 _PATH_BLACKLIST
, key_type(key
), key_size(key
));
836 /* Scan a blacklist of known-vulnerable keys. */
838 blacklisted_key(Key
*key
)
840 char *blacklist_file
;
842 char *dgst_hex
= NULL
;
843 char *dgst_packed
= NULL
, *p
;
848 off_t start
, lower
, upper
;
851 blacklist_file
= blacklist_filename(key
);
852 debug("Checking blacklist file %s", blacklist_file
);
853 fd
= open(blacklist_file
, O_RDONLY
);
857 dgst_hex
= key_fingerprint(key
, SSH_FP_MD5
, SSH_FP_HEX
);
858 /* Remove all colons */
859 dgst_packed
= xcalloc(1, strlen(dgst_hex
) + 1);
860 for (i
= 0, p
= dgst_packed
; dgst_hex
[i
]; i
++)
861 if (dgst_hex
[i
] != ':')
863 /* Only compare least-significant 80 bits (to keep the blacklist
866 line_len
= strlen(dgst_packed
+ 12);
870 /* Skip leading comments */
876 r
= atomicio(read
, fd
, buf
, 256);
882 newline
= memchr(buf
, '\n', 256);
885 start
+= newline
+ 1 - buf
;
886 if (lseek(fd
, start
, SEEK_SET
) < 0)
890 /* Initialise binary search record numbers */
891 if (fstat(fd
, &st
) < 0)
894 upper
= (st
.st_size
- start
) / (line_len
+ 1);
896 while (lower
!= upper
) {
901 cur
= lower
+ (upper
- lower
) / 2;
903 /* Read this line and compare to digest; this is
904 * overflow-safe since cur < max(off_t) / (line_len + 1) */
905 if (lseek(fd
, start
+ cur
* (line_len
+ 1), SEEK_SET
) < 0)
907 if (atomicio(read
, fd
, buf
, line_len
) != line_len
)
909 cmp
= memcmp(buf
, dgst_packed
+ 12, line_len
);
914 } else if (cmp
> 0) {
919 debug("Found %s in blacklist", dgst_hex
);
932 xfree(blacklist_file
);
936 /* Load the certificate associated with the named private key */
938 key_load_cert(const char *filename
)
943 pub
= key_new(KEY_UNSPEC
);
944 xasprintf(&file
, "%s-cert.pub", filename
);
945 if (key_try_load_public(pub
, file
, NULL
) == 1) {
954 /* Load private key and certificate */
956 key_load_private_cert(int type
, const char *filename
, const char *passphrase
,
967 error("%s: unsupported key type", __func__
);
971 if ((key
= key_load_private_type(type
, filename
,
972 passphrase
, NULL
, perm_ok
)) == NULL
)
975 if ((pub
= key_load_cert(filename
)) == NULL
) {
980 /* Make sure the private key matches the certificate */
981 if (key_equal_public(key
, pub
) == 0) {
982 error("%s: certificate does not match private key %s",
984 } else if (key_to_certified(key
, key_cert_is_legacy(pub
)) != 0) {
985 error("%s: key_to_certified failed", __func__
);
987 key_cert_copy(pub
, key
);
998 * Returns 1 if the specified "key" is listed in the file "filename",
999 * 0 if the key is not listed or -1 on error.
1000 * If strict_type is set then the key type must match exactly,
1001 * otherwise a comparison that ignores certficiate data is performed.
1004 key_in_file(Key
*key
, const char *filename
, int strict_type
)
1007 char line
[SSH_MAX_PUBKEY_BYTES
];
1012 int (*key_compare
)(const Key
*, const Key
*) = strict_type
?
1013 key_equal
: key_equal_public
;
1015 if ((f
= fopen(filename
, "r")) == NULL
) {
1016 if (errno
== ENOENT
) {
1017 debug("%s: keyfile \"%s\" missing", __func__
, filename
);
1020 error("%s: could not open keyfile \"%s\": %s", __func__
,
1021 filename
, strerror(errno
));
1026 while (read_keyfile_line(f
, filename
, line
, sizeof(line
),
1030 /* Skip leading whitespace. */
1031 for (; *cp
&& (*cp
== ' ' || *cp
== '\t'); cp
++)
1034 /* Skip comments and empty lines */
1042 pub
= key_new(KEY_UNSPEC
);
1043 if (key_read(pub
, &cp
) != 1) {
1047 if (key_compare(key
, pub
)) {