Annotation of src/usr.bin/ssh/authfile.c, Revision 1.123
1.123 ! deraadt 1: /* $OpenBSD: authfile.c,v 1.122 2016/11/25 23:24:45 djm Exp $ */
1.1 deraadt 2: /*
1.99 markus 3: * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved.
1.19 deraadt 4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: *
14: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.9 deraadt 24: */
1.1 deraadt 25:
1.62 stevesk 26:
27: #include <sys/types.h>
28: #include <sys/stat.h>
1.76 deraadt 29: #include <sys/uio.h>
1.1 deraadt 30:
1.69 stevesk 31: #include <errno.h>
1.68 stevesk 32: #include <fcntl.h>
1.74 stevesk 33: #include <stdio.h>
1.73 stevesk 34: #include <stdlib.h>
1.71 stevesk 35: #include <string.h>
1.70 stevesk 36: #include <unistd.h>
1.110 deraadt 37: #include <limits.h>
1.15 markus 38:
1.25 markus 39: #include "cipher.h"
1.1 deraadt 40: #include "ssh.h"
1.25 markus 41: #include "log.h"
1.27 itojun 42: #include "authfile.h"
1.44 markus 43: #include "rsa.h"
1.60 dtucker 44: #include "misc.h"
1.61 djm 45: #include "atomicio.h"
1.116 markus 46: #include "sshkey.h"
1.107 djm 47: #include "sshbuf.h"
48: #include "ssherr.h"
1.108 djm 49: #include "krl.h"
1.1 deraadt 50:
1.88 djm 51: #define MAX_KEY_FILE_SIZE (1024 * 1024)
52:
1.86 djm 53: /* Save a key blob to a file */
54: static int
1.107 djm 55: sshkey_save_private_blob(struct sshbuf *keybuf, const char *filename)
1.86 djm 56: {
1.107 djm 57: int fd, oerrno;
1.86 djm 58:
1.107 djm 59: if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0)
60: return SSH_ERR_SYSTEM_ERROR;
61: if (atomicio(vwrite, fd, (u_char *)sshbuf_ptr(keybuf),
62: sshbuf_len(keybuf)) != sshbuf_len(keybuf)) {
63: oerrno = errno;
1.86 djm 64: close(fd);
65: unlink(filename);
1.107 djm 66: errno = oerrno;
67: return SSH_ERR_SYSTEM_ERROR;
1.86 djm 68: }
69: close(fd);
1.107 djm 70: return 0;
1.86 djm 71: }
72:
73: int
1.107 djm 74: sshkey_save_private(struct sshkey *key, const char *filename,
75: const char *passphrase, const char *comment,
76: int force_new_format, const char *new_format_cipher, int new_format_rounds)
1.86 djm 77: {
1.107 djm 78: struct sshbuf *keyblob = NULL;
79: int r;
1.86 djm 80:
1.107 djm 81: if ((keyblob = sshbuf_new()) == NULL)
82: return SSH_ERR_ALLOC_FAIL;
83: if ((r = sshkey_private_to_fileblob(key, keyblob, passphrase, comment,
84: force_new_format, new_format_cipher, new_format_rounds)) != 0)
1.86 djm 85: goto out;
1.107 djm 86: if ((r = sshkey_save_private_blob(keyblob, filename)) != 0)
1.86 djm 87: goto out;
1.107 djm 88: r = 0;
1.86 djm 89: out:
1.107 djm 90: sshbuf_free(keyblob);
91: return r;
1.86 djm 92: }
93:
1.88 djm 94: /* Load a key from a fd into a buffer */
95: int
1.109 djm 96: sshkey_load_file(int fd, struct sshbuf *blob)
1.86 djm 97: {
1.88 djm 98: u_char buf[1024];
1.86 djm 99: size_t len;
1.51 fgsch 100: struct stat st;
1.122 djm 101: int r, dontmax = 0;
1.8 markus 102:
1.107 djm 103: if (fstat(fd, &st) < 0)
104: return SSH_ERR_SYSTEM_ERROR;
1.88 djm 105: if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
1.107 djm 106: st.st_size > MAX_KEY_FILE_SIZE)
107: return SSH_ERR_INVALID_FORMAT;
1.122 djm 108: /*
109: * Pre-allocate the buffer used for the key contents and clamp its
110: * maximum size. This ensures that key contents are never leaked via
111: * implicit realloc() in the sshbuf code.
112: */
113: if ((st.st_mode & S_IFREG) == 0 || st.st_size <= 0) {
1.123 ! deraadt 114: st.st_size = 64*1024; /* 64k ought to be enough for anybody. :) */
1.122 djm 115: dontmax = 1;
116: }
117: if ((r = sshbuf_allocate(blob, st.st_size)) != 0 ||
118: (dontmax && (r = sshbuf_set_max_size(blob, st.st_size)) != 0))
119: return r;
1.88 djm 120: for (;;) {
121: if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) {
122: if (errno == EPIPE)
123: break;
1.107 djm 124: r = SSH_ERR_SYSTEM_ERROR;
125: goto out;
1.88 djm 126: }
1.107 djm 127: if ((r = sshbuf_put(blob, buf, len)) != 0)
128: goto out;
129: if (sshbuf_len(blob) > MAX_KEY_FILE_SIZE) {
130: r = SSH_ERR_INVALID_FORMAT;
131: goto out;
1.88 djm 132: }
133: }
134: if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
1.107 djm 135: st.st_size != (off_t)sshbuf_len(blob)) {
136: r = SSH_ERR_FILE_CHANGED;
137: goto out;
1.8 markus 138: }
1.107 djm 139: r = 0;
1.88 djm 140:
1.107 djm 141: out:
142: explicit_bzero(buf, sizeof(buf));
143: if (r != 0)
144: sshbuf_reset(blob);
145: return r;
1.86 djm 146: }
1.8 markus 147:
1.106 markus 148: #ifdef WITH_SSH1
1.86 djm 149: /*
150: * Loads the public part of the ssh v1 key file. Returns NULL if an error was
151: * encountered (the file does not exist or is not readable), and the key
152: * otherwise.
153: */
1.107 djm 154: static int
1.109 djm 155: sshkey_load_public_rsa1(int fd, struct sshkey **keyp, char **commentp)
1.86 djm 156: {
1.107 djm 157: struct sshbuf *b = NULL;
158: int r;
1.86 djm 159:
1.121 djm 160: if (keyp != NULL)
161: *keyp = NULL;
1.107 djm 162: if (commentp != NULL)
163: *commentp = NULL;
1.8 markus 164:
1.107 djm 165: if ((b = sshbuf_new()) == NULL)
166: return SSH_ERR_ALLOC_FAIL;
1.109 djm 167: if ((r = sshkey_load_file(fd, b)) != 0)
1.107 djm 168: goto out;
169: if ((r = sshkey_parse_public_rsa1_fileblob(b, keyp, commentp)) != 0)
170: goto out;
171: r = 0;
172: out:
173: sshbuf_free(b);
174: return r;
1.1 deraadt 175: }
1.107 djm 176: #endif /* WITH_SSH1 */
1.1 deraadt 177:
1.107 djm 178: /* XXX remove error() calls from here? */
1.63 dtucker 179: int
1.107 djm 180: sshkey_perm_ok(int fd, const char *filename)
1.15 markus 181: {
182: struct stat st;
183:
1.38 markus 184: if (fstat(fd, &st) < 0)
1.107 djm 185: return SSH_ERR_SYSTEM_ERROR;
1.38 markus 186: /*
187: * if a key owned by the user is accessed, then we check the
188: * permissions of the file. if the key owned by a different user,
189: * then we don't care.
190: */
191: if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) {
1.15 markus 192: error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
193: error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @");
194: error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
1.38 markus 195: error("Permissions 0%3.3o for '%s' are too open.",
1.54 djm 196: (u_int)st.st_mode & 0777, filename);
1.114 djm 197: error("It is required that your private key files are NOT accessible by others.");
1.29 markus 198: error("This private key will be ignored.");
1.107 djm 199: return SSH_ERR_KEY_BAD_PERMISSIONS;
1.15 markus 200: }
1.107 djm 201: return 0;
1.29 markus 202: }
203:
1.107 djm 204: /* XXX kill perm_ok now that we have SSH_ERR_KEY_BAD_PERMISSIONS? */
205: int
206: sshkey_load_private_type(int type, const char *filename, const char *passphrase,
207: struct sshkey **keyp, char **commentp, int *perm_ok)
1.86 djm 208: {
1.107 djm 209: int fd, r;
1.99 markus 210:
1.121 djm 211: if (keyp != NULL)
212: *keyp = NULL;
1.107 djm 213: if (commentp != NULL)
214: *commentp = NULL;
1.86 djm 215:
1.107 djm 216: if ((fd = open(filename, O_RDONLY)) < 0) {
1.78 dtucker 217: if (perm_ok != NULL)
218: *perm_ok = 0;
1.107 djm 219: return SSH_ERR_SYSTEM_ERROR;
1.78 dtucker 220: }
1.107 djm 221: if (sshkey_perm_ok(fd, filename) != 0) {
1.67 dtucker 222: if (perm_ok != NULL)
223: *perm_ok = 0;
1.107 djm 224: r = SSH_ERR_KEY_BAD_PERMISSIONS;
225: goto out;
1.29 markus 226: }
1.67 dtucker 227: if (perm_ok != NULL)
228: *perm_ok = 1;
1.86 djm 229:
1.109 djm 230: r = sshkey_load_private_type_fd(fd, type, passphrase, keyp, commentp);
231: out:
232: close(fd);
233: return r;
234: }
235:
236: int
237: sshkey_load_private_type_fd(int fd, int type, const char *passphrase,
238: struct sshkey **keyp, char **commentp)
239: {
240: struct sshbuf *buffer = NULL;
241: int r;
242:
1.121 djm 243: if (keyp != NULL)
244: *keyp = NULL;
1.107 djm 245: if ((buffer = sshbuf_new()) == NULL) {
246: r = SSH_ERR_ALLOC_FAIL;
247: goto out;
1.15 markus 248: }
1.109 djm 249: if ((r = sshkey_load_file(fd, buffer)) != 0 ||
250: (r = sshkey_parse_private_fileblob_type(buffer, type,
251: passphrase, keyp, commentp)) != 0)
1.107 djm 252: goto out;
1.109 djm 253:
254: /* success */
1.107 djm 255: r = 0;
256: out:
1.120 mmcc 257: sshbuf_free(buffer);
1.107 djm 258: return r;
1.29 markus 259: }
260:
1.107 djm 261: /* XXX this is almost identical to sshkey_load_private_type() */
262: int
263: sshkey_load_private(const char *filename, const char *passphrase,
264: struct sshkey **keyp, char **commentp)
1.88 djm 265: {
1.107 djm 266: struct sshbuf *buffer = NULL;
267: int r, fd;
1.88 djm 268:
1.121 djm 269: if (keyp != NULL)
270: *keyp = NULL;
1.107 djm 271: if (commentp != NULL)
272: *commentp = NULL;
1.88 djm 273:
1.107 djm 274: if ((fd = open(filename, O_RDONLY)) < 0)
275: return SSH_ERR_SYSTEM_ERROR;
276: if (sshkey_perm_ok(fd, filename) != 0) {
277: r = SSH_ERR_KEY_BAD_PERMISSIONS;
278: goto out;
1.29 markus 279: }
1.86 djm 280:
1.107 djm 281: if ((buffer = sshbuf_new()) == NULL) {
282: r = SSH_ERR_ALLOC_FAIL;
283: goto out;
1.86 djm 284: }
1.109 djm 285: if ((r = sshkey_load_file(fd, buffer)) != 0 ||
1.117 tim 286: (r = sshkey_parse_private_fileblob(buffer, passphrase, keyp,
287: commentp)) != 0)
1.107 djm 288: goto out;
289: r = 0;
290: out:
1.86 djm 291: close(fd);
1.120 mmcc 292: sshbuf_free(buffer);
1.107 djm 293: return r;
1.18 markus 294: }
295:
1.37 itojun 296: static int
1.107 djm 297: sshkey_try_load_public(struct sshkey *k, const char *filename, char **commentp)
1.18 markus 298: {
299: FILE *f;
1.59 dtucker 300: char line[SSH_MAX_PUBKEY_BYTES];
1.18 markus 301: char *cp;
1.60 dtucker 302: u_long linenum = 0;
1.107 djm 303: int r;
1.18 markus 304:
1.107 djm 305: if (commentp != NULL)
306: *commentp = NULL;
307: if ((f = fopen(filename, "r")) == NULL)
308: return SSH_ERR_SYSTEM_ERROR;
309: while (read_keyfile_line(f, filename, line, sizeof(line),
310: &linenum) != -1) {
311: cp = line;
312: switch (*cp) {
313: case '#':
314: case '\n':
315: case '\0':
316: continue;
317: }
318: /* Abort loading if this looks like a private key */
319: if (strncmp(cp, "-----BEGIN", 10) == 0 ||
320: strcmp(cp, "SSH PRIVATE KEY FILE") == 0)
321: break;
322: /* Skip leading whitespace. */
323: for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
324: ;
325: if (*cp) {
326: if ((r = sshkey_read(k, &cp)) == 0) {
327: cp[strcspn(cp, "\r\n")] = '\0';
328: if (commentp) {
329: *commentp = strdup(*cp ?
330: cp : filename);
331: if (*commentp == NULL)
332: r = SSH_ERR_ALLOC_FAIL;
1.18 markus 333: }
1.107 djm 334: fclose(f);
335: return r;
1.18 markus 336: }
337: }
338: }
1.107 djm 339: fclose(f);
340: return SSH_ERR_INVALID_FORMAT;
1.18 markus 341: }
342:
1.29 markus 343: /* load public key from ssh v1 private or any pubkey file */
1.107 djm 344: int
345: sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp)
1.18 markus 346: {
1.107 djm 347: struct sshkey *pub = NULL;
1.110 deraadt 348: char file[PATH_MAX];
1.107 djm 349: int r, fd;
1.18 markus 350:
1.107 djm 351: if (keyp != NULL)
352: *keyp = NULL;
353: if (commentp != NULL)
354: *commentp = NULL;
355:
1.111 djm 356: /* XXX should load file once and attempt to parse each format */
357:
1.107 djm 358: if ((fd = open(filename, O_RDONLY)) < 0)
359: goto skip;
1.106 markus 360: #ifdef WITH_SSH1
1.53 markus 361: /* try rsa1 private key */
1.109 djm 362: r = sshkey_load_public_rsa1(fd, keyp, commentp);
1.107 djm 363: close(fd);
364: switch (r) {
365: case SSH_ERR_INTERNAL_ERROR:
366: case SSH_ERR_ALLOC_FAIL:
367: case SSH_ERR_INVALID_ARGUMENT:
368: case SSH_ERR_SYSTEM_ERROR:
369: case 0:
370: return r;
371: }
1.113 djm 372: #else /* WITH_SSH1 */
373: close(fd);
1.107 djm 374: #endif /* WITH_SSH1 */
375:
376: /* try ssh2 public key */
377: if ((pub = sshkey_new(KEY_UNSPEC)) == NULL)
378: return SSH_ERR_ALLOC_FAIL;
379: if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) {
380: if (keyp != NULL)
381: *keyp = pub;
382: return 0;
383: }
384: sshkey_free(pub);
1.53 markus 385:
1.107 djm 386: #ifdef WITH_SSH1
1.53 markus 387: /* try rsa1 public key */
1.107 djm 388: if ((pub = sshkey_new(KEY_RSA1)) == NULL)
389: return SSH_ERR_ALLOC_FAIL;
390: if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) {
391: if (keyp != NULL)
392: *keyp = pub;
393: return 0;
394: }
395: sshkey_free(pub);
396: #endif /* WITH_SSH1 */
1.53 markus 397:
1.107 djm 398: skip:
399: /* try .pub suffix */
400: if ((pub = sshkey_new(KEY_UNSPEC)) == NULL)
401: return SSH_ERR_ALLOC_FAIL;
402: r = SSH_ERR_ALLOC_FAIL; /* in case strlcpy or strlcat fail */
1.29 markus 403: if ((strlcpy(file, filename, sizeof file) < sizeof(file)) &&
404: (strlcat(file, ".pub", sizeof file) < sizeof(file)) &&
1.107 djm 405: (r = sshkey_try_load_public(pub, file, commentp)) == 0) {
406: if (keyp != NULL)
407: *keyp = pub;
408: return 0;
409: }
410: sshkey_free(pub);
1.111 djm 411:
1.107 djm 412: return r;
1.81 djm 413: }
414:
415: /* Load the certificate associated with the named private key */
1.107 djm 416: int
417: sshkey_load_cert(const char *filename, struct sshkey **keyp)
1.81 djm 418: {
1.107 djm 419: struct sshkey *pub = NULL;
420: char *file = NULL;
421: int r = SSH_ERR_INTERNAL_ERROR;
422:
1.121 djm 423: if (keyp != NULL)
424: *keyp = NULL;
1.81 djm 425:
1.107 djm 426: if (asprintf(&file, "%s-cert.pub", filename) == -1)
427: return SSH_ERR_ALLOC_FAIL;
428:
429: if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) {
430: goto out;
431: }
432: if ((r = sshkey_try_load_public(pub, file, NULL)) != 0)
433: goto out;
1.121 djm 434: /* success */
435: if (keyp != NULL) {
436: *keyp = pub;
437: pub = NULL;
438: }
1.107 djm 439: r = 0;
440: out:
1.118 mmcc 441: free(file);
1.119 mmcc 442: sshkey_free(pub);
1.107 djm 443: return r;
1.81 djm 444: }
445:
446: /* Load private key and certificate */
1.107 djm 447: int
448: sshkey_load_private_cert(int type, const char *filename, const char *passphrase,
449: struct sshkey **keyp, int *perm_ok)
1.81 djm 450: {
1.107 djm 451: struct sshkey *key = NULL, *cert = NULL;
452: int r;
453:
1.121 djm 454: if (keyp != NULL)
455: *keyp = NULL;
1.81 djm 456:
457: switch (type) {
1.106 markus 458: #ifdef WITH_OPENSSL
1.81 djm 459: case KEY_RSA:
460: case KEY_DSA:
1.83 djm 461: case KEY_ECDSA:
1.116 markus 462: #endif /* WITH_OPENSSL */
1.101 djm 463: case KEY_ED25519:
1.107 djm 464: case KEY_UNSPEC:
1.81 djm 465: break;
466: default:
1.107 djm 467: return SSH_ERR_KEY_TYPE_UNKNOWN;
1.81 djm 468: }
469:
1.107 djm 470: if ((r = sshkey_load_private_type(type, filename,
471: passphrase, &key, NULL, perm_ok)) != 0 ||
472: (r = sshkey_load_cert(filename, &cert)) != 0)
473: goto out;
1.81 djm 474:
475: /* Make sure the private key matches the certificate */
1.107 djm 476: if (sshkey_equal_public(key, cert) == 0) {
477: r = SSH_ERR_KEY_CERT_MISMATCH;
478: goto out;
1.81 djm 479: }
480:
1.115 djm 481: if ((r = sshkey_to_certified(key)) != 0 ||
1.107 djm 482: (r = sshkey_cert_copy(cert, key)) != 0)
483: goto out;
484: r = 0;
1.121 djm 485: if (keyp != NULL) {
486: *keyp = key;
487: key = NULL;
488: }
1.107 djm 489: out:
1.119 mmcc 490: sshkey_free(key);
491: sshkey_free(cert);
1.107 djm 492: return r;
1.1 deraadt 493: }
1.80 djm 494:
495: /*
1.107 djm 496: * Returns success if the specified "key" is listed in the file "filename",
497: * SSH_ERR_KEY_NOT_FOUND: if the key is not listed or another error.
1.108 djm 498: * If "strict_type" is set then the key type must match exactly,
1.80 djm 499: * otherwise a comparison that ignores certficiate data is performed.
1.108 djm 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.
1.80 djm 502: */
503: int
1.108 djm 504: sshkey_in_file(struct sshkey *key, const char *filename, int strict_type,
505: int check_ca)
1.80 djm 506: {
507: FILE *f;
508: char line[SSH_MAX_PUBKEY_BYTES];
509: char *cp;
510: u_long linenum = 0;
1.107 djm 511: int r = 0;
512: struct sshkey *pub = NULL;
513: int (*sshkey_compare)(const struct sshkey *, const struct sshkey *) =
514: strict_type ? sshkey_equal : sshkey_equal_public;
1.80 djm 515:
1.108 djm 516: if ((f = fopen(filename, "r")) == NULL)
517: return SSH_ERR_SYSTEM_ERROR;
1.80 djm 518:
519: while (read_keyfile_line(f, filename, line, sizeof(line),
1.107 djm 520: &linenum) != -1) {
1.80 djm 521: cp = line;
522:
523: /* Skip leading whitespace. */
524: for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
525: ;
526:
527: /* Skip comments and empty lines */
528: switch (*cp) {
529: case '#':
530: case '\n':
531: case '\0':
532: continue;
533: }
534:
1.107 djm 535: if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) {
536: r = SSH_ERR_ALLOC_FAIL;
537: goto out;
1.80 djm 538: }
1.107 djm 539: if ((r = sshkey_read(pub, &cp)) != 0)
540: goto out;
1.108 djm 541: if (sshkey_compare(key, pub) ||
542: (check_ca && sshkey_is_cert(key) &&
543: sshkey_compare(key->cert->signature_key, pub))) {
1.107 djm 544: r = 0;
545: goto out;
1.80 djm 546: }
1.107 djm 547: sshkey_free(pub);
548: pub = NULL;
1.80 djm 549: }
1.107 djm 550: r = SSH_ERR_KEY_NOT_FOUND;
551: out:
1.119 mmcc 552: sshkey_free(pub);
1.80 djm 553: fclose(f);
1.107 djm 554: return r;
1.108 djm 555: }
556:
557: /*
558: * Checks whether the specified key is revoked, returning 0 if not,
559: * SSH_ERR_KEY_REVOKED if it is or another error code if something
560: * unexpected happened.
561: * This will check both the key and, if it is a certificate, its CA key too.
562: * "revoked_keys_file" may be a KRL or a one-per-line list of public keys.
563: */
564: int
565: sshkey_check_revoked(struct sshkey *key, const char *revoked_keys_file)
566: {
567: int r;
568:
569: r = ssh_krl_file_contains_key(revoked_keys_file, key);
570: /* If this was not a KRL to begin with then continue below */
571: if (r != SSH_ERR_KRL_BAD_MAGIC)
572: return r;
573:
574: /*
575: * If the file is not a KRL or we can't handle KRLs then attempt to
576: * parse the file as a flat list of keys.
577: */
578: switch ((r = sshkey_in_file(key, revoked_keys_file, 0, 1))) {
579: case 0:
580: /* Key found => revoked */
581: return SSH_ERR_KEY_REVOKED;
582: case SSH_ERR_KEY_NOT_FOUND:
583: /* Key not found => not revoked */
584: return 0;
585: default:
586: /* Some other error occurred */
587: return r;
588: }
1.80 djm 589: }
1.107 djm 590: