1323124Sdes/* $OpenBSD: authfile.c,v 1.121 2016/04/09 12:39:30 djm Exp $ */ 257429Smarkm/* 3262566Sdes * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved. 465674Skris * 565674Skris * Redistribution and use in source and binary forms, with or without 665674Skris * modification, are permitted provided that the following conditions 765674Skris * are met: 865674Skris * 1. Redistributions of source code must retain the above copyright 965674Skris * notice, this list of conditions and the following disclaimer. 1065674Skris * 2. Redistributions in binary form must reproduce the above copyright 1165674Skris * notice, this list of conditions and the following disclaimer in the 1265674Skris * documentation and/or other materials provided with the distribution. 1365674Skris * 1465674Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1565674Skris * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1665674Skris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1765674Skris * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1865674Skris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1965674Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2065674Skris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2165674Skris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2265674Skris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2365674Skris * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2457429Smarkm */ 2557429Smarkm 2657429Smarkm#include "includes.h" 2757429Smarkm 28162856Sdes#include <sys/types.h> 29162856Sdes#include <sys/stat.h> 30162856Sdes#include <sys/uio.h> 31162856Sdes 32162856Sdes#include <errno.h> 33162856Sdes#include <fcntl.h> 34295367Sdes#include <stdio.h> 35162856Sdes#include <stdarg.h> 36162856Sdes#include <stdlib.h> 37162856Sdes#include <string.h> 38162856Sdes#include <unistd.h> 39295367Sdes#include <limits.h> 40162856Sdes 4176262Sgreen#include "cipher.h" 4257429Smarkm#include "ssh.h" 4376262Sgreen#include "log.h" 4476262Sgreen#include "authfile.h" 4592559Sdes#include "rsa.h" 46147005Sdes#include "misc.h" 47149753Sdes#include "atomicio.h" 48295367Sdes#include "sshkey.h" 49295367Sdes#include "sshbuf.h" 50295367Sdes#include "ssherr.h" 51295367Sdes#include "krl.h" 5257429Smarkm 53226046Sdes#define MAX_KEY_FILE_SIZE (1024 * 1024) 54226046Sdes 55221420Sdes/* Save a key blob to a file */ 56221420Sdesstatic int 57295367Sdessshkey_save_private_blob(struct sshbuf *keybuf, const char *filename) 58221420Sdes{ 59295367Sdes int fd, oerrno; 60221420Sdes 61295367Sdes if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) 62295367Sdes return SSH_ERR_SYSTEM_ERROR; 63295367Sdes if (atomicio(vwrite, fd, (u_char *)sshbuf_ptr(keybuf), 64295367Sdes sshbuf_len(keybuf)) != sshbuf_len(keybuf)) { 65295367Sdes oerrno = errno; 66221420Sdes close(fd); 67221420Sdes unlink(filename); 68295367Sdes errno = oerrno; 69295367Sdes return SSH_ERR_SYSTEM_ERROR; 70221420Sdes } 71221420Sdes close(fd); 72295367Sdes return 0; 73221420Sdes} 74221420Sdes 75221420Sdesint 76295367Sdessshkey_save_private(struct sshkey *key, const char *filename, 77295367Sdes const char *passphrase, const char *comment, 78295367Sdes int force_new_format, const char *new_format_cipher, int new_format_rounds) 79221420Sdes{ 80295367Sdes struct sshbuf *keyblob = NULL; 81295367Sdes int r; 82221420Sdes 83295367Sdes if ((keyblob = sshbuf_new()) == NULL) 84295367Sdes return SSH_ERR_ALLOC_FAIL; 85295367Sdes if ((r = sshkey_private_to_fileblob(key, keyblob, passphrase, comment, 86295367Sdes force_new_format, new_format_cipher, new_format_rounds)) != 0) 87221420Sdes goto out; 88295367Sdes if ((r = sshkey_save_private_blob(keyblob, filename)) != 0) 89221420Sdes goto out; 90295367Sdes r = 0; 91221420Sdes out: 92295367Sdes sshbuf_free(keyblob); 93295367Sdes return r; 94221420Sdes} 95221420Sdes 96226046Sdes/* Load a key from a fd into a buffer */ 97226046Sdesint 98295367Sdessshkey_load_file(int fd, struct sshbuf *blob) 99221420Sdes{ 100226046Sdes u_char buf[1024]; 101221420Sdes size_t len; 102113911Sdes struct stat st; 103295367Sdes int r; 10457429Smarkm 105295367Sdes if (fstat(fd, &st) < 0) 106295367Sdes return SSH_ERR_SYSTEM_ERROR; 107226046Sdes if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && 108295367Sdes st.st_size > MAX_KEY_FILE_SIZE) 109295367Sdes return SSH_ERR_INVALID_FORMAT; 110226046Sdes for (;;) { 111226046Sdes if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) { 112226046Sdes if (errno == EPIPE) 113226046Sdes break; 114295367Sdes r = SSH_ERR_SYSTEM_ERROR; 115295367Sdes goto out; 116226046Sdes } 117295367Sdes if ((r = sshbuf_put(blob, buf, len)) != 0) 118295367Sdes goto out; 119295367Sdes if (sshbuf_len(blob) > MAX_KEY_FILE_SIZE) { 120295367Sdes r = SSH_ERR_INVALID_FORMAT; 121295367Sdes goto out; 122226046Sdes } 123226046Sdes } 124226046Sdes if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && 125295367Sdes st.st_size != (off_t)sshbuf_len(blob)) { 126295367Sdes r = SSH_ERR_FILE_CHANGED; 127295367Sdes goto out; 12857429Smarkm } 129295367Sdes r = 0; 130226046Sdes 131295367Sdes out: 132295367Sdes explicit_bzero(buf, sizeof(buf)); 133295367Sdes if (r != 0) 134295367Sdes sshbuf_reset(blob); 135295367Sdes return r; 136221420Sdes} 13757429Smarkm 138295367Sdes#ifdef WITH_SSH1 139221420Sdes/* 140221420Sdes * Loads the public part of the ssh v1 key file. Returns NULL if an error was 141221420Sdes * encountered (the file does not exist or is not readable), and the key 142221420Sdes * otherwise. 143221420Sdes */ 144295367Sdesstatic int 145295367Sdessshkey_load_public_rsa1(int fd, struct sshkey **keyp, char **commentp) 146221420Sdes{ 147295367Sdes struct sshbuf *b = NULL; 148295367Sdes int r; 149221420Sdes 150323124Sdes if (keyp != NULL) 151323124Sdes *keyp = NULL; 152255767Sdes if (commentp != NULL) 153295367Sdes *commentp = NULL; 15460576Skris 155295367Sdes if ((b = sshbuf_new()) == NULL) 156295367Sdes return SSH_ERR_ALLOC_FAIL; 157295367Sdes if ((r = sshkey_load_file(fd, b)) != 0) 158295367Sdes goto out; 159295367Sdes if ((r = sshkey_parse_public_rsa1_fileblob(b, keyp, commentp)) != 0) 160295367Sdes goto out; 161295367Sdes r = 0; 162295367Sdes out: 163295367Sdes sshbuf_free(b); 164295367Sdes return r; 16560576Skris} 166295367Sdes#endif /* WITH_SSH1 */ 16760576Skris 168295367Sdes/* XXX remove error() calls from here? */ 169162856Sdesint 170295367Sdessshkey_perm_ok(int fd, const char *filename) 17160576Skris{ 17260576Skris struct stat st; 17360576Skris 17492559Sdes if (fstat(fd, &st) < 0) 175295367Sdes return SSH_ERR_SYSTEM_ERROR; 17692559Sdes /* 17792559Sdes * if a key owned by the user is accessed, then we check the 17892559Sdes * permissions of the file. if the key owned by a different user, 17992559Sdes * then we don't care. 18092559Sdes */ 18198941Sdes#ifdef HAVE_CYGWIN 18298941Sdes if (check_ntsec(filename)) 18398941Sdes#endif 18492559Sdes if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) { 18560576Skris error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 18660576Skris error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @"); 18760576Skris error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 18892559Sdes error("Permissions 0%3.3o for '%s' are too open.", 189124211Sdes (u_int)st.st_mode & 0777, filename); 190226046Sdes error("It is required that your private key files are NOT accessible by others."); 19176262Sgreen error("This private key will be ignored."); 192295367Sdes return SSH_ERR_KEY_BAD_PERMISSIONS; 19360576Skris } 194295367Sdes return 0; 19576262Sgreen} 19676262Sgreen 197295367Sdes/* XXX kill perm_ok now that we have SSH_ERR_KEY_BAD_PERMISSIONS? */ 198295367Sdesint 199295367Sdessshkey_load_private_type(int type, const char *filename, const char *passphrase, 200295367Sdes struct sshkey **keyp, char **commentp, int *perm_ok) 201221420Sdes{ 202295367Sdes int fd, r; 203262566Sdes 204323124Sdes if (keyp != NULL) 205323124Sdes *keyp = NULL; 206295367Sdes if (commentp != NULL) 207295367Sdes *commentp = NULL; 208221420Sdes 209295367Sdes if ((fd = open(filename, O_RDONLY)) < 0) { 210204917Sdes if (perm_ok != NULL) 211204917Sdes *perm_ok = 0; 212295367Sdes return SSH_ERR_SYSTEM_ERROR; 213204917Sdes } 214295367Sdes if (sshkey_perm_ok(fd, filename) != 0) { 215162856Sdes if (perm_ok != NULL) 216162856Sdes *perm_ok = 0; 217295367Sdes r = SSH_ERR_KEY_BAD_PERMISSIONS; 218295367Sdes goto out; 21976262Sgreen } 220162856Sdes if (perm_ok != NULL) 221162856Sdes *perm_ok = 1; 222221420Sdes 223295367Sdes r = sshkey_load_private_type_fd(fd, type, passphrase, keyp, commentp); 224295367Sdes out: 225221420Sdes close(fd); 226295367Sdes return r; 22760576Skris} 22865674Skris 229295367Sdesint 230295367Sdessshkey_load_private_type_fd(int fd, int type, const char *passphrase, 231295367Sdes struct sshkey **keyp, char **commentp) 232226046Sdes{ 233295367Sdes struct sshbuf *buffer = NULL; 234295367Sdes int r; 235226046Sdes 236323124Sdes if (keyp != NULL) 237323124Sdes *keyp = NULL; 238295367Sdes if ((buffer = sshbuf_new()) == NULL) { 239295367Sdes r = SSH_ERR_ALLOC_FAIL; 240295367Sdes goto out; 241226046Sdes } 242295367Sdes if ((r = sshkey_load_file(fd, buffer)) != 0 || 243295367Sdes (r = sshkey_parse_private_fileblob_type(buffer, type, 244295367Sdes passphrase, keyp, commentp)) != 0) 245295367Sdes goto out; 246295367Sdes 247295367Sdes /* success */ 248295367Sdes r = 0; 249295367Sdes out: 250296781Sdes sshbuf_free(buffer); 251295367Sdes return r; 252226046Sdes} 253226046Sdes 254295367Sdes/* XXX this is almost identical to sshkey_load_private_type() */ 255295367Sdesint 256295367Sdessshkey_load_private(const char *filename, const char *passphrase, 257295367Sdes struct sshkey **keyp, char **commentp) 25876262Sgreen{ 259295367Sdes struct sshbuf *buffer = NULL; 260295367Sdes int r, fd; 26176262Sgreen 262323124Sdes if (keyp != NULL) 263323124Sdes *keyp = NULL; 264295367Sdes if (commentp != NULL) 265295367Sdes *commentp = NULL; 266295367Sdes 267295367Sdes if ((fd = open(filename, O_RDONLY)) < 0) 268295367Sdes return SSH_ERR_SYSTEM_ERROR; 269295367Sdes if (sshkey_perm_ok(fd, filename) != 0) { 270295367Sdes r = SSH_ERR_KEY_BAD_PERMISSIONS; 271295367Sdes goto out; 272204917Sdes } 273221420Sdes 274295367Sdes if ((buffer = sshbuf_new()) == NULL) { 275295367Sdes r = SSH_ERR_ALLOC_FAIL; 276295367Sdes goto out; 277221420Sdes } 278295367Sdes if ((r = sshkey_load_file(fd, buffer)) != 0 || 279296781Sdes (r = sshkey_parse_private_fileblob(buffer, passphrase, keyp, 280296781Sdes commentp)) != 0) 281295367Sdes goto out; 282295367Sdes r = 0; 283295367Sdes out: 284221420Sdes close(fd); 285296781Sdes sshbuf_free(buffer); 286295367Sdes return r; 28776262Sgreen} 28876262Sgreen 28992559Sdesstatic int 290295367Sdessshkey_try_load_public(struct sshkey *k, const char *filename, char **commentp) 29165674Skris{ 29265674Skris FILE *f; 293147005Sdes char line[SSH_MAX_PUBKEY_BYTES]; 29465674Skris char *cp; 295147005Sdes u_long linenum = 0; 296295367Sdes int r; 29765674Skris 298295367Sdes if (commentp != NULL) 299295367Sdes *commentp = NULL; 300295367Sdes if ((f = fopen(filename, "r")) == NULL) 301295367Sdes return SSH_ERR_SYSTEM_ERROR; 302295367Sdes while (read_keyfile_line(f, filename, line, sizeof(line), 303295367Sdes &linenum) != -1) { 304295367Sdes cp = line; 305295367Sdes switch (*cp) { 306295367Sdes case '#': 307295367Sdes case '\n': 308295367Sdes case '\0': 309295367Sdes continue; 310295367Sdes } 311295367Sdes /* Abort loading if this looks like a private key */ 312295367Sdes if (strncmp(cp, "-----BEGIN", 10) == 0 || 313295367Sdes strcmp(cp, "SSH PRIVATE KEY FILE") == 0) 314295367Sdes break; 315295367Sdes /* Skip leading whitespace. */ 316295367Sdes for (; *cp && (*cp == ' ' || *cp == '\t'); cp++) 317295367Sdes ; 318295367Sdes if (*cp) { 319295367Sdes if ((r = sshkey_read(k, &cp)) == 0) { 320295367Sdes cp[strcspn(cp, "\r\n")] = '\0'; 321295367Sdes if (commentp) { 322295367Sdes *commentp = strdup(*cp ? 323295367Sdes cp : filename); 324295367Sdes if (*commentp == NULL) 325295367Sdes r = SSH_ERR_ALLOC_FAIL; 32665674Skris } 327295367Sdes fclose(f); 328295367Sdes return r; 32965674Skris } 33065674Skris } 33165674Skris } 332295367Sdes fclose(f); 333295367Sdes return SSH_ERR_INVALID_FORMAT; 33465674Skris} 33565674Skris 33676262Sgreen/* load public key from ssh v1 private or any pubkey file */ 337295367Sdesint 338295367Sdessshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp) 33965674Skris{ 340295367Sdes struct sshkey *pub = NULL; 341295367Sdes char file[PATH_MAX]; 342295367Sdes int r, fd; 34365674Skris 344295367Sdes if (keyp != NULL) 345295367Sdes *keyp = NULL; 346295367Sdes if (commentp != NULL) 347295367Sdes *commentp = NULL; 348295367Sdes 349295367Sdes /* XXX should load file once and attempt to parse each format */ 350295367Sdes 351295367Sdes if ((fd = open(filename, O_RDONLY)) < 0) 352295367Sdes goto skip; 353295367Sdes#ifdef WITH_SSH1 354124211Sdes /* try rsa1 private key */ 355295367Sdes r = sshkey_load_public_rsa1(fd, keyp, commentp); 356295367Sdes close(fd); 357295367Sdes switch (r) { 358295367Sdes case SSH_ERR_INTERNAL_ERROR: 359295367Sdes case SSH_ERR_ALLOC_FAIL: 360295367Sdes case SSH_ERR_INVALID_ARGUMENT: 361295367Sdes case SSH_ERR_SYSTEM_ERROR: 362295367Sdes case 0: 363295367Sdes return r; 364295367Sdes } 365295367Sdes#else /* WITH_SSH1 */ 366295367Sdes close(fd); 367295367Sdes#endif /* WITH_SSH1 */ 368124211Sdes 369295367Sdes /* try ssh2 public key */ 370295367Sdes if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) 371295367Sdes return SSH_ERR_ALLOC_FAIL; 372295367Sdes if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) { 373295367Sdes if (keyp != NULL) 374295367Sdes *keyp = pub; 375295367Sdes return 0; 376295367Sdes } 377295367Sdes sshkey_free(pub); 378295367Sdes 379295367Sdes#ifdef WITH_SSH1 380124211Sdes /* try rsa1 public key */ 381295367Sdes if ((pub = sshkey_new(KEY_RSA1)) == NULL) 382295367Sdes return SSH_ERR_ALLOC_FAIL; 383295367Sdes if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) { 384295367Sdes if (keyp != NULL) 385295367Sdes *keyp = pub; 386295367Sdes return 0; 387295367Sdes } 388295367Sdes sshkey_free(pub); 389295367Sdes#endif /* WITH_SSH1 */ 390124211Sdes 391295367Sdes skip: 392295367Sdes /* try .pub suffix */ 393295367Sdes if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) 394295367Sdes return SSH_ERR_ALLOC_FAIL; 395295367Sdes r = SSH_ERR_ALLOC_FAIL; /* in case strlcpy or strlcat fail */ 39676262Sgreen if ((strlcpy(file, filename, sizeof file) < sizeof(file)) && 39776262Sgreen (strlcat(file, ".pub", sizeof file) < sizeof(file)) && 398295367Sdes (r = sshkey_try_load_public(pub, file, commentp)) == 0) { 399295367Sdes if (keyp != NULL) 400295367Sdes *keyp = pub; 401295367Sdes return 0; 402295367Sdes } 403295367Sdes sshkey_free(pub); 404295367Sdes 405295367Sdes return r; 40665674Skris} 407204917Sdes 408215116Sdes/* Load the certificate associated with the named private key */ 409295367Sdesint 410295367Sdessshkey_load_cert(const char *filename, struct sshkey **keyp) 411215116Sdes{ 412295367Sdes struct sshkey *pub = NULL; 413295367Sdes char *file = NULL; 414295367Sdes int r = SSH_ERR_INTERNAL_ERROR; 415215116Sdes 416323124Sdes if (keyp != NULL) 417323124Sdes *keyp = NULL; 418295367Sdes 419295367Sdes if (asprintf(&file, "%s-cert.pub", filename) == -1) 420295367Sdes return SSH_ERR_ALLOC_FAIL; 421295367Sdes 422295367Sdes if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) { 423295367Sdes goto out; 424295367Sdes } 425295367Sdes if ((r = sshkey_try_load_public(pub, file, NULL)) != 0) 426295367Sdes goto out; 427323124Sdes /* success */ 428323124Sdes if (keyp != NULL) { 429323124Sdes *keyp = pub; 430323124Sdes pub = NULL; 431323124Sdes } 432295367Sdes r = 0; 433295367Sdes out: 434296781Sdes free(file); 435296781Sdes sshkey_free(pub); 436295367Sdes return r; 437215116Sdes} 438215116Sdes 439215116Sdes/* Load private key and certificate */ 440295367Sdesint 441295367Sdessshkey_load_private_cert(int type, const char *filename, const char *passphrase, 442295367Sdes struct sshkey **keyp, int *perm_ok) 443215116Sdes{ 444295367Sdes struct sshkey *key = NULL, *cert = NULL; 445295367Sdes int r; 446215116Sdes 447323124Sdes if (keyp != NULL) 448323124Sdes *keyp = NULL; 449295367Sdes 450215116Sdes switch (type) { 451295367Sdes#ifdef WITH_OPENSSL 452215116Sdes case KEY_RSA: 453215116Sdes case KEY_DSA: 454221420Sdes case KEY_ECDSA: 455295367Sdes#endif /* WITH_OPENSSL */ 456262566Sdes case KEY_ED25519: 457295367Sdes case KEY_UNSPEC: 458215116Sdes break; 459215116Sdes default: 460295367Sdes return SSH_ERR_KEY_TYPE_UNKNOWN; 461215116Sdes } 462215116Sdes 463295367Sdes if ((r = sshkey_load_private_type(type, filename, 464295367Sdes passphrase, &key, NULL, perm_ok)) != 0 || 465295367Sdes (r = sshkey_load_cert(filename, &cert)) != 0) 466295367Sdes goto out; 467215116Sdes 468215116Sdes /* Make sure the private key matches the certificate */ 469295367Sdes if (sshkey_equal_public(key, cert) == 0) { 470295367Sdes r = SSH_ERR_KEY_CERT_MISMATCH; 471295367Sdes goto out; 472215116Sdes } 473215116Sdes 474295367Sdes if ((r = sshkey_to_certified(key)) != 0 || 475295367Sdes (r = sshkey_cert_copy(cert, key)) != 0) 476295367Sdes goto out; 477295367Sdes r = 0; 478323124Sdes if (keyp != NULL) { 479323124Sdes *keyp = key; 480323124Sdes key = NULL; 481323124Sdes } 482295367Sdes out: 483296781Sdes sshkey_free(key); 484296781Sdes sshkey_free(cert); 485295367Sdes return r; 486215116Sdes} 487215116Sdes 488204917Sdes/* 489295367Sdes * Returns success if the specified "key" is listed in the file "filename", 490295367Sdes * SSH_ERR_KEY_NOT_FOUND: if the key is not listed or another error. 491295367Sdes * If "strict_type" is set then the key type must match exactly, 492204917Sdes * otherwise a comparison that ignores certficiate data is performed. 493295367Sdes * If "check_ca" is set and "key" is a certificate, then its CA key is 494295367Sdes * also checked and sshkey_in_file() will return success if either is found. 495204917Sdes */ 496204917Sdesint 497295367Sdessshkey_in_file(struct sshkey *key, const char *filename, int strict_type, 498295367Sdes int check_ca) 499204917Sdes{ 500204917Sdes FILE *f; 501204917Sdes char line[SSH_MAX_PUBKEY_BYTES]; 502204917Sdes char *cp; 503204917Sdes u_long linenum = 0; 504295367Sdes int r = 0; 505295367Sdes struct sshkey *pub = NULL; 506295367Sdes int (*sshkey_compare)(const struct sshkey *, const struct sshkey *) = 507295367Sdes strict_type ? sshkey_equal : sshkey_equal_public; 508204917Sdes 509295367Sdes if ((f = fopen(filename, "r")) == NULL) 510295367Sdes return SSH_ERR_SYSTEM_ERROR; 511204917Sdes 512204917Sdes while (read_keyfile_line(f, filename, line, sizeof(line), 513295367Sdes &linenum) != -1) { 514204917Sdes cp = line; 515204917Sdes 516204917Sdes /* Skip leading whitespace. */ 517204917Sdes for (; *cp && (*cp == ' ' || *cp == '\t'); cp++) 518204917Sdes ; 519204917Sdes 520204917Sdes /* Skip comments and empty lines */ 521204917Sdes switch (*cp) { 522204917Sdes case '#': 523204917Sdes case '\n': 524204917Sdes case '\0': 525204917Sdes continue; 526204917Sdes } 527204917Sdes 528295367Sdes if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) { 529295367Sdes r = SSH_ERR_ALLOC_FAIL; 530295367Sdes goto out; 531204917Sdes } 532295367Sdes if ((r = sshkey_read(pub, &cp)) != 0) 533295367Sdes goto out; 534295367Sdes if (sshkey_compare(key, pub) || 535295367Sdes (check_ca && sshkey_is_cert(key) && 536295367Sdes sshkey_compare(key->cert->signature_key, pub))) { 537295367Sdes r = 0; 538295367Sdes goto out; 539204917Sdes } 540295367Sdes sshkey_free(pub); 541295367Sdes pub = NULL; 542204917Sdes } 543295367Sdes r = SSH_ERR_KEY_NOT_FOUND; 544295367Sdes out: 545296781Sdes sshkey_free(pub); 546204917Sdes fclose(f); 547295367Sdes return r; 548204917Sdes} 549295367Sdes 550295367Sdes/* 551295367Sdes * Checks whether the specified key is revoked, returning 0 if not, 552295367Sdes * SSH_ERR_KEY_REVOKED if it is or another error code if something 553295367Sdes * unexpected happened. 554295367Sdes * This will check both the key and, if it is a certificate, its CA key too. 555295367Sdes * "revoked_keys_file" may be a KRL or a one-per-line list of public keys. 556295367Sdes */ 557295367Sdesint 558295367Sdessshkey_check_revoked(struct sshkey *key, const char *revoked_keys_file) 559295367Sdes{ 560295367Sdes int r; 561295367Sdes 562295367Sdes r = ssh_krl_file_contains_key(revoked_keys_file, key); 563295367Sdes /* If this was not a KRL to begin with then continue below */ 564295367Sdes if (r != SSH_ERR_KRL_BAD_MAGIC) 565295367Sdes return r; 566295367Sdes 567295367Sdes /* 568295367Sdes * If the file is not a KRL or we can't handle KRLs then attempt to 569295367Sdes * parse the file as a flat list of keys. 570295367Sdes */ 571295367Sdes switch ((r = sshkey_in_file(key, revoked_keys_file, 0, 1))) { 572295367Sdes case 0: 573295367Sdes /* Key found => revoked */ 574295367Sdes return SSH_ERR_KEY_REVOKED; 575295367Sdes case SSH_ERR_KEY_NOT_FOUND: 576295367Sdes /* Key not found => not revoked */ 577295367Sdes return 0; 578295367Sdes default: 579295367Sdes /* Some other error occurred */ 580295367Sdes return r; 581295367Sdes } 582295367Sdes} 583295367Sdes 584