11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* $OpenBSD: authfile.c,v 1.92 2011/06/14 22:49:18 markus Exp $ */ 21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Author: Tatu Ylonen <ylo@cs.hut.fi> 41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * All rights reserved 61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * This file contains functions for reading and writing identity files, and 71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * for reading the passphrase from the user. 81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * As far as I am concerned, the code I have written for this software 101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * can be used freely for any purpose. Any derived versions of this 111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * software must be clearly marked as such, and if the derived work is 121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * incompatible with the protocol description in the RFC file, it must be 131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * called by a name other than "ssh" or "Secure Shell". 141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2000 Markus Friedl. All rights reserved. 171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Redistribution and use in source and binary forms, with or without 191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * modification, are permitted provided that the following conditions 201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * are met: 211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 1. Redistributions of source code must retain the above copyright 221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * notice, this list of conditions and the following disclaimer. 231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 2. Redistributions in binary form must reproduce the above copyright 241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * notice, this list of conditions and the following disclaimer in the 251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * documentation and/or other materials provided with the distribution. 261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h" 401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h> 421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/stat.h> 431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/param.h> 441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/uio.h> 451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <openssl/err.h> 471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <openssl/evp.h> 481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <openssl/pem.h> 491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* compatibility with old or broken OpenSSL versions */ 511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "openbsd-compat/openssl-compat.h" 521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <errno.h> 541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <fcntl.h> 551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdarg.h> 561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdio.h> 571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdlib.h> 581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h> 591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <unistd.h> 601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "xmalloc.h" 621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "cipher.h" 631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "buffer.h" 641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "key.h" 651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh.h" 661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "log.h" 671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "authfile.h" 681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "rsa.h" 691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "misc.h" 701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "atomicio.h" 711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define MAX_KEY_FILE_SIZE (1024 * 1024) 731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Version identification string for SSH v1 identity files. */ 751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic const char authfile_id_string[] = 761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "SSH PRIVATE KEY FILE FORMAT 1.1\n"; 771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Serialises the authentication (private) key to a blob, encrypting it with 801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * passphrase. The identification of the blob (lowest 64 bits of n) will 811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * precede the key to provide identification of the key without needing a 821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * passphrase. 831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_private_rsa1_to_blob(Key *key, Buffer *blob, const char *passphrase, 861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const char *comment) 871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Buffer buffer, encrypted; 891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_char buf[100], *cp; 901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int i, cipher_num; 911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CipherContext ciphercontext; 921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Cipher *cipher; 931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int32_t rnd; 941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * If the passphrase is empty, use SSH_CIPHER_NONE to ease converting 971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * to another cipher; otherwise use SSH_AUTHFILE_CIPHER. 981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cipher_num = (strcmp(passphrase, "") == 0) ? 1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood SSH_CIPHER_NONE : SSH_AUTHFILE_CIPHER; 1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((cipher = cipher_by_number(cipher_num)) == NULL) 1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("save_private_key_rsa: bad cipher"); 1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* This buffer is used to built the secret part of the private key. */ 1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_init(&buffer); 1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Put checkbytes for checking passphrase validity. */ 1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rnd = arc4random(); 1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buf[0] = rnd & 0xff; 1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buf[1] = (rnd >> 8) & 0xff; 1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buf[2] = buf[0]; 1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buf[3] = buf[1]; 1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_append(&buffer, buf, 4); 1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Store the private key (n and e will not be stored because they 1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * will be stored in plain text, and storing them also in encrypted 1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * format would just give known plaintext). 1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_bignum(&buffer, key->rsa->d); 1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_bignum(&buffer, key->rsa->iqmp); 1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_bignum(&buffer, key->rsa->q); /* reverse from SSL p */ 1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_bignum(&buffer, key->rsa->p); /* reverse from SSL q */ 1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Pad the part to be encrypted until its size is a multiple of 8. */ 1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood while (buffer_len(&buffer) % 8 != 0) 1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_char(&buffer, 0); 1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* This buffer will be used to contain the data in the file. */ 1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_init(&encrypted); 1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* First store keyfile id string. */ 1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (i = 0; authfile_id_string[i]; i++) 1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_char(&encrypted, authfile_id_string[i]); 1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_char(&encrypted, 0); 1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Store cipher type. */ 1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_char(&encrypted, cipher_num); 1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_int(&encrypted, 0); /* For future extension */ 1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Store public key. This will be in plain text. */ 1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_int(&encrypted, BN_num_bits(key->rsa->n)); 1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_bignum(&encrypted, key->rsa->n); 1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_bignum(&encrypted, key->rsa->e); 1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_cstring(&encrypted, comment); 1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Allocate space for the private part of the key in the buffer. */ 1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cp = buffer_append_space(&encrypted, buffer_len(&buffer)); 1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cipher_set_key_string(&ciphercontext, cipher, passphrase, 1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CIPHER_ENCRYPT); 1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cipher_crypt(&ciphercontext, cp, 1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_ptr(&buffer), buffer_len(&buffer)); 1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cipher_cleanup(&ciphercontext); 1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memset(&ciphercontext, 0, sizeof(ciphercontext)); 1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Destroy temporary data. */ 1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memset(buf, 0, sizeof(buf)); 1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(&buffer); 1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_append(blob, buffer_ptr(&encrypted), buffer_len(&encrypted)); 1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(&encrypted); 1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return 1; 1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* convert SSH v2 key in OpenSSL PEM format */ 1681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 1691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_private_pem_to_blob(Key *key, Buffer *blob, const char *_passphrase, 1701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const char *comment) 1711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int success = 0; 1731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int blen, len = strlen(_passphrase); 1741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL; 1751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if (OPENSSL_VERSION_NUMBER < 0x00907000L) 1761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL; 1771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else 1781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL; 1791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 1801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const u_char *bptr; 1811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood BIO *bio; 1821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (len > 0 && len <= 4) { 1841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("passphrase too short: have %d bytes, need > 4", len); 1851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return 0; 1861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((bio = BIO_new(BIO_s_mem())) == NULL) { 1881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("%s: BIO_new failed", __func__); 1891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return 0; 1901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood switch (key->type) { 1921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case KEY_DSA: 1931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood success = PEM_write_bio_DSAPrivateKey(bio, key->dsa, 1941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cipher, passphrase, len, NULL, NULL); 1951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 1961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC 1971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case KEY_ECDSA: 1981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa, 1991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cipher, passphrase, len, NULL, NULL); 2001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 2011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 2021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case KEY_RSA: 2031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood success = PEM_write_bio_RSAPrivateKey(bio, key->rsa, 2041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cipher, passphrase, len, NULL, NULL); 2051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 2061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (success) { 2081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) 2091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood success = 0; 2101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else 2111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_append(blob, bptr, blen); 2121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood BIO_free(bio); 2141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return success; 2151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 2161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Save a key blob to a file */ 2181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 2191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_save_private_blob(Buffer *keybuf, const char *filename) 2201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 2211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int fd; 2221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) { 2241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("open %s failed: %s.", filename, strerror(errno)); 2251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return 0; 2261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (atomicio(vwrite, fd, buffer_ptr(keybuf), 2281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_len(keybuf)) != buffer_len(keybuf)) { 2291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("write to key file %s failed: %s", filename, 2301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood strerror(errno)); 2311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood close(fd); 2321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood unlink(filename); 2331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return 0; 2341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood close(fd); 2361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return 1; 2371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 2381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Serialise "key" to buffer "blob" */ 2401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 2411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_private_to_blob(Key *key, Buffer *blob, const char *passphrase, 2421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const char *comment) 2431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 2441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood switch (key->type) { 2451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case KEY_RSA1: 2461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return key_private_rsa1_to_blob(key, blob, passphrase, comment); 2471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case KEY_DSA: 2481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case KEY_ECDSA: 2491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case KEY_RSA: 2501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return key_private_pem_to_blob(key, blob, passphrase, comment); 2511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood default: 2521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("%s: cannot save key type %d", __func__, key->type); 2531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return 0; 2541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 2561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint 2581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_save_private(Key *key, const char *filename, const char *passphrase, 2591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const char *comment) 2601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 2611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Buffer keyblob; 2621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int success = 0; 2631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_init(&keyblob); 2651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!key_private_to_blob(key, &keyblob, passphrase, comment)) 2661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto out; 2671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!key_save_private_blob(&keyblob, filename)) 2681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto out; 2691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood success = 1; 2701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood out: 2711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(&keyblob); 2721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return success; 2731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 2741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 2761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Parse the public, unencrypted portion of a RSA1 key. 2771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 2781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Key * 2791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_parse_public_rsa1(Buffer *blob, char **commentp) 2801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 2811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Key *pub; 2821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Buffer copy; 2831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Check that it is at least big enough to contain the ID string. */ 2851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (buffer_len(blob) < sizeof(authfile_id_string)) { 2861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug3("Truncated RSA1 identifier"); 2871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 2881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 2911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Make sure it begins with the id string. Consume the id string 2921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * from the buffer. 2931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 2941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (memcmp(buffer_ptr(blob), authfile_id_string, 2951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood sizeof(authfile_id_string)) != 0) { 2961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug3("Incorrect RSA1 identifier"); 2971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 2981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_init(©); 3001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_append(©, buffer_ptr(blob), buffer_len(blob)); 3011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_consume(©, sizeof(authfile_id_string)); 3021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Skip cipher type and reserved data. */ 3041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (void) buffer_get_char(©); /* cipher type */ 3051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (void) buffer_get_int(©); /* reserved */ 3061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Read the public key from the buffer. */ 3081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (void) buffer_get_int(©); 3091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pub = key_new(KEY_RSA1); 3101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_get_bignum(©, pub->rsa->n); 3111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_get_bignum(©, pub->rsa->e); 3121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (commentp) 3131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *commentp = buffer_get_string(©, NULL); 3141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* The encrypted private part is not parsed by this function. */ 3151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(©); 3161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return pub; 3181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 3191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Load a key from a fd into a buffer */ 3211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint 3221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_load_file(int fd, const char *filename, Buffer *blob) 3231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 3241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_char buf[1024]; 3251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood size_t len; 3261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct stat st; 3271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (fstat(fd, &st) < 0) { 3291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("%s: fstat of key file %.200s%sfailed: %.100s", __func__, 3301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood filename == NULL ? "" : filename, 3311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood filename == NULL ? "" : " ", 3321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood strerror(errno)); 3331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return 0; 3341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && 3361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood st.st_size > MAX_KEY_FILE_SIZE) { 3371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood toobig: 3381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("%s: key file %.200s%stoo large", __func__, 3391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood filename == NULL ? "" : filename, 3401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood filename == NULL ? "" : " "); 3411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return 0; 3421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_init(blob); 3441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (;;) { 3451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) { 3461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (errno == EPIPE) 3471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 3481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("%s: read from key file %.200s%sfailed: %.100s", 3491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood __func__, filename == NULL ? "" : filename, 3501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood filename == NULL ? "" : " ", strerror(errno)); 3511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_clear(blob); 3521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood bzero(buf, sizeof(buf)); 3531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return 0; 3541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_append(blob, buf, len); 3561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (buffer_len(blob) > MAX_KEY_FILE_SIZE) { 3571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_clear(blob); 3581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood bzero(buf, sizeof(buf)); 3591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto toobig; 3601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood bzero(buf, sizeof(buf)); 3631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && 3641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood st.st_size != buffer_len(blob)) { 3651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("%s: key file %.200s%schanged size while reading", 3661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood __func__, filename == NULL ? "" : filename, 3671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood filename == NULL ? "" : " "); 3681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_clear(blob); 3691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return 0; 3701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return 1; 3731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 3741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 3761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Loads the public part of the ssh v1 key file. Returns NULL if an error was 3771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * encountered (the file does not exist or is not readable), and the key 3781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * otherwise. 3791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 3801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Key * 3811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_load_public_rsa1(int fd, const char *filename, char **commentp) 3821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 3831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Buffer buffer; 3841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Key *pub; 3851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_init(&buffer); 3871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!key_load_file(fd, filename, &buffer)) { 3881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(&buffer); 3891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 3901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pub = key_parse_public_rsa1(&buffer, commentp); 3931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (pub == NULL) 3941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug3("Could not load \"%s\" as a RSA1 public key", filename); 3951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(&buffer); 3961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return pub; 3971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 3981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* load public key from private-key file, works only for SSH v1 */ 4001305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodKey * 4011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_load_public_type(int type, const char *filename, char **commentp) 4021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 4031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Key *pub; 4041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int fd; 4051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (type == KEY_RSA1) { 4071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fd = open(filename, O_RDONLY); 4081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (fd < 0) 4091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 4101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pub = key_load_public_rsa1(fd, filename, commentp); 4111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood close(fd); 4121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return pub; 4131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 4151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 4161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Key * 4181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_parse_private_rsa1(Buffer *blob, const char *passphrase, char **commentp) 4191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 4201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int check1, check2, cipher_type; 4211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Buffer decrypted; 4221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_char *cp; 4231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CipherContext ciphercontext; 4241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Cipher *cipher; 4251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Key *prv = NULL; 4261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Buffer copy; 4271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Check that it is at least big enough to contain the ID string. */ 4291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (buffer_len(blob) < sizeof(authfile_id_string)) { 4301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug3("Truncated RSA1 identifier"); 4311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 4321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 4351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Make sure it begins with the id string. Consume the id string 4361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * from the buffer. 4371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 4381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (memcmp(buffer_ptr(blob), authfile_id_string, 4391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood sizeof(authfile_id_string)) != 0) { 4401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug3("Incorrect RSA1 identifier"); 4411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 4421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_init(©); 4441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_append(©, buffer_ptr(blob), buffer_len(blob)); 4451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_consume(©, sizeof(authfile_id_string)); 4461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Read cipher type. */ 4481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cipher_type = buffer_get_char(©); 4491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (void) buffer_get_int(©); /* Reserved data. */ 4501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Read the public key from the buffer. */ 4521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (void) buffer_get_int(©); 4531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood prv = key_new_private(KEY_RSA1); 4541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_get_bignum(©, prv->rsa->n); 4561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_get_bignum(©, prv->rsa->e); 4571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (commentp) 4581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *commentp = buffer_get_string(©, NULL); 4591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else 4601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (void)buffer_get_string_ptr(©, NULL); 4611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Check that it is a supported cipher. */ 4631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cipher = cipher_by_number(cipher_type); 4641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (cipher == NULL) { 4651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("Unsupported RSA1 cipher %d", cipher_type); 4661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(©); 4671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto fail; 4681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Initialize space for decrypted data. */ 4701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_init(&decrypted); 4711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cp = buffer_append_space(&decrypted, buffer_len(©)); 4721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ 4741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cipher_set_key_string(&ciphercontext, cipher, passphrase, 4751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CIPHER_DECRYPT); 4761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cipher_crypt(&ciphercontext, cp, 4771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_ptr(©), buffer_len(©)); 4781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cipher_cleanup(&ciphercontext); 4791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memset(&ciphercontext, 0, sizeof(ciphercontext)); 4801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(©); 4811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood check1 = buffer_get_char(&decrypted); 4831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood check2 = buffer_get_char(&decrypted); 4841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (check1 != buffer_get_char(&decrypted) || 4851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood check2 != buffer_get_char(&decrypted)) { 4861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (strcmp(passphrase, "") != 0) 4871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("Bad passphrase supplied for RSA1 key"); 4881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Bad passphrase. */ 4891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(&decrypted); 4901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto fail; 4911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Read the rest of the private key. */ 4931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_get_bignum(&decrypted, prv->rsa->d); 4941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_get_bignum(&decrypted, prv->rsa->iqmp); /* u */ 4951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* in SSL and SSH v1 p and q are exchanged */ 4961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_get_bignum(&decrypted, prv->rsa->q); /* p */ 4971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_get_bignum(&decrypted, prv->rsa->p); /* q */ 4981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* calculate p-1 and q-1 */ 5001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rsa_generate_additional_parameters(prv->rsa); 5011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(&decrypted); 5031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* enable blinding */ 5051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (RSA_blinding_on(prv->rsa, NULL) != 1) { 5061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("%s: RSA_blinding_on failed", __func__); 5071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto fail; 5081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return prv; 5101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodfail: 5121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (commentp) 5131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(*commentp); 5141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_free(prv); 5151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 5161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 5171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Key * 5191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_parse_private_pem(Buffer *blob, int type, const char *passphrase, 5201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char **commentp) 5211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 5221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood EVP_PKEY *pk = NULL; 5231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Key *prv = NULL; 5241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *name = "<no key>"; 5251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood BIO *bio; 5261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((bio = BIO_new_mem_buf(buffer_ptr(blob), 5281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_len(blob))) == NULL) { 5291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("%s: BIO_new_mem_buf failed", __func__); 5301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 5311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, (char *)passphrase); 5341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood BIO_free(bio); 5351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (pk == NULL) { 5361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("%s: PEM_read_PrivateKey failed", __func__); 5371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (void)ERR_get_error(); 5381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (pk->type == EVP_PKEY_RSA && 5391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (type == KEY_UNSPEC||type==KEY_RSA)) { 5401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood prv = key_new(KEY_UNSPEC); 5411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood prv->rsa = EVP_PKEY_get1_RSA(pk); 5421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood prv->type = KEY_RSA; 5431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood name = "rsa w/o comment"; 5441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef DEBUG_PK 5451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood RSA_print_fp(stderr, prv->rsa, 8); 5461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 5471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (RSA_blinding_on(prv->rsa, NULL) != 1) { 5481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("%s: RSA_blinding_on failed", __func__); 5491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_free(prv); 5501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood prv = NULL; 5511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (pk->type == EVP_PKEY_DSA && 5531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (type == KEY_UNSPEC||type==KEY_DSA)) { 5541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood prv = key_new(KEY_UNSPEC); 5551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood prv->dsa = EVP_PKEY_get1_DSA(pk); 5561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood prv->type = KEY_DSA; 5571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood name = "dsa w/o comment"; 5581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef DEBUG_PK 5591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood DSA_print_fp(stderr, prv->dsa, 8); 5601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 5611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC 5621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (pk->type == EVP_PKEY_EC && 5631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (type == KEY_UNSPEC||type==KEY_ECDSA)) { 5641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood prv = key_new(KEY_UNSPEC); 5651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood prv->ecdsa = EVP_PKEY_get1_EC_KEY(pk); 5661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood prv->type = KEY_ECDSA; 5671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((prv->ecdsa_nid = key_ecdsa_key_to_nid(prv->ecdsa)) == -1 || 5681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_curve_nid_to_name(prv->ecdsa_nid) == NULL || 5691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_ec_validate_public(EC_KEY_get0_group(prv->ecdsa), 5701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood EC_KEY_get0_public_key(prv->ecdsa)) != 0 || 5711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_ec_validate_private(prv->ecdsa) != 0) { 5721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("%s: bad ECDSA key", __func__); 5731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_free(prv); 5741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood prv = NULL; 5751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood name = "ecdsa w/o comment"; 5771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef DEBUG_PK 5781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (prv != NULL && prv->ecdsa != NULL) 5791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_dump_ec_key(prv->ecdsa); 5801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 5811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* OPENSSL_HAS_ECC */ 5821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 5831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("%s: PEM_read_PrivateKey: mismatch or " 5841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "unknown EVP_PKEY save_type %d", __func__, pk->save_type); 5851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (pk != NULL) 5871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood EVP_PKEY_free(pk); 5881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (prv != NULL && commentp) 5891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *commentp = xstrdup(name); 5901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("read PEM private key done: type %s", 5911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood prv ? key_type(prv) : "<unknown>"); 5921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return prv; 5931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 5941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5951305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodKey * 5961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_load_private_pem(int fd, int type, const char *passphrase, 5971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char **commentp) 5981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 5991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Buffer buffer; 6001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Key *prv; 6011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_init(&buffer); 6031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!key_load_file(fd, NULL, &buffer)) { 6041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(&buffer); 6051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 6061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 6071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood prv = key_parse_private_pem(&buffer, type, passphrase, commentp); 6081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(&buffer); 6091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return prv; 6101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 6111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint 6131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_perm_ok(int fd, const char *filename) 6141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 6151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct stat st; 6161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (fstat(fd, &st) < 0) 6181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return 0; 6191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 6201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * if a key owned by the user is accessed, then we check the 6211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * permissions of the file. if the key owned by a different user, 6221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * then we don't care. 6231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 6241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_CYGWIN 6251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (check_ntsec(filename)) 6261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 6271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) { 6281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 6291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @"); 6301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 6311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("Permissions 0%3.3o for '%s' are too open.", 6321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (u_int)st.st_mode & 0777, filename); 6331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("It is required that your private key files are NOT accessible by others."); 6341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("This private key will be ignored."); 6351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return 0; 6361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 6371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return 1; 6381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 6391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Key * 6411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_parse_private_type(Buffer *blob, int type, const char *passphrase, 6421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char **commentp) 6431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 6441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood switch (type) { 6451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case KEY_RSA1: 6461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return key_parse_private_rsa1(blob, passphrase, commentp); 6471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case KEY_DSA: 6481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case KEY_ECDSA: 6491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case KEY_RSA: 6501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case KEY_UNSPEC: 6511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return key_parse_private_pem(blob, type, passphrase, commentp); 6521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood default: 6531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("%s: cannot parse key type %d", __func__, type); 6541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 6551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 6561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 6571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 6581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6591305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodKey * 6601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_load_private_type(int type, const char *filename, const char *passphrase, 6611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char **commentp, int *perm_ok) 6621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 6631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int fd; 6641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Key *ret; 6651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Buffer buffer; 6661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fd = open(filename, O_RDONLY); 6681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (fd < 0) { 6691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("could not open key file '%s': %s", filename, 6701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood strerror(errno)); 6711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (perm_ok != NULL) 6721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *perm_ok = 0; 6731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 6741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 6751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!key_perm_ok(fd, filename)) { 6761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (perm_ok != NULL) 6771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *perm_ok = 0; 6781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("bad permissions: ignore key: %s", filename); 6791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood close(fd); 6801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 6811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 6821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (perm_ok != NULL) 6831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *perm_ok = 1; 6841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_init(&buffer); 6861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!key_load_file(fd, filename, &buffer)) { 6871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(&buffer); 6881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood close(fd); 6891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 6901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 6911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood close(fd); 6921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ret = key_parse_private_type(&buffer, type, passphrase, commentp); 6931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(&buffer); 6941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return ret; 6951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 6961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6971305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodKey * 6981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_parse_private(Buffer *buffer, const char *filename, 6991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const char *passphrase, char **commentp) 7001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 7011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Key *pub, *prv; 7021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* it's a SSH v1 key if the public key part is readable */ 7041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pub = key_parse_public_rsa1(buffer, commentp); 7051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (pub == NULL) { 7061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood prv = key_parse_private_type(buffer, KEY_UNSPEC, 7071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood passphrase, NULL); 7081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* use the filename as a comment for PEM */ 7091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (commentp && prv) 7101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *commentp = xstrdup(filename); 7111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 7121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_free(pub); 7131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* key_parse_public_rsa1() has already loaded the comment */ 7141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood prv = key_parse_private_type(buffer, KEY_RSA1, passphrase, 7151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood NULL); 7161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 7171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return prv; 7181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 7191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7201305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodKey * 7211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_load_private(const char *filename, const char *passphrase, 7221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char **commentp) 7231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 7241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Key *prv; 7251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Buffer buffer; 7261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int fd; 7271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fd = open(filename, O_RDONLY); 7291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (fd < 0) { 7301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("could not open key file '%s': %s", filename, 7311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood strerror(errno)); 7321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 7331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 7341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!key_perm_ok(fd, filename)) { 7351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("bad permissions: ignore key: %s", filename); 7361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood close(fd); 7371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 7381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 7391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_init(&buffer); 7411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!key_load_file(fd, filename, &buffer)) { 7421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(&buffer); 7431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood close(fd); 7441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 7451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 7461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood close(fd); 7471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood prv = key_parse_private(&buffer, filename, passphrase, commentp); 7491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(&buffer); 7501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return prv; 7511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 7521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 7541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_try_load_public(Key *k, const char *filename, char **commentp) 7551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 7561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood FILE *f; 7571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char line[SSH_MAX_PUBKEY_BYTES]; 7581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *cp; 7591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_long linenum = 0; 7601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood f = fopen(filename, "r"); 7621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (f != NULL) { 7631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood while (read_keyfile_line(f, filename, line, sizeof(line), 7641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood &linenum) != -1) { 7651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cp = line; 7661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood switch (*cp) { 7671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case '#': 7681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case '\n': 7691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case '\0': 7701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood continue; 7711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 7721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Abort loading if this looks like a private key */ 7731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (strncmp(cp, "-----BEGIN", 10) == 0) 7741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 7751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Skip leading whitespace. */ 7761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (; *cp && (*cp == ' ' || *cp == '\t'); cp++) 7771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ; 7781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (*cp) { 7791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (key_read(k, &cp) == 1) { 7801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cp[strcspn(cp, "\r\n")] = '\0'; 7811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (commentp) { 7821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *commentp = xstrdup(*cp ? 7831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cp : filename); 7841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 7851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fclose(f); 7861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return 1; 7871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 7881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 7891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 7901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fclose(f); 7911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 7921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return 0; 7931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 7941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* load public key from ssh v1 private or any pubkey file */ 7961305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodKey * 7971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_load_public(const char *filename, char **commentp) 7981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 7991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Key *pub; 8001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char file[MAXPATHLEN]; 8011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* try rsa1 private key */ 8031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pub = key_load_public_type(KEY_RSA1, filename, commentp); 8041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (pub != NULL) 8051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return pub; 8061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* try rsa1 public key */ 8081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pub = key_new(KEY_RSA1); 8091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (key_try_load_public(pub, filename, commentp) == 1) 8101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return pub; 8111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_free(pub); 8121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* try ssh2 public key */ 8141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pub = key_new(KEY_UNSPEC); 8151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (key_try_load_public(pub, filename, commentp) == 1) 8161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return pub; 8171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((strlcpy(file, filename, sizeof file) < sizeof(file)) && 8181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (strlcat(file, ".pub", sizeof file) < sizeof(file)) && 8191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (key_try_load_public(pub, file, commentp) == 1)) 8201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return pub; 8211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_free(pub); 8221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 8231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 8241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Load the certificate associated with the named private key */ 8261305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodKey * 8271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_load_cert(const char *filename) 8281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 8291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Key *pub; 8301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *file; 8311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pub = key_new(KEY_UNSPEC); 8331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xasprintf(&file, "%s-cert.pub", filename); 8341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (key_try_load_public(pub, file, NULL) == 1) { 8351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(file); 8361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return pub; 8371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 8381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(file); 8391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_free(pub); 8401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 8411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 8421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Load private key and certificate */ 8441305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodKey * 8451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_load_private_cert(int type, const char *filename, const char *passphrase, 8461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int *perm_ok) 8471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 8481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Key *key, *pub; 8491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood switch (type) { 8511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case KEY_RSA: 8521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case KEY_DSA: 8531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case KEY_ECDSA: 8541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 8551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood default: 8561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("%s: unsupported key type", __func__); 8571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 8581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 8591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((key = key_load_private_type(type, filename, 8611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood passphrase, NULL, perm_ok)) == NULL) 8621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 8631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((pub = key_load_cert(filename)) == NULL) { 8651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_free(key); 8661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 8671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 8681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Make sure the private key matches the certificate */ 8701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (key_equal_public(key, pub) == 0) { 8711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("%s: certificate does not match private key %s", 8721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood __func__, filename); 8731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (key_to_certified(key, key_cert_is_legacy(pub)) != 0) { 8741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("%s: key_to_certified failed", __func__); 8751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 8761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_cert_copy(pub, key); 8771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_free(pub); 8781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return key; 8791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 8801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_free(key); 8821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_free(pub); 8831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 8841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 8851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 8871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Returns 1 if the specified "key" is listed in the file "filename", 8881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 0 if the key is not listed or -1 on error. 8891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * If strict_type is set then the key type must match exactly, 8901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * otherwise a comparison that ignores certficiate data is performed. 8911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 8921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint 8931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkey_in_file(Key *key, const char *filename, int strict_type) 8941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 8951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood FILE *f; 8961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char line[SSH_MAX_PUBKEY_BYTES]; 8971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *cp; 8981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_long linenum = 0; 8991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int ret = 0; 9001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Key *pub; 9011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int (*key_compare)(const Key *, const Key *) = strict_type ? 9021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_equal : key_equal_public; 9031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 9041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((f = fopen(filename, "r")) == NULL) { 9051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (errno == ENOENT) { 9061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("%s: keyfile \"%s\" missing", __func__, filename); 9071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return 0; 9081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 9091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("%s: could not open keyfile \"%s\": %s", __func__, 9101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood filename, strerror(errno)); 9111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 9121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 9131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 9141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 9151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood while (read_keyfile_line(f, filename, line, sizeof(line), 9161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood &linenum) != -1) { 9171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cp = line; 9181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 9191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Skip leading whitespace. */ 9201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (; *cp && (*cp == ' ' || *cp == '\t'); cp++) 9211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ; 9221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 9231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Skip comments and empty lines */ 9241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood switch (*cp) { 9251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case '#': 9261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case '\n': 9271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case '\0': 9281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood continue; 9291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 9301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 9311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pub = key_new(KEY_UNSPEC); 9321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (key_read(pub, &cp) != 1) { 9331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_free(pub); 9341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood continue; 9351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 9361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (key_compare(key, pub)) { 9371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ret = 1; 9381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_free(pub); 9391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 9401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 9411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_free(pub); 9421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 9431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fclose(f); 9441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return ret; 9451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 9461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 947