Annotation of src/crypto/external/bsd/openssh/dist/ssh-keygen.c, Revision 1.30
1.29 christos 1: /* $NetBSD: ssh-keygen.c,v 1.28 2017/10/08 20:19:05 joerg Exp $ */
1.30 ! christos 2: /* $OpenBSD: ssh-keygen.c,v 1.314 2018/03/12 00:52:01 djm Exp $ */
1.1 christos 3: /*
4: * Author: Tatu Ylonen <ylo@cs.hut.fi>
5: * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
6: * All rights reserved
7: * Identity and host key generation and maintenance.
8: *
9: * As far as I am concerned, the code I have written for this software
10: * can be used freely for any purpose. Any derived versions of this
11: * software must be clearly marked as such, and if the derived work is
12: * incompatible with the protocol description in the RFC file, it must be
13: * called by a name other than "ssh" or "Secure Shell".
14: */
15:
1.2 christos 16: #include "includes.h"
1.29 christos 17: __RCSID("$NetBSD: ssh-keygen.c,v 1.28 2017/10/08 20:19:05 joerg Exp $");
1.1 christos 18: #include <sys/types.h>
1.3 christos 19: #include <sys/socket.h>
1.1 christos 20: #include <sys/stat.h>
21:
22: #include <openssl/evp.h>
23: #include <openssl/pem.h>
24:
25: #include <errno.h>
26: #include <fcntl.h>
1.14 christos 27: #include <netdb.h>
1.1 christos 28: #include <pwd.h>
29: #include <stdio.h>
30: #include <stdlib.h>
31: #include <string.h>
32: #include <unistd.h>
1.15 christos 33: #include <limits.h>
1.26 christos 34: #include <locale.h>
1.1 christos 35:
36: #include "xmalloc.h"
1.15 christos 37: #include "sshkey.h"
1.1 christos 38: #include "authfile.h"
39: #include "uuencode.h"
1.15 christos 40: #include "sshbuf.h"
1.1 christos 41: #include "pathnames.h"
42: #include "log.h"
43: #include "misc.h"
44: #include "match.h"
45: #include "hostfile.h"
46: #include "dns.h"
1.11 christos 47: #include "ssh.h"
1.4 adam 48: #include "ssh2.h"
1.15 christos 49: #include "ssherr.h"
1.11 christos 50: #include "atomicio.h"
51: #include "krl.h"
1.15 christos 52: #include "digest.h"
1.26 christos 53: #include "utf8.h"
1.27 christos 54: #include "authfd.h"
1.1 christos 55:
1.4 adam 56: #ifdef ENABLE_PKCS11
57: #include "ssh-pkcs11.h"
1.1 christos 58: #endif
59:
1.17 christos 60: #ifdef WITH_OPENSSL
61: # define DEFAULT_KEY_TYPE_NAME "rsa"
62: #else
63: # define DEFAULT_KEY_TYPE_NAME "ed25519"
64: #endif
65:
1.1 christos 66: /* Number of bits in the RSA/DSA key. This value can be set on the command line. */
67: #define DEFAULT_BITS 2048
68: #define DEFAULT_BITS_DSA 1024
1.6 christos 69: #define DEFAULT_BITS_ECDSA 256
1.1 christos 70: u_int32_t bits = 0;
71:
72: /*
73: * Flag indicating that we just want to change the passphrase. This can be
74: * set on the command line.
75: */
76: int change_passphrase = 0;
77:
78: /*
79: * Flag indicating that we just want to change the comment. This can be set
80: * on the command line.
81: */
82: int change_comment = 0;
83:
84: int quiet = 0;
85:
86: int log_level = SYSLOG_LEVEL_INFO;
87:
88: /* Flag indicating that we want to hash a known_hosts file */
89: int hash_hosts = 0;
90: /* Flag indicating that we want lookup a host in known_hosts file */
91: int find_host = 0;
92: /* Flag indicating that we want to delete a host from a known_hosts file */
93: int delete_host = 0;
94:
1.4 adam 95: /* Flag indicating that we want to show the contents of a certificate */
96: int show_cert = 0;
97:
1.1 christos 98: /* Flag indicating that we just want to see the key fingerprint */
99: int print_fingerprint = 0;
100: int print_bubblebabble = 0;
101:
1.15 christos 102: /* Hash algorithm to use for fingerprints. */
103: int fingerprint_hash = SSH_FP_HASH_DEFAULT;
104:
1.1 christos 105: /* The identity file name, given on the command line or entered by the user. */
106: char identity_file[1024];
107: int have_identity = 0;
108:
109: /* This is set to the passphrase if given on the command line. */
110: char *identity_passphrase = NULL;
111:
112: /* This is set to the new passphrase if given on the command line. */
113: char *identity_new_passphrase = NULL;
114:
115: /* This is set to the new comment if given on the command line. */
116: char *identity_comment = NULL;
117:
1.4 adam 118: /* Path to CA key when certifying keys. */
119: char *ca_key_path = NULL;
120:
1.27 christos 121: /* Prefer to use agent keys for CA signing */
122: int prefer_agent = 0;
123:
1.4 adam 124: /* Certificate serial number */
1.11 christos 125: unsigned long long cert_serial = 0;
1.4 adam 126:
127: /* Key type when certifying */
128: u_int cert_key_type = SSH2_CERT_TYPE_USER;
129:
130: /* "key ID" of signed key */
131: char *cert_key_id = NULL;
132:
133: /* Comma-separated list of principal names for certifying keys */
134: char *cert_principals = NULL;
135:
136: /* Validity period for certificates */
137: u_int64_t cert_valid_from = 0;
138: u_int64_t cert_valid_to = ~0ULL;
139:
140: /* Certificate options */
141: #define CERTOPT_X_FWD (1)
142: #define CERTOPT_AGENT_FWD (1<<1)
143: #define CERTOPT_PORT_FWD (1<<2)
144: #define CERTOPT_PTY (1<<3)
145: #define CERTOPT_USER_RC (1<<4)
146: #define CERTOPT_DEFAULT (CERTOPT_X_FWD|CERTOPT_AGENT_FWD| \
147: CERTOPT_PORT_FWD|CERTOPT_PTY|CERTOPT_USER_RC)
148: u_int32_t certflags_flags = CERTOPT_DEFAULT;
149: char *certflags_command = NULL;
150: char *certflags_src_addr = NULL;
151:
1.27 christos 152: /* Arbitrary extensions specified by user */
153: struct cert_userext {
154: char *key;
155: char *val;
156: int crit;
157: };
158: struct cert_userext *cert_userext;
159: size_t ncert_userext;
160:
1.4 adam 161: /* Conversion to/from various formats */
162: int convert_to = 0;
163: int convert_from = 0;
164: enum {
165: FMT_RFC4716,
166: FMT_PKCS8,
167: FMT_PEM
168: } convert_format = FMT_RFC4716;
1.1 christos 169: int print_public = 0;
170: int print_generic = 0;
171:
1.6 christos 172: const char *key_type_name = NULL;
1.1 christos 173:
1.4 adam 174: /* Load key from this PKCS#11 provider */
175: char *pkcs11provider = NULL;
176:
1.14 christos 177: /* Use new OpenSSH private key format when writing SSH2 keys instead of PEM */
178: int use_new_format = 0;
179:
180: /* Cipher for new-format private keys */
181: char *new_format_cipher = NULL;
182:
183: /*
184: * Number of KDF rounds to derive new format keys /
185: * number of primality trials when screening moduli.
186: */
187: int rounds = 0;
188:
1.1 christos 189: /* argv0 */
190: extern char *__progname;
191:
1.14 christos 192: char hostname[NI_MAXHOST];
1.1 christos 193:
1.17 christos 194: #ifdef WITH_OPENSSL
1.1 christos 195: /* moduli.c */
196: int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *);
1.10 christos 197: int prime_test(FILE *, FILE *, u_int32_t, u_int32_t, char *, unsigned long,
198: unsigned long);
1.17 christos 199: #endif
1.1 christos 200:
201: static void
1.15 christos 202: type_bits_valid(int type, const char *name, u_int32_t *bitsp)
1.7 christos 203: {
1.17 christos 204: #ifdef WITH_OPENSSL
1.15 christos 205: u_int maxbits, nid;
1.17 christos 206: #endif
1.7 christos 207:
1.17 christos 208: if (type == KEY_UNSPEC)
209: fatal("unknown key type %s", key_type_name);
1.7 christos 210: if (*bitsp == 0) {
1.17 christos 211: #ifdef WITH_OPENSSL
1.7 christos 212: if (type == KEY_DSA)
213: *bitsp = DEFAULT_BITS_DSA;
1.15 christos 214: else if (type == KEY_ECDSA) {
215: if (name != NULL &&
216: (nid = sshkey_ecdsa_nid_from_name(name)) > 0)
217: *bitsp = sshkey_curve_nid_to_bits(nid);
218: if (*bitsp == 0)
219: *bitsp = DEFAULT_BITS_ECDSA;
1.25 christos 220: } else
1.17 christos 221: #endif
1.7 christos 222: *bitsp = DEFAULT_BITS;
223: }
1.17 christos 224: #ifdef WITH_OPENSSL
1.7 christos 225: maxbits = (type == KEY_DSA) ?
226: OPENSSL_DSA_MAX_MODULUS_BITS : OPENSSL_RSA_MAX_MODULUS_BITS;
1.17 christos 227: if (*bitsp > maxbits)
228: fatal("key bits exceeds maximum %d", maxbits);
1.27 christos 229: switch (type) {
230: case KEY_DSA:
231: if (*bitsp != 1024)
232: fatal("Invalid DSA key length: must be 1024 bits");
233: break;
234: case KEY_RSA:
235: if (*bitsp < SSH_RSA_MINIMUM_MODULUS_SIZE)
236: fatal("Invalid RSA key length: minimum is %d bits",
237: SSH_RSA_MINIMUM_MODULUS_SIZE);
238: break;
239: case KEY_ECDSA:
240: if (sshkey_ecdsa_bits_to_nid(*bitsp) == -1)
241: fatal("Invalid ECDSA key length: valid lengths are "
242: "256, 384 or 521 bits");
243: }
1.14 christos 244: #endif
1.7 christos 245: }
246:
247: static void
1.1 christos 248: ask_filename(struct passwd *pw, const char *prompt)
249: {
250: char buf[1024];
1.6 christos 251: const char *name = NULL;
1.1 christos 252:
253: if (key_type_name == NULL)
254: name = _PATH_SSH_CLIENT_ID_RSA;
255: else {
1.15 christos 256: switch (sshkey_type_from_name(key_type_name)) {
1.4 adam 257: case KEY_DSA_CERT:
1.1 christos 258: case KEY_DSA:
259: name = _PATH_SSH_CLIENT_ID_DSA;
260: break;
1.6 christos 261: case KEY_ECDSA_CERT:
262: case KEY_ECDSA:
263: name = _PATH_SSH_CLIENT_ID_ECDSA;
264: break;
1.4 adam 265: case KEY_RSA_CERT:
1.1 christos 266: case KEY_RSA:
267: name = _PATH_SSH_CLIENT_ID_RSA;
268: break;
1.14 christos 269: case KEY_ED25519:
270: case KEY_ED25519_CERT:
271: name = _PATH_SSH_CLIENT_ID_ED25519;
272: break;
1.30 ! christos 273: case KEY_XMSS:
! 274: case KEY_XMSS_CERT:
! 275: name = _PATH_SSH_CLIENT_ID_XMSS;
! 276: break;
1.1 christos 277: default:
1.17 christos 278: fatal("bad key type");
1.1 christos 279: }
280: }
1.17 christos 281: snprintf(identity_file, sizeof(identity_file),
282: "%s/%s", pw->pw_dir, name);
283: printf("%s (%s): ", prompt, identity_file);
284: fflush(stdout);
1.1 christos 285: if (fgets(buf, sizeof(buf), stdin) == NULL)
286: exit(1);
287: buf[strcspn(buf, "\n")] = '\0';
288: if (strcmp(buf, "") != 0)
289: strlcpy(identity_file, buf, sizeof(identity_file));
290: have_identity = 1;
291: }
292:
1.15 christos 293: static struct sshkey *
1.1 christos 294: load_identity(char *filename)
295: {
296: char *pass;
1.15 christos 297: struct sshkey *prv;
298: int r;
1.1 christos 299:
1.15 christos 300: if ((r = sshkey_load_private(filename, "", &prv, NULL)) == 0)
301: return prv;
302: if (r != SSH_ERR_KEY_WRONG_PASSPHRASE)
303: fatal("Load key \"%s\": %s", filename, ssh_err(r));
304: if (identity_passphrase)
305: pass = xstrdup(identity_passphrase);
306: else
307: pass = read_passphrase("Enter passphrase: ", RP_ALLOW_STDIN);
308: r = sshkey_load_private(filename, pass, &prv, NULL);
309: explicit_bzero(pass, strlen(pass));
310: free(pass);
311: if (r != 0)
312: fatal("Load key \"%s\": %s", filename, ssh_err(r));
1.1 christos 313: return prv;
314: }
315:
316: #define SSH_COM_PUBLIC_BEGIN "---- BEGIN SSH2 PUBLIC KEY ----"
317: #define SSH_COM_PUBLIC_END "---- END SSH2 PUBLIC KEY ----"
318: #define SSH_COM_PRIVATE_BEGIN "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"
319: #define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb
320:
1.14 christos 321: #ifdef WITH_OPENSSL
1.16 joerg 322: __dead static void
1.15 christos 323: do_convert_to_ssh2(struct passwd *pw, struct sshkey *k)
1.1 christos 324: {
1.15 christos 325: size_t len;
1.1 christos 326: u_char *blob;
1.4 adam 327: char comment[61];
1.15 christos 328: int r;
1.4 adam 329:
1.17 christos 330: if ((r = sshkey_to_blob(k, &blob, &len)) != 0)
331: fatal("key_to_blob failed: %s", ssh_err(r));
1.4 adam 332: /* Comment + surrounds must fit into 72 chars (RFC 4716 sec 3.3) */
333: snprintf(comment, sizeof(comment),
334: "%u-bit %s, converted by %s@%s from OpenSSH",
1.15 christos 335: sshkey_size(k), sshkey_type(k),
1.4 adam 336: pw->pw_name, hostname);
337:
338: fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN);
339: fprintf(stdout, "Comment: \"%s\"\n", comment);
340: dump_base64(stdout, blob, len);
341: fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END);
1.15 christos 342: sshkey_free(k);
1.13 christos 343: free(blob);
1.4 adam 344: exit(0);
345: }
346:
1.8 joerg 347: __dead static void
1.15 christos 348: do_convert_to_pkcs8(struct sshkey *k)
1.4 adam 349: {
1.15 christos 350: switch (sshkey_type_plain(k->type)) {
1.4 adam 351: case KEY_RSA:
352: if (!PEM_write_RSA_PUBKEY(stdout, k->rsa))
353: fatal("PEM_write_RSA_PUBKEY failed");
354: break;
355: case KEY_DSA:
356: if (!PEM_write_DSA_PUBKEY(stdout, k->dsa))
357: fatal("PEM_write_DSA_PUBKEY failed");
358: break;
1.6 christos 359: case KEY_ECDSA:
360: if (!PEM_write_EC_PUBKEY(stdout, k->ecdsa))
361: fatal("PEM_write_EC_PUBKEY failed");
362: break;
1.4 adam 363: default:
1.15 christos 364: fatal("%s: unsupported key type %s", __func__, sshkey_type(k));
1.4 adam 365: }
366: exit(0);
367: }
368:
1.8 joerg 369: __dead static void
1.15 christos 370: do_convert_to_pem(struct sshkey *k)
1.4 adam 371: {
1.15 christos 372: switch (sshkey_type_plain(k->type)) {
1.4 adam 373: case KEY_RSA:
374: if (!PEM_write_RSAPublicKey(stdout, k->rsa))
375: fatal("PEM_write_RSAPublicKey failed");
376: break;
377: default:
1.15 christos 378: fatal("%s: unsupported key type %s", __func__, sshkey_type(k));
1.4 adam 379: }
380: exit(0);
381: }
382:
1.8 joerg 383: __dead static void
1.4 adam 384: do_convert_to(struct passwd *pw)
385: {
1.15 christos 386: struct sshkey *k;
1.1 christos 387: struct stat st;
1.15 christos 388: int r;
1.1 christos 389:
390: if (!have_identity)
391: ask_filename(pw, "Enter file in which the key is");
1.4 adam 392: if (stat(identity_file, &st) < 0)
393: fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
1.15 christos 394: if ((r = sshkey_load_public(identity_file, &k, NULL)) != 0)
395: k = load_identity(identity_file);
1.4 adam 396: switch (convert_format) {
397: case FMT_RFC4716:
398: do_convert_to_ssh2(pw, k);
399: break;
400: case FMT_PKCS8:
401: do_convert_to_pkcs8(k);
402: break;
403: case FMT_PEM:
404: do_convert_to_pem(k);
405: break;
406: default:
407: fatal("%s: unknown key format %d", __func__, convert_format);
1.1 christos 408: }
409: exit(0);
410: }
411:
1.15 christos 412: /*
413: * This is almost exactly the bignum1 encoding, but with 32 bit for length
414: * instead of 16.
415: */
1.1 christos 416: static void
1.15 christos 417: buffer_get_bignum_bits(struct sshbuf *b, BIGNUM *value)
1.1 christos 418: {
1.15 christos 419: u_int bytes, bignum_bits;
420: int r;
1.1 christos 421:
1.15 christos 422: if ((r = sshbuf_get_u32(b, &bignum_bits)) != 0)
423: fatal("%s: buffer error: %s", __func__, ssh_err(r));
424: bytes = (bignum_bits + 7) / 8;
425: if (sshbuf_len(b) < bytes)
426: fatal("%s: input buffer too small: need %d have %zu",
427: __func__, bytes, sshbuf_len(b));
428: if (BN_bin2bn(sshbuf_ptr(b), bytes, value) == NULL)
429: fatal("%s: BN_bin2bn failed", __func__);
430: if ((r = sshbuf_consume(b, bytes)) != 0)
431: fatal("%s: buffer error: %s", __func__, ssh_err(r));
1.1 christos 432: }
433:
1.15 christos 434: static struct sshkey *
1.1 christos 435: do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
436: {
1.15 christos 437: struct sshbuf *b;
438: struct sshkey *key = NULL;
1.1 christos 439: char *type, *cipher;
1.15 christos 440: u_char e1, e2, e3, *sig = NULL, data[] = "abcde12345";
441: int r, rlen, ktype;
442: u_int magic, i1, i2, i3, i4;
443: size_t slen;
1.1 christos 444: u_long e;
445:
1.15 christos 446: if ((b = sshbuf_from(blob, blen)) == NULL)
447: fatal("%s: sshbuf_from failed", __func__);
448: if ((r = sshbuf_get_u32(b, &magic)) != 0)
449: fatal("%s: buffer error: %s", __func__, ssh_err(r));
1.1 christos 450:
451: if (magic != SSH_COM_PRIVATE_KEY_MAGIC) {
1.15 christos 452: error("bad magic 0x%x != 0x%x", magic,
453: SSH_COM_PRIVATE_KEY_MAGIC);
454: sshbuf_free(b);
1.1 christos 455: return NULL;
456: }
1.15 christos 457: if ((r = sshbuf_get_u32(b, &i1)) != 0 ||
458: (r = sshbuf_get_cstring(b, &type, NULL)) != 0 ||
459: (r = sshbuf_get_cstring(b, &cipher, NULL)) != 0 ||
460: (r = sshbuf_get_u32(b, &i2)) != 0 ||
461: (r = sshbuf_get_u32(b, &i3)) != 0 ||
462: (r = sshbuf_get_u32(b, &i4)) != 0)
463: fatal("%s: buffer error: %s", __func__, ssh_err(r));
1.1 christos 464: debug("ignore (%d %d %d %d)", i1, i2, i3, i4);
465: if (strcmp(cipher, "none") != 0) {
466: error("unsupported cipher %s", cipher);
1.13 christos 467: free(cipher);
1.15 christos 468: sshbuf_free(b);
1.13 christos 469: free(type);
1.1 christos 470: return NULL;
471: }
1.13 christos 472: free(cipher);
1.1 christos 473:
474: if (strstr(type, "dsa")) {
475: ktype = KEY_DSA;
476: } else if (strstr(type, "rsa")) {
477: ktype = KEY_RSA;
478: } else {
1.15 christos 479: sshbuf_free(b);
1.13 christos 480: free(type);
1.1 christos 481: return NULL;
482: }
1.15 christos 483: if ((key = sshkey_new_private(ktype)) == NULL)
1.27 christos 484: fatal("sshkey_new_private failed");
1.13 christos 485: free(type);
1.1 christos 486:
487: switch (key->type) {
488: case KEY_DSA:
1.29 christos 489: {
490: BIGNUM *p=NULL, *g=NULL, *q=NULL, *pub_key=NULL, *priv_key=NULL;
491: if ((p=BN_new()) == NULL ||
492: (g=BN_new()) == NULL ||
493: (q=BN_new()) == NULL ||
494: (pub_key=BN_new()) == NULL ||
495: (priv_key=BN_new()) == NULL) {
496: BN_free(p);
497: BN_free(g);
498: BN_free(q);
499: BN_free(pub_key);
500: BN_free(priv_key);
501: return NULL;
502: }
503: buffer_get_bignum_bits(b, p);
504: buffer_get_bignum_bits(b, g);
505: buffer_get_bignum_bits(b, q);
506: buffer_get_bignum_bits(b, pub_key);
507: buffer_get_bignum_bits(b, priv_key);
508: if (DSA_set0_pqg(key->dsa, p, q, g) == 0 ||
509: DSA_set0_key(key->dsa, pub_key, priv_key) == 0) {
510: fatal("failed to set DSA key");
511: BN_free(p); BN_free(g); BN_free(q);
512: BN_free(pub_key); BN_free(priv_key);
513: return NULL;
514: }
515: }
1.1 christos 516: break;
517: case KEY_RSA:
1.15 christos 518: if ((r = sshbuf_get_u8(b, &e1)) != 0 ||
519: (e1 < 30 && (r = sshbuf_get_u8(b, &e2)) != 0) ||
520: (e1 < 30 && (r = sshbuf_get_u8(b, &e3)) != 0))
521: fatal("%s: buffer error: %s", __func__, ssh_err(r));
522: e = e1;
1.1 christos 523: debug("e %lx", e);
524: if (e < 30) {
525: e <<= 8;
1.15 christos 526: e += e2;
1.1 christos 527: debug("e %lx", e);
528: e <<= 8;
1.15 christos 529: e += e3;
1.1 christos 530: debug("e %lx", e);
531: }
1.29 christos 532: {
533: BIGNUM *rsa_e = NULL;
534: BIGNUM *d=NULL, *n=NULL, *iqmp=NULL, *q=NULL, *p=NULL;
535: BIGNUM *dmp1=NULL, *dmq1=NULL; /* dummy input to set in RSA_set0_crt_params */
536: rsa_e = BN_new();
537: if (!rsa_e || !BN_set_word(rsa_e, e)) {
538: if (rsa_e) BN_free(rsa_e);
1.15 christos 539: sshbuf_free(b);
540: sshkey_free(key);
1.1 christos 541: return NULL;
542: }
1.29 christos 543: if ((d=BN_new()) == NULL ||
544: (n=BN_new()) == NULL ||
545: (iqmp=BN_new()) == NULL ||
546: (q=BN_new()) == NULL ||
547: (p=BN_new()) == NULL ||
548: (dmp1=BN_new()) == NULL ||
549: (dmq1=BN_new()) == NULL) {
550: BN_free(d); BN_free(n); BN_free(iqmp);
551: BN_free(q); BN_free(p);
552: BN_free(dmp1); BN_free(dmq1);
553: return NULL;
554: }
555: BN_clear(dmp1); BN_clear(dmq1);
556: buffer_get_bignum_bits(b, d);
557: buffer_get_bignum_bits(b, n);
558: buffer_get_bignum_bits(b, iqmp);
559: buffer_get_bignum_bits(b, q);
560: buffer_get_bignum_bits(b, p);
561: if (RSA_set0_key(key->rsa, n, rsa_e, d) == 0)
562: goto null;
563: n = d = NULL;
564: if (RSA_set0_factors(key->rsa, p, q) == 0)
565: goto null;
566: p = q = NULL;
567: /* dmp1, dmq1 should not be NULL for initial set0 */
568: if (RSA_set0_crt_params(key->rsa, dmp1, dmq1, iqmp) == 0) {
569: null:
570: fatal("Failed to set RSA parameters");
571: BN_free(d); BN_free(n); BN_free(iqmp);
572: BN_free(q); BN_free(p);
573: BN_free(dmp1); BN_free(dmq1);
574: return NULL;
575: }
576: dmp1 = dmq1 = iqmp = NULL;
577: }
1.27 christos 578: if ((r = ssh_rsa_generate_additional_parameters(key)) != 0)
1.15 christos 579: fatal("generate RSA parameters failed: %s", ssh_err(r));
1.1 christos 580: break;
581: }
1.15 christos 582: rlen = sshbuf_len(b);
1.1 christos 583: if (rlen != 0)
584: error("do_convert_private_ssh2_from_blob: "
585: "remaining bytes in key blob %d", rlen);
1.15 christos 586: sshbuf_free(b);
1.1 christos 587:
588: /* try the key */
1.20 christos 589: if (sshkey_sign(key, &sig, &slen, data, sizeof(data), NULL, 0) != 0 ||
1.30 ! christos 590: sshkey_verify(key, sig, slen, data, sizeof(data), NULL, 0) != 0) {
1.15 christos 591: sshkey_free(key);
592: free(sig);
593: return NULL;
594: }
1.13 christos 595: free(sig);
1.1 christos 596: return key;
597: }
598:
599: static int
600: get_line(FILE *fp, char *line, size_t len)
601: {
602: int c;
603: size_t pos = 0;
604:
605: line[0] = '\0';
606: while ((c = fgetc(fp)) != EOF) {
1.17 christos 607: if (pos >= len - 1)
608: fatal("input line too long.");
1.1 christos 609: switch (c) {
610: case '\r':
611: c = fgetc(fp);
1.17 christos 612: if (c != EOF && c != '\n' && ungetc(c, fp) == EOF)
613: fatal("unget: %s", strerror(errno));
1.1 christos 614: return pos;
615: case '\n':
616: return pos;
617: }
618: line[pos++] = c;
619: line[pos] = '\0';
620: }
621: /* We reached EOF */
622: return -1;
623: }
624:
625: static void
1.15 christos 626: do_convert_from_ssh2(struct passwd *pw, struct sshkey **k, int *private)
1.1 christos 627: {
1.15 christos 628: int r, blen, escaped = 0;
1.1 christos 629: u_int len;
630: char line[1024];
631: u_char blob[8096];
632: char encoded[8096];
633: FILE *fp;
634:
1.4 adam 635: if ((fp = fopen(identity_file, "r")) == NULL)
636: fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
1.1 christos 637: encoded[0] = '\0';
638: while ((blen = get_line(fp, line, sizeof(line))) != -1) {
1.13 christos 639: if (blen > 0 && line[blen - 1] == '\\')
1.1 christos 640: escaped++;
641: if (strncmp(line, "----", 4) == 0 ||
642: strstr(line, ": ") != NULL) {
643: if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL)
1.4 adam 644: *private = 1;
1.1 christos 645: if (strstr(line, " END ") != NULL) {
646: break;
647: }
648: /* fprintf(stderr, "ignore: %s", line); */
649: continue;
650: }
651: if (escaped) {
652: escaped--;
653: /* fprintf(stderr, "escaped: %s", line); */
654: continue;
655: }
656: strlcat(encoded, line, sizeof(encoded));
657: }
658: len = strlen(encoded);
659: if (((len % 4) == 3) &&
660: (encoded[len-1] == '=') &&
661: (encoded[len-2] == '=') &&
662: (encoded[len-3] == '='))
663: encoded[len-3] = '\0';
664: blen = uudecode(encoded, blob, sizeof(blob));
1.17 christos 665: if (blen < 0)
666: fatal("uudecode failed.");
1.15 christos 667: if (*private)
668: *k = do_convert_private_ssh2_from_blob(blob, blen);
1.17 christos 669: else if ((r = sshkey_from_blob(blob, blen, k)) != 0)
670: fatal("decode blob failed: %s", ssh_err(r));
1.4 adam 671: fclose(fp);
672: }
673:
674: static void
1.15 christos 675: do_convert_from_pkcs8(struct sshkey **k, int *private)
1.4 adam 676: {
677: EVP_PKEY *pubkey;
678: FILE *fp;
679:
680: if ((fp = fopen(identity_file, "r")) == NULL)
681: fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
682: if ((pubkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) {
683: fatal("%s: %s is not a recognised public key format", __func__,
684: identity_file);
1.1 christos 685: }
686: fclose(fp);
1.29 christos 687: switch (EVP_PKEY_type(EVP_PKEY_id(pubkey))) {
1.4 adam 688: case EVP_PKEY_RSA:
1.15 christos 689: if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
690: fatal("sshkey_new failed");
1.4 adam 691: (*k)->type = KEY_RSA;
692: (*k)->rsa = EVP_PKEY_get1_RSA(pubkey);
693: break;
694: case EVP_PKEY_DSA:
1.15 christos 695: if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
696: fatal("sshkey_new failed");
1.4 adam 697: (*k)->type = KEY_DSA;
698: (*k)->dsa = EVP_PKEY_get1_DSA(pubkey);
699: break;
1.6 christos 700: case EVP_PKEY_EC:
1.15 christos 701: if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
702: fatal("sshkey_new failed");
1.6 christos 703: (*k)->type = KEY_ECDSA;
704: (*k)->ecdsa = EVP_PKEY_get1_EC_KEY(pubkey);
1.15 christos 705: (*k)->ecdsa_nid = sshkey_ecdsa_key_to_nid((*k)->ecdsa);
1.6 christos 706: break;
1.4 adam 707: default:
708: fatal("%s: unsupported pubkey type %d", __func__,
1.29 christos 709: EVP_PKEY_type(EVP_PKEY_id(pubkey)));
1.4 adam 710: }
711: EVP_PKEY_free(pubkey);
712: return;
713: }
714:
715: static void
1.15 christos 716: do_convert_from_pem(struct sshkey **k, int *private)
1.4 adam 717: {
718: FILE *fp;
719: RSA *rsa;
720:
721: if ((fp = fopen(identity_file, "r")) == NULL)
722: fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
723: if ((rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL)) != NULL) {
1.15 christos 724: if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
725: fatal("sshkey_new failed");
1.4 adam 726: (*k)->type = KEY_RSA;
727: (*k)->rsa = rsa;
728: fclose(fp);
729: return;
730: }
731: fatal("%s: unrecognised raw private key format", __func__);
1.1 christos 732: }
733:
1.8 joerg 734: __dead static void
1.4 adam 735: do_convert_from(struct passwd *pw)
1.1 christos 736: {
1.15 christos 737: struct sshkey *k = NULL;
738: int r, private = 0, ok = 0;
1.1 christos 739: struct stat st;
740:
741: if (!have_identity)
742: ask_filename(pw, "Enter file in which the key is");
1.4 adam 743: if (stat(identity_file, &st) < 0)
744: fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
745:
746: switch (convert_format) {
747: case FMT_RFC4716:
748: do_convert_from_ssh2(pw, &k, &private);
749: break;
750: case FMT_PKCS8:
751: do_convert_from_pkcs8(&k, &private);
752: break;
753: case FMT_PEM:
754: do_convert_from_pem(&k, &private);
755: break;
756: default:
757: fatal("%s: unknown key format %d", __func__, convert_format);
758: }
759:
1.15 christos 760: if (!private) {
761: if ((r = sshkey_write(k, stdout)) == 0)
762: ok = 1;
1.4 adam 763: if (ok)
764: fprintf(stdout, "\n");
1.15 christos 765: } else {
1.4 adam 766: switch (k->type) {
767: case KEY_DSA:
768: ok = PEM_write_DSAPrivateKey(stdout, k->dsa, NULL,
769: NULL, 0, NULL, NULL);
770: break;
1.6 christos 771: case KEY_ECDSA:
772: ok = PEM_write_ECPrivateKey(stdout, k->ecdsa, NULL,
773: NULL, 0, NULL, NULL);
774: break;
1.4 adam 775: case KEY_RSA:
776: ok = PEM_write_RSAPrivateKey(stdout, k->rsa, NULL,
777: NULL, 0, NULL, NULL);
778: break;
779: default:
780: fatal("%s: unsupported key type %s", __func__,
1.15 christos 781: sshkey_type(k));
1.4 adam 782: }
1.1 christos 783: }
1.4 adam 784:
1.17 christos 785: if (!ok)
786: fatal("key write failed");
1.15 christos 787: sshkey_free(k);
1.1 christos 788: exit(0);
789: }
1.14 christos 790: #endif
1.1 christos 791:
1.8 joerg 792: __dead static void
1.4 adam 793: do_print_public(struct passwd *pw)
1.1 christos 794: {
1.15 christos 795: struct sshkey *prv;
1.1 christos 796: struct stat st;
1.15 christos 797: int r;
1.1 christos 798:
799: if (!have_identity)
800: ask_filename(pw, "Enter file in which the key is");
1.17 christos 801: if (stat(identity_file, &st) < 0)
802: fatal("%s: %s", identity_file, strerror(errno));
1.1 christos 803: prv = load_identity(identity_file);
1.15 christos 804: if ((r = sshkey_write(prv, stdout)) != 0)
1.27 christos 805: error("sshkey_write failed: %s", ssh_err(r));
1.15 christos 806: sshkey_free(prv);
1.4 adam 807: fprintf(stdout, "\n");
1.1 christos 808: exit(0);
809: }
810:
1.8 joerg 811: __dead static void
1.4 adam 812: do_download(struct passwd *pw)
1.1 christos 813: {
1.4 adam 814: #ifdef ENABLE_PKCS11
1.15 christos 815: struct sshkey **keys = NULL;
1.4 adam 816: int i, nkeys;
1.15 christos 817: enum sshkey_fp_rep rep;
818: int fptype;
1.11 christos 819: char *fp, *ra;
820:
1.15 christos 821: fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash;
822: rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
1.1 christos 823:
1.4 adam 824: pkcs11_init(0);
825: nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys);
826: if (nkeys <= 0)
827: fatal("cannot read public key from pkcs11");
828: for (i = 0; i < nkeys; i++) {
1.11 christos 829: if (print_fingerprint) {
1.15 christos 830: fp = sshkey_fingerprint(keys[i], fptype, rep);
831: ra = sshkey_fingerprint(keys[i], fingerprint_hash,
1.11 christos 832: SSH_FP_RANDOMART);
1.15 christos 833: if (fp == NULL || ra == NULL)
834: fatal("%s: sshkey_fingerprint fail", __func__);
835: printf("%u %s %s (PKCS11 key)\n", sshkey_size(keys[i]),
836: fp, sshkey_type(keys[i]));
1.11 christos 837: if (log_level >= SYSLOG_LEVEL_VERBOSE)
838: printf("%s\n", ra);
1.13 christos 839: free(ra);
840: free(fp);
1.11 christos 841: } else {
1.15 christos 842: (void) sshkey_write(keys[i], stdout); /* XXX check */
1.11 christos 843: fprintf(stdout, "\n");
844: }
1.15 christos 845: sshkey_free(keys[i]);
1.1 christos 846: }
1.13 christos 847: free(keys);
1.4 adam 848: pkcs11_terminate();
1.1 christos 849: exit(0);
1.4 adam 850: #else
851: fatal("no pkcs11 support");
852: #endif /* ENABLE_PKCS11 */
1.1 christos 853: }
854:
1.20 christos 855: static struct sshkey *
856: try_read_key(char **cpp)
857: {
858: struct sshkey *ret;
859: int r;
860:
861: if ((ret = sshkey_new(KEY_UNSPEC)) == NULL)
862: fatal("sshkey_new failed");
863: if ((r = sshkey_read(ret, cpp)) == 0)
864: return ret;
865: /* Not a key */
866: sshkey_free(ret);
867: return NULL;
868: }
869:
1.21 christos 870: static void
1.20 christos 871: fingerprint_one_key(const struct sshkey *public, const char *comment)
1.1 christos 872: {
1.20 christos 873: char *fp = NULL, *ra = NULL;
1.15 christos 874: enum sshkey_fp_rep rep;
875: int fptype;
1.1 christos 876:
1.15 christos 877: fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash;
878: rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
1.20 christos 879: fp = sshkey_fingerprint(public, fptype, rep);
880: ra = sshkey_fingerprint(public, fingerprint_hash, SSH_FP_RANDOMART);
881: if (fp == NULL || ra == NULL)
882: fatal("%s: sshkey_fingerprint failed", __func__);
1.26 christos 883: mprintf("%u %s %s (%s)\n", sshkey_size(public), fp,
1.20 christos 884: comment ? comment : "no comment", sshkey_type(public));
885: if (log_level >= SYSLOG_LEVEL_VERBOSE)
886: printf("%s\n", ra);
887: free(ra);
888: free(fp);
889: }
890:
891: static void
892: fingerprint_private(const char *path)
893: {
894: struct stat st;
895: char *comment = NULL;
896: struct sshkey *public = NULL;
897: int r;
898:
1.17 christos 899: if (stat(identity_file, &st) < 0)
1.20 christos 900: fatal("%s: %s", path, strerror(errno));
901: if ((r = sshkey_load_public(path, &public, &comment)) != 0) {
902: debug("load public \"%s\": %s", path, ssh_err(r));
903: if ((r = sshkey_load_private(path, NULL,
904: &public, &comment)) != 0) {
905: debug("load private \"%s\": %s", path, ssh_err(r));
906: fatal("%s is not a key file.", path);
907: }
1.1 christos 908: }
909:
1.20 christos 910: fingerprint_one_key(public, comment);
911: sshkey_free(public);
912: free(comment);
913: }
914:
1.21 christos 915: __dead static void
1.20 christos 916: do_fingerprint(struct passwd *pw)
917: {
918: FILE *f;
919: struct sshkey *public = NULL;
920: char *comment = NULL, *cp, *ep, line[SSH_MAX_PUBKEY_BYTES];
921: int i, invalid = 1;
922: const char *path;
1.24 christos 923: u_long lnum = 0;
1.20 christos 924:
925: if (!have_identity)
926: ask_filename(pw, "Enter file in which the key is");
927: path = identity_file;
1.4 adam 928:
1.20 christos 929: if (strcmp(identity_file, "-") == 0) {
930: f = stdin;
931: path = "(stdin)";
932: } else if ((f = fopen(path, "r")) == NULL)
933: fatal("%s: %s: %s", __progname, path, strerror(errno));
934:
935: while (read_keyfile_line(f, path, line, sizeof(line), &lnum) == 0) {
936: cp = line;
937: cp[strcspn(cp, "\n")] = '\0';
938: /* Trim leading space and comments */
939: cp = line + strspn(line, " \t");
940: if (*cp == '#' || *cp == '\0')
1.4 adam 941: continue;
1.20 christos 942:
943: /*
944: * Input may be plain keys, private keys, authorized_keys
945: * or known_hosts.
946: */
947:
948: /*
949: * Try private keys first. Assume a key is private if
950: * "SSH PRIVATE KEY" appears on the first line and we're
951: * not reading from stdin (XXX support private keys on stdin).
952: */
953: if (lnum == 1 && strcmp(identity_file, "-") != 0 &&
954: strstr(cp, "PRIVATE KEY") != NULL) {
955: fclose(f);
956: fingerprint_private(path);
957: exit(0);
958: }
959:
960: /*
961: * If it's not a private key, then this must be prepared to
962: * accept a public key prefixed with a hostname or options.
963: * Try a bare key first, otherwise skip the leading stuff.
964: */
965: if ((public = try_read_key(&cp)) == NULL) {
966: i = strtol(cp, &ep, 10);
967: if (i == 0 || ep == NULL ||
968: (*ep != ' ' && *ep != '\t')) {
969: int quoted = 0;
970:
971: comment = cp;
972: for (; *cp && (quoted || (*cp != ' ' &&
973: *cp != '\t')); cp++) {
974: if (*cp == '\\' && cp[1] == '"')
975: cp++; /* Skip both */
976: else if (*cp == '"')
977: quoted = !quoted;
978: }
979: if (!*cp)
980: continue;
981: *cp++ = '\0';
982: }
1.4 adam 983: }
1.20 christos 984: /* Retry after parsing leading hostname/key options */
985: if (public == NULL && (public = try_read_key(&cp)) == NULL) {
1.24 christos 986: debug("%s:%lu: not a public key", path, lnum);
1.4 adam 987: continue;
988: }
989:
1.20 christos 990: /* Find trailing comment, if any */
991: for (; *cp == ' ' || *cp == '\t'; cp++)
1.4 adam 992: ;
1.20 christos 993: if (*cp != '\0' && *cp != '#')
1.4 adam 994: comment = cp;
1.20 christos 995:
996: fingerprint_one_key(public, comment);
1.15 christos 997: sshkey_free(public);
1.20 christos 998: invalid = 0; /* One good key in the file is sufficient */
1.1 christos 999: }
1.4 adam 1000: fclose(f);
1001:
1.17 christos 1002: if (invalid)
1.20 christos 1003: fatal("%s is not a public key file.", path);
1.1 christos 1004: exit(0);
1005: }
1006:
1007: static void
1.7 christos 1008: do_gen_all_hostkeys(struct passwd *pw)
1009: {
1010: struct {
1011: const char *key_type;
1012: const char *key_type_display;
1013: const char *path;
1014: } key_types[] = {
1.17 christos 1015: #ifdef WITH_OPENSSL
1.7 christos 1016: { "rsa", "RSA" ,_PATH_HOST_RSA_KEY_FILE },
1017: { "dsa", "DSA", _PATH_HOST_DSA_KEY_FILE },
1018: { "ecdsa", "ECDSA",_PATH_HOST_ECDSA_KEY_FILE },
1.17 christos 1019: #endif /* WITH_OPENSSL */
1.14 christos 1020: { "ed25519", "ED25519",_PATH_HOST_ED25519_KEY_FILE },
1.30 ! christos 1021: #ifdef WITH_XMSS
! 1022: { "xmss", "XMSS",_PATH_HOST_XMSS_KEY_FILE },
! 1023: #endif /* WITH_XMSS */
1.7 christos 1024: { NULL, NULL, NULL }
1025: };
1026:
1027: int first = 0;
1028: struct stat st;
1.15 christos 1029: struct sshkey *private, *public;
1.27 christos 1030: char comment[1024], *prv_tmp, *pub_tmp, *prv_file, *pub_file;
1.15 christos 1031: int i, type, fd, r;
1.7 christos 1032: FILE *f;
1033:
1034: for (i = 0; key_types[i].key_type; i++) {
1.27 christos 1035: public = private = NULL;
1036: prv_tmp = pub_tmp = prv_file = pub_file = NULL;
1037:
1038: xasprintf(&prv_file, "%s%s",
1039: identity_file, key_types[i].path);
1040:
1041: /* Check whether private key exists and is not zero-length */
1042: if (stat(prv_file, &st) == 0) {
1043: if (st.st_size != 0)
1044: goto next;
1045: } else if (errno != ENOENT) {
1.17 christos 1046: error("Could not stat %s: %s", key_types[i].path,
1.7 christos 1047: strerror(errno));
1.27 christos 1048: goto failnext;
1.7 christos 1049: }
1050:
1.27 christos 1051: /*
1052: * Private key doesn't exist or is invalid; proceed with
1053: * key generation.
1054: */
1055: xasprintf(&prv_tmp, "%s%s.XXXXXXXXXX",
1056: identity_file, key_types[i].path);
1057: xasprintf(&pub_tmp, "%s%s.pub.XXXXXXXXXX",
1058: identity_file, key_types[i].path);
1059: xasprintf(&pub_file, "%s%s.pub",
1060: identity_file, key_types[i].path);
1061:
1.7 christos 1062: if (first == 0) {
1063: first = 1;
1064: printf("%s: generating new host keys: ", __progname);
1065: }
1066: printf("%s ", key_types[i].key_type_display);
1067: fflush(stdout);
1.15 christos 1068: type = sshkey_type_from_name(key_types[i].key_type);
1.27 christos 1069: if ((fd = mkstemp(prv_tmp)) == -1) {
1070: error("Could not save your public key in %s: %s",
1071: prv_tmp, strerror(errno));
1072: goto failnext;
1073: }
1074: close(fd); /* just using mkstemp() to generate/reserve a name */
1.7 christos 1075: bits = 0;
1.15 christos 1076: type_bits_valid(type, NULL, &bits);
1077: if ((r = sshkey_generate(type, bits, &private)) != 0) {
1.27 christos 1078: error("sshkey_generate failed: %s", ssh_err(r));
1079: goto failnext;
1.7 christos 1080: }
1.15 christos 1081: if ((r = sshkey_from_private(private, &public)) != 0)
1082: fatal("sshkey_from_private failed: %s", ssh_err(r));
1.7 christos 1083: snprintf(comment, sizeof comment, "%s@%s", pw->pw_name,
1084: hostname);
1.27 christos 1085: if ((r = sshkey_save_private(private, prv_tmp, "",
1.15 christos 1086: comment, use_new_format, new_format_cipher, rounds)) != 0) {
1.17 christos 1087: error("Saving key \"%s\" failed: %s",
1.27 christos 1088: prv_tmp, ssh_err(r));
1089: goto failnext;
1.7 christos 1090: }
1.27 christos 1091: if ((fd = mkstemp(pub_tmp)) == -1) {
1092: error("Could not save your public key in %s: %s",
1093: pub_tmp, strerror(errno));
1094: goto failnext;
1.7 christos 1095: }
1.27 christos 1096: (void)fchmod(fd, 0644);
1.7 christos 1097: f = fdopen(fd, "w");
1098: if (f == NULL) {
1.27 christos 1099: error("fdopen %s failed: %s", pub_tmp, strerror(errno));
1.15 christos 1100: close(fd);
1.27 christos 1101: goto failnext;
1.7 christos 1102: }
1.15 christos 1103: if ((r = sshkey_write(public, f)) != 0) {
1.17 christos 1104: error("write key failed: %s", ssh_err(r));
1.15 christos 1105: fclose(f);
1.27 christos 1106: goto failnext;
1107: }
1108: fprintf(f, " %s\n", comment);
1109: if (ferror(f) != 0) {
1110: error("write key failed: %s", strerror(errno));
1111: fclose(f);
1112: goto failnext;
1113: }
1114: if (fclose(f) != 0) {
1115: error("key close failed: %s", strerror(errno));
1116: goto failnext;
1117: }
1118:
1119: /* Rename temporary files to their permanent locations. */
1120: if (rename(pub_tmp, pub_file) != 0) {
1121: error("Unable to move %s into position: %s",
1122: pub_file, strerror(errno));
1123: goto failnext;
1124: }
1125: if (rename(prv_tmp, prv_file) != 0) {
1126: error("Unable to move %s into position: %s",
1127: key_types[i].path, strerror(errno));
1128: failnext:
1.7 christos 1129: first = 0;
1.27 christos 1130: goto next;
1.7 christos 1131: }
1.27 christos 1132: next:
1133: sshkey_free(private);
1.15 christos 1134: sshkey_free(public);
1.27 christos 1135: free(prv_tmp);
1136: free(pub_tmp);
1137: free(prv_file);
1138: free(pub_file);
1.7 christos 1139: }
1140: if (first != 0)
1141: printf("\n");
1142: }
1143:
1.15 christos 1144: struct known_hosts_ctx {
1145: const char *host; /* Hostname searched for in find/delete case */
1146: FILE *out; /* Output file, stdout for find_hosts case */
1147: int has_unhashed; /* When hashing, original had unhashed hosts */
1148: int found_key; /* For find/delete, host was found */
1149: int invalid; /* File contained invalid items; don't delete */
1150: };
1151:
1152: static int
1153: known_hosts_hash(struct hostkey_foreach_line *l, void *_ctx)
1154: {
1155: struct known_hosts_ctx *ctx = (struct known_hosts_ctx *)_ctx;
1156: char *hashed, *cp, *hosts, *ohosts;
1157: int has_wild = l->hosts && strcspn(l->hosts, "*?!") != strlen(l->hosts);
1.26 christos 1158: int was_hashed = l->hosts && l->hosts[0] == HASH_DELIM;
1.15 christos 1159:
1160: switch (l->status) {
1161: case HKF_STATUS_OK:
1162: case HKF_STATUS_MATCHED:
1163: /*
1164: * Don't hash hosts already already hashed, with wildcard
1165: * characters or a CA/revocation marker.
1166: */
1.26 christos 1167: if (was_hashed || has_wild || l->marker != MRK_NONE) {
1.15 christos 1168: fprintf(ctx->out, "%s\n", l->line);
1169: if (has_wild && !find_host) {
1.26 christos 1170: logit("%s:%lu: ignoring host name "
1.17 christos 1171: "with wildcard: %.64s", l->path,
1.15 christos 1172: l->linenum, l->hosts);
1173: }
1174: return 0;
1175: }
1176: /*
1177: * Split any comma-separated hostnames from the host list,
1178: * hash and store separately.
1179: */
1180: ohosts = hosts = xstrdup(l->hosts);
1181: while ((cp = strsep(&hosts, ",")) != NULL && *cp != '\0') {
1.26 christos 1182: lowercase(cp);
1.15 christos 1183: if ((hashed = host_hash(cp, NULL, 0)) == NULL)
1184: fatal("hash_host failed");
1185: fprintf(ctx->out, "%s %s\n", hashed, l->rawkey);
1186: ctx->has_unhashed = 1;
1187: }
1188: free(ohosts);
1189: return 0;
1190: case HKF_STATUS_INVALID:
1191: /* Retain invalid lines, but mark file as invalid. */
1192: ctx->invalid = 1;
1.26 christos 1193: logit("%s:%lu: invalid line", l->path, l->linenum);
1.15 christos 1194: /* FALLTHROUGH */
1195: default:
1196: fprintf(ctx->out, "%s\n", l->line);
1197: return 0;
1198: }
1199: /* NOTREACHED */
1200: return -1;
1201: }
1202:
1203: static int
1204: known_hosts_find_delete(struct hostkey_foreach_line *l, void *_ctx)
1.1 christos 1205: {
1.15 christos 1206: struct known_hosts_ctx *ctx = (struct known_hosts_ctx *)_ctx;
1.17 christos 1207: enum sshkey_fp_rep rep;
1208: int fptype;
1209: char *fp;
1210:
1211: fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash;
1212: rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
1.15 christos 1213:
1214: if (l->status == HKF_STATUS_MATCHED) {
1215: if (delete_host) {
1216: if (l->marker != MRK_NONE) {
1217: /* Don't remove CA and revocation lines */
1218: fprintf(ctx->out, "%s\n", l->line);
1219: } else {
1220: /*
1221: * Hostname matches and has no CA/revoke
1222: * marker, delete it by *not* writing the
1223: * line to ctx->out.
1224: */
1225: ctx->found_key = 1;
1226: if (!quiet)
1.26 christos 1227: printf("# Host %s found: line %lu\n",
1.15 christos 1228: ctx->host, l->linenum);
1229: }
1230: return 0;
1231: } else if (find_host) {
1232: ctx->found_key = 1;
1233: if (!quiet) {
1.26 christos 1234: printf("# Host %s found: line %lu %s\n",
1.15 christos 1235: ctx->host,
1236: l->linenum, l->marker == MRK_CA ? "CA" :
1237: (l->marker == MRK_REVOKE ? "REVOKED" : ""));
1238: }
1239: if (hash_hosts)
1240: known_hosts_hash(l, ctx);
1.17 christos 1241: else if (print_fingerprint) {
1242: fp = sshkey_fingerprint(l->key, fptype, rep);
1.26 christos 1243: mprintf("%s %s %s %s\n", ctx->host,
1.17 christos 1244: sshkey_type(l->key), fp, l->comment);
1245: free(fp);
1246: } else
1.15 christos 1247: fprintf(ctx->out, "%s\n", l->line);
1248: return 0;
1249: }
1250: } else if (delete_host) {
1251: /* Retain non-matching hosts when deleting */
1252: if (l->status == HKF_STATUS_INVALID) {
1253: ctx->invalid = 1;
1.26 christos 1254: logit("%s:%lu: invalid line", l->path, l->linenum);
1.15 christos 1255: }
1256: fprintf(ctx->out, "%s\n", l->line);
1.1 christos 1257: }
1.15 christos 1258: return 0;
1.1 christos 1259: }
1260:
1.8 joerg 1261: __dead static void
1.1 christos 1262: do_known_hosts(struct passwd *pw, const char *name)
1263: {
1.15 christos 1264: char *cp, tmp[PATH_MAX], old[PATH_MAX];
1265: int r, fd, oerrno, inplace = 0;
1266: struct known_hosts_ctx ctx;
1.17 christos 1267: u_int foreach_options;
1.1 christos 1268:
1269: if (!have_identity) {
1270: cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid);
1271: if (strlcpy(identity_file, cp, sizeof(identity_file)) >=
1272: sizeof(identity_file))
1273: fatal("Specified known hosts path too long");
1.13 christos 1274: free(cp);
1.1 christos 1275: have_identity = 1;
1276: }
1277:
1.15 christos 1278: memset(&ctx, 0, sizeof(ctx));
1279: ctx.out = stdout;
1280: ctx.host = name;
1281:
1.1 christos 1282: /*
1283: * Find hosts goes to stdout, hash and deletions happen in-place
1284: * A corner case is ssh-keygen -HF foo, which should go to stdout
1285: */
1286: if (!find_host && (hash_hosts || delete_host)) {
1287: if (strlcpy(tmp, identity_file, sizeof(tmp)) >= sizeof(tmp) ||
1288: strlcat(tmp, ".XXXXXXXXXX", sizeof(tmp)) >= sizeof(tmp) ||
1289: strlcpy(old, identity_file, sizeof(old)) >= sizeof(old) ||
1290: strlcat(old, ".old", sizeof(old)) >= sizeof(old))
1291: fatal("known_hosts path too long");
1292: umask(077);
1.15 christos 1293: if ((fd = mkstemp(tmp)) == -1)
1.1 christos 1294: fatal("mkstemp: %s", strerror(errno));
1.15 christos 1295: if ((ctx.out = fdopen(fd, "w")) == NULL) {
1296: oerrno = errno;
1.1 christos 1297: unlink(tmp);
1.15 christos 1298: fatal("fdopen: %s", strerror(oerrno));
1.1 christos 1299: }
1300: inplace = 1;
1301: }
1302:
1.15 christos 1303: /* XXX support identity_file == "-" for stdin */
1.17 christos 1304: foreach_options = find_host ? HKF_WANT_MATCH : 0;
1305: foreach_options |= print_fingerprint ? HKF_WANT_PARSE_KEY : 0;
1.15 christos 1306: if ((r = hostkeys_foreach(identity_file,
1307: hash_hosts ? known_hosts_hash : known_hosts_find_delete, &ctx,
1.20 christos 1308: name, NULL, foreach_options)) != 0) {
1309: if (inplace)
1310: unlink(tmp);
1.15 christos 1311: fatal("%s: hostkeys_foreach failed: %s", __func__, ssh_err(r));
1.20 christos 1312: }
1.1 christos 1313:
1.15 christos 1314: if (inplace)
1315: fclose(ctx.out);
1.4 adam 1316:
1.15 christos 1317: if (ctx.invalid) {
1.17 christos 1318: error("%s is not a valid known_hosts file.", identity_file);
1.1 christos 1319: if (inplace) {
1.17 christos 1320: error("Not replacing existing known_hosts "
1321: "file because of errors");
1.1 christos 1322: unlink(tmp);
1323: }
1324: exit(1);
1.15 christos 1325: } else if (delete_host && !ctx.found_key) {
1.17 christos 1326: logit("Host %s not found in %s", name, identity_file);
1.19 christos 1327: if (inplace)
1328: unlink(tmp);
1.15 christos 1329: } else if (inplace) {
1.1 christos 1330: /* Backup existing file */
1331: if (unlink(old) == -1 && errno != ENOENT)
1332: fatal("unlink %.100s: %s", old, strerror(errno));
1333: if (link(identity_file, old) == -1)
1334: fatal("link %.100s to %.100s: %s", identity_file, old,
1335: strerror(errno));
1336: /* Move new one into place */
1337: if (rename(tmp, identity_file) == -1) {
1338: error("rename\"%s\" to \"%s\": %s", tmp, identity_file,
1339: strerror(errno));
1340: unlink(tmp);
1341: unlink(old);
1342: exit(1);
1343: }
1344:
1.17 christos 1345: printf("%s updated.\n", identity_file);
1346: printf("Original contents retained as %s\n", old);
1.15 christos 1347: if (ctx.has_unhashed) {
1.17 christos 1348: logit("WARNING: %s contains unhashed entries", old);
1349: logit("Delete this file to ensure privacy "
1350: "of hostnames");
1.1 christos 1351: }
1352: }
1353:
1.15 christos 1354: exit (find_host && !ctx.found_key);
1.1 christos 1355: }
1356:
1357: /*
1358: * Perform changing a passphrase. The argument is the passwd structure
1359: * for the current user.
1360: */
1.8 joerg 1361: __dead static void
1.1 christos 1362: do_change_passphrase(struct passwd *pw)
1363: {
1364: char *comment;
1365: char *old_passphrase, *passphrase1, *passphrase2;
1366: struct stat st;
1.15 christos 1367: struct sshkey *private;
1368: int r;
1.1 christos 1369:
1370: if (!have_identity)
1371: ask_filename(pw, "Enter file in which the key is");
1.17 christos 1372: if (stat(identity_file, &st) < 0)
1373: fatal("%s: %s", identity_file, strerror(errno));
1.1 christos 1374: /* Try to load the file with empty passphrase. */
1.15 christos 1375: r = sshkey_load_private(identity_file, "", &private, &comment);
1376: if (r == SSH_ERR_KEY_WRONG_PASSPHRASE) {
1.1 christos 1377: if (identity_passphrase)
1378: old_passphrase = xstrdup(identity_passphrase);
1379: else
1380: old_passphrase =
1381: read_passphrase("Enter old passphrase: ",
1382: RP_ALLOW_STDIN);
1.15 christos 1383: r = sshkey_load_private(identity_file, old_passphrase,
1384: &private, &comment);
1.14 christos 1385: explicit_bzero(old_passphrase, strlen(old_passphrase));
1.13 christos 1386: free(old_passphrase);
1.15 christos 1387: if (r != 0)
1388: goto badkey;
1389: } else if (r != 0) {
1390: badkey:
1.17 christos 1391: fatal("Failed to load key %s: %s", identity_file, ssh_err(r));
1.1 christos 1392: }
1.15 christos 1393: if (comment)
1.26 christos 1394: mprintf("Key has comment '%s'\n", comment);
1.1 christos 1395:
1396: /* Ask the new passphrase (twice). */
1397: if (identity_new_passphrase) {
1398: passphrase1 = xstrdup(identity_new_passphrase);
1399: passphrase2 = NULL;
1400: } else {
1401: passphrase1 =
1402: read_passphrase("Enter new passphrase (empty for no "
1403: "passphrase): ", RP_ALLOW_STDIN);
1404: passphrase2 = read_passphrase("Enter same passphrase again: ",
1405: RP_ALLOW_STDIN);
1406:
1407: /* Verify that they are the same. */
1408: if (strcmp(passphrase1, passphrase2) != 0) {
1.14 christos 1409: explicit_bzero(passphrase1, strlen(passphrase1));
1410: explicit_bzero(passphrase2, strlen(passphrase2));
1.13 christos 1411: free(passphrase1);
1412: free(passphrase2);
1.1 christos 1413: printf("Pass phrases do not match. Try again.\n");
1414: exit(1);
1415: }
1416: /* Destroy the other copy. */
1.14 christos 1417: explicit_bzero(passphrase2, strlen(passphrase2));
1.13 christos 1418: free(passphrase2);
1.1 christos 1419: }
1420:
1421: /* Save the file using the new passphrase. */
1.15 christos 1422: if ((r = sshkey_save_private(private, identity_file, passphrase1,
1423: comment, use_new_format, new_format_cipher, rounds)) != 0) {
1.17 christos 1424: error("Saving key \"%s\" failed: %s.",
1.15 christos 1425: identity_file, ssh_err(r));
1.14 christos 1426: explicit_bzero(passphrase1, strlen(passphrase1));
1.13 christos 1427: free(passphrase1);
1.15 christos 1428: sshkey_free(private);
1.13 christos 1429: free(comment);
1.1 christos 1430: exit(1);
1431: }
1432: /* Destroy the passphrase and the copy of the key in memory. */
1.14 christos 1433: explicit_bzero(passphrase1, strlen(passphrase1));
1.13 christos 1434: free(passphrase1);
1.15 christos 1435: sshkey_free(private); /* Destroys contents */
1.13 christos 1436: free(comment);
1.1 christos 1437:
1438: printf("Your identification has been saved with the new passphrase.\n");
1439: exit(0);
1440: }
1441:
1442: /*
1443: * Print the SSHFP RR.
1444: */
1445: static int
1.6 christos 1446: do_print_resource_record(struct passwd *pw, const char *fname,
1447: const char *hname)
1.1 christos 1448: {
1.15 christos 1449: struct sshkey *public;
1.1 christos 1450: char *comment = NULL;
1451: struct stat st;
1.15 christos 1452: int r;
1.1 christos 1453:
1454: if (fname == NULL)
1.13 christos 1455: fatal("%s: no filename", __func__);
1.1 christos 1456: if (stat(fname, &st) < 0) {
1457: if (errno == ENOENT)
1458: return 0;
1.17 christos 1459: fatal("%s: %s", fname, strerror(errno));
1.1 christos 1460: }
1.17 christos 1461: if ((r = sshkey_load_public(fname, &public, &comment)) != 0)
1462: fatal("Failed to read v2 public key from \"%s\": %s.",
1.15 christos 1463: fname, ssh_err(r));
1464: export_dns_rr(hname, public, stdout, print_generic);
1465: sshkey_free(public);
1466: free(comment);
1467: return 1;
1.1 christos 1468: }
1469:
1470: /*
1471: * Change the comment of a private key file.
1472: */
1.8 joerg 1473: __dead static void
1.1 christos 1474: do_change_comment(struct passwd *pw)
1475: {
1476: char new_comment[1024], *comment, *passphrase;
1.15 christos 1477: struct sshkey *private;
1478: struct sshkey *public;
1.1 christos 1479: struct stat st;
1480: FILE *f;
1.15 christos 1481: int r, fd;
1.1 christos 1482:
1483: if (!have_identity)
1484: ask_filename(pw, "Enter file in which the key is");
1.17 christos 1485: if (stat(identity_file, &st) < 0)
1486: fatal("%s: %s", identity_file, strerror(errno));
1.15 christos 1487: if ((r = sshkey_load_private(identity_file, "",
1488: &private, &comment)) == 0)
1489: passphrase = xstrdup("");
1.17 christos 1490: else if (r != SSH_ERR_KEY_WRONG_PASSPHRASE)
1491: fatal("Cannot load private key \"%s\": %s.",
1.15 christos 1492: identity_file, ssh_err(r));
1.17 christos 1493: else {
1.1 christos 1494: if (identity_passphrase)
1495: passphrase = xstrdup(identity_passphrase);
1496: else if (identity_new_passphrase)
1497: passphrase = xstrdup(identity_new_passphrase);
1498: else
1499: passphrase = read_passphrase("Enter passphrase: ",
1500: RP_ALLOW_STDIN);
1501: /* Try to load using the passphrase. */
1.15 christos 1502: if ((r = sshkey_load_private(identity_file, passphrase,
1503: &private, &comment)) != 0) {
1.14 christos 1504: explicit_bzero(passphrase, strlen(passphrase));
1.13 christos 1505: free(passphrase);
1.17 christos 1506: fatal("Cannot load private key \"%s\": %s.",
1.15 christos 1507: identity_file, ssh_err(r));
1.1 christos 1508: }
1509: }
1.20 christos 1510:
1.30 ! christos 1511: if (private->type != KEY_ED25519 && private->type != KEY_XMSS &&
! 1512: !use_new_format) {
1.27 christos 1513: error("Comments are only supported for keys stored in "
1.20 christos 1514: "the new format (-o).");
1.17 christos 1515: explicit_bzero(passphrase, strlen(passphrase));
1.15 christos 1516: sshkey_free(private);
1.1 christos 1517: exit(1);
1518: }
1.26 christos 1519: if (comment)
1520: printf("Key now has comment '%s'\n", comment);
1521: else
1522: printf("Key now has no comment\n");
1.1 christos 1523:
1524: if (identity_comment) {
1525: strlcpy(new_comment, identity_comment, sizeof(new_comment));
1526: } else {
1527: printf("Enter new comment: ");
1528: fflush(stdout);
1529: if (!fgets(new_comment, sizeof(new_comment), stdin)) {
1.14 christos 1530: explicit_bzero(passphrase, strlen(passphrase));
1.15 christos 1531: sshkey_free(private);
1.1 christos 1532: exit(1);
1533: }
1534: new_comment[strcspn(new_comment, "\n")] = '\0';
1535: }
1536:
1537: /* Save the file using the new passphrase. */
1.15 christos 1538: if ((r = sshkey_save_private(private, identity_file, passphrase,
1539: new_comment, use_new_format, new_format_cipher, rounds)) != 0) {
1.17 christos 1540: error("Saving key \"%s\" failed: %s",
1.15 christos 1541: identity_file, ssh_err(r));
1.14 christos 1542: explicit_bzero(passphrase, strlen(passphrase));
1.13 christos 1543: free(passphrase);
1.15 christos 1544: sshkey_free(private);
1.13 christos 1545: free(comment);
1.1 christos 1546: exit(1);
1547: }
1.14 christos 1548: explicit_bzero(passphrase, strlen(passphrase));
1.13 christos 1549: free(passphrase);
1.15 christos 1550: if ((r = sshkey_from_private(private, &public)) != 0)
1.27 christos 1551: fatal("sshkey_from_private failed: %s", ssh_err(r));
1.15 christos 1552: sshkey_free(private);
1.1 christos 1553:
1554: strlcat(identity_file, ".pub", sizeof(identity_file));
1555: fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
1.17 christos 1556: if (fd == -1)
1557: fatal("Could not save your public key in %s", identity_file);
1.1 christos 1558: f = fdopen(fd, "w");
1.17 christos 1559: if (f == NULL)
1560: fatal("fdopen %s failed: %s", identity_file, strerror(errno));
1.15 christos 1561: if ((r = sshkey_write(public, f)) != 0)
1.17 christos 1562: fatal("write key failed: %s", ssh_err(r));
1.15 christos 1563: sshkey_free(public);
1.1 christos 1564: fprintf(f, " %s\n", new_comment);
1565: fclose(f);
1566:
1.13 christos 1567: free(comment);
1.1 christos 1568:
1569: printf("The comment in your key file has been changed.\n");
1570: exit(0);
1571: }
1572:
1.4 adam 1573: static void
1.15 christos 1574: add_flag_option(struct sshbuf *c, const char *name)
1.4 adam 1575: {
1.15 christos 1576: int r;
1577:
1.4 adam 1578: debug3("%s: %s", __func__, name);
1.15 christos 1579: if ((r = sshbuf_put_cstring(c, name)) != 0 ||
1580: (r = sshbuf_put_string(c, NULL, 0)) != 0)
1581: fatal("%s: buffer error: %s", __func__, ssh_err(r));
1.4 adam 1582: }
1583:
1584: static void
1.15 christos 1585: add_string_option(struct sshbuf *c, const char *name, const char *value)
1.4 adam 1586: {
1.15 christos 1587: struct sshbuf *b;
1588: int r;
1.4 adam 1589:
1590: debug3("%s: %s=%s", __func__, name, value);
1.15 christos 1591: if ((b = sshbuf_new()) == NULL)
1592: fatal("%s: sshbuf_new failed", __func__);
1593: if ((r = sshbuf_put_cstring(b, value)) != 0 ||
1594: (r = sshbuf_put_cstring(c, name)) != 0 ||
1595: (r = sshbuf_put_stringb(c, b)) != 0)
1596: fatal("%s: buffer error: %s", __func__, ssh_err(r));
1.4 adam 1597:
1.15 christos 1598: sshbuf_free(b);
1.4 adam 1599: }
1600:
1601: #define OPTIONS_CRITICAL 1
1602: #define OPTIONS_EXTENSIONS 2
1603: static void
1.15 christos 1604: prepare_options_buf(struct sshbuf *c, int which)
1.4 adam 1605: {
1.27 christos 1606: size_t i;
1607:
1.15 christos 1608: sshbuf_reset(c);
1.4 adam 1609: if ((which & OPTIONS_CRITICAL) != 0 &&
1610: certflags_command != NULL)
1611: add_string_option(c, "force-command", certflags_command);
1612: if ((which & OPTIONS_EXTENSIONS) != 0 &&
1.7 christos 1613: (certflags_flags & CERTOPT_X_FWD) != 0)
1614: add_flag_option(c, "permit-X11-forwarding");
1615: if ((which & OPTIONS_EXTENSIONS) != 0 &&
1.4 adam 1616: (certflags_flags & CERTOPT_AGENT_FWD) != 0)
1617: add_flag_option(c, "permit-agent-forwarding");
1618: if ((which & OPTIONS_EXTENSIONS) != 0 &&
1619: (certflags_flags & CERTOPT_PORT_FWD) != 0)
1620: add_flag_option(c, "permit-port-forwarding");
1621: if ((which & OPTIONS_EXTENSIONS) != 0 &&
1622: (certflags_flags & CERTOPT_PTY) != 0)
1623: add_flag_option(c, "permit-pty");
1624: if ((which & OPTIONS_EXTENSIONS) != 0 &&
1625: (certflags_flags & CERTOPT_USER_RC) != 0)
1626: add_flag_option(c, "permit-user-rc");
1627: if ((which & OPTIONS_CRITICAL) != 0 &&
1628: certflags_src_addr != NULL)
1629: add_string_option(c, "source-address", certflags_src_addr);
1.27 christos 1630: for (i = 0; i < ncert_userext; i++) {
1631: if ((cert_userext[i].crit && (which & OPTIONS_EXTENSIONS)) ||
1632: (!cert_userext[i].crit && (which & OPTIONS_CRITICAL)))
1633: continue;
1634: if (cert_userext[i].val == NULL)
1635: add_flag_option(c, cert_userext[i].key);
1636: else {
1637: add_string_option(c, cert_userext[i].key,
1638: cert_userext[i].val);
1639: }
1640: }
1.4 adam 1641: }
1642:
1.15 christos 1643: static struct sshkey *
1.4 adam 1644: load_pkcs11_key(char *path)
1645: {
1646: #ifdef ENABLE_PKCS11
1.15 christos 1647: struct sshkey **keys = NULL, *public, *private = NULL;
1648: int r, i, nkeys;
1.4 adam 1649:
1.15 christos 1650: if ((r = sshkey_load_public(path, &public, NULL)) != 0)
1651: fatal("Couldn't load CA public key \"%s\": %s",
1652: path, ssh_err(r));
1.4 adam 1653:
1654: nkeys = pkcs11_add_provider(pkcs11provider, identity_passphrase, &keys);
1655: debug3("%s: %d keys", __func__, nkeys);
1656: if (nkeys <= 0)
1657: fatal("cannot read public key from pkcs11");
1658: for (i = 0; i < nkeys; i++) {
1.15 christos 1659: if (sshkey_equal_public(public, keys[i])) {
1.4 adam 1660: private = keys[i];
1661: continue;
1662: }
1.15 christos 1663: sshkey_free(keys[i]);
1.4 adam 1664: }
1.13 christos 1665: free(keys);
1.15 christos 1666: sshkey_free(public);
1.4 adam 1667: return private;
1668: #else
1669: fatal("no pkcs11 support");
1670: #endif /* ENABLE_PKCS11 */
1671: }
1672:
1.27 christos 1673: /* Signer for sshkey_certify_custom that uses the agent */
1674: static int
1675: agent_signer(const struct sshkey *key, u_char **sigp, size_t *lenp,
1676: const u_char *data, size_t datalen,
1677: const char *alg, u_int compat, void *ctx)
1678: {
1679: int *agent_fdp = (int *)ctx;
1680:
1681: return ssh_agent_sign(*agent_fdp, key, sigp, lenp,
1682: data, datalen, alg, compat);
1683: }
1684:
1.28 joerg 1685: __dead static void
1.4 adam 1686: do_ca_sign(struct passwd *pw, int argc, char **argv)
1687: {
1.27 christos 1688: int r, i, fd, found, agent_fd = -1;
1.4 adam 1689: u_int n;
1.15 christos 1690: struct sshkey *ca, *public;
1.20 christos 1691: char valid[64], *otmp, *tmp, *cp, *out, *comment, **plist = NULL;
1.4 adam 1692: FILE *f;
1.27 christos 1693: struct ssh_identitylist *agent_ids;
1694: size_t j;
1.4 adam 1695:
1.14 christos 1696: #ifdef ENABLE_PKCS11
1.4 adam 1697: pkcs11_init(1);
1.14 christos 1698: #endif
1.4 adam 1699: tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
1700: if (pkcs11provider != NULL) {
1.27 christos 1701: /* If a PKCS#11 token was specified then try to use it */
1.4 adam 1702: if ((ca = load_pkcs11_key(tmp)) == NULL)
1703: fatal("No PKCS#11 key matching %s found", ca_key_path);
1.27 christos 1704: } else if (prefer_agent) {
1705: /*
1706: * Agent signature requested. Try to use agent after making
1707: * sure the public key specified is actually present in the
1708: * agent.
1709: */
1710: if ((r = sshkey_load_public(tmp, &ca, NULL)) != 0)
1711: fatal("Cannot load CA public key %s: %s",
1712: tmp, ssh_err(r));
1713: if ((r = ssh_get_authentication_socket(&agent_fd)) != 0)
1714: fatal("Cannot use public key for CA signature: %s",
1715: ssh_err(r));
1716: if ((r = ssh_fetch_identitylist(agent_fd, &agent_ids)) != 0)
1717: fatal("Retrieve agent key list: %s", ssh_err(r));
1718: found = 0;
1719: for (j = 0; j < agent_ids->nkeys; j++) {
1720: if (sshkey_equal(ca, agent_ids->keys[j])) {
1721: found = 1;
1722: break;
1723: }
1724: }
1725: if (!found)
1726: fatal("CA key %s not found in agent", tmp);
1727: ssh_free_identitylist(agent_ids);
1728: ca->flags |= SSHKEY_FLAG_EXT;
1729: } else {
1730: /* CA key is assumed to be a private key on the filesystem */
1.15 christos 1731: ca = load_identity(tmp);
1.27 christos 1732: }
1.13 christos 1733: free(tmp);
1.4 adam 1734:
1.24 christos 1735: if (key_type_name != NULL &&
1736: sshkey_type_from_name(key_type_name) != ca->type) {
1737: fatal("CA key type %s doesn't match specified %s",
1738: sshkey_ssh_name(ca), key_type_name);
1739: }
1740:
1.4 adam 1741: for (i = 0; i < argc; i++) {
1742: /* Split list of principals */
1743: n = 0;
1744: if (cert_principals != NULL) {
1745: otmp = tmp = xstrdup(cert_principals);
1746: plist = NULL;
1747: for (; (cp = strsep(&tmp, ",")) != NULL; n++) {
1.17 christos 1748: plist = xreallocarray(plist, n + 1, sizeof(*plist));
1.4 adam 1749: if (*(plist[n] = xstrdup(cp)) == '\0')
1750: fatal("Empty principal name");
1751: }
1.13 christos 1752: free(otmp);
1.4 adam 1753: }
1.30 ! christos 1754: if (n > SSHKEY_CERT_MAX_PRINCIPALS)
! 1755: fatal("Too many certificate principals specified");
1.4 adam 1756:
1757: tmp = tilde_expand_filename(argv[i], pw->pw_uid);
1.15 christos 1758: if ((r = sshkey_load_public(tmp, &public, &comment)) != 0)
1759: fatal("%s: unable to open \"%s\": %s",
1760: __func__, tmp, ssh_err(r));
1.6 christos 1761: if (public->type != KEY_RSA && public->type != KEY_DSA &&
1.30 ! christos 1762: public->type != KEY_ECDSA && public->type != KEY_ED25519 &&
! 1763: public->type != KEY_XMSS)
1.4 adam 1764: fatal("%s: key \"%s\" type %s cannot be certified",
1.15 christos 1765: __func__, tmp, sshkey_type(public));
1.4 adam 1766:
1767: /* Prepare certificate to sign */
1.18 christos 1768: if ((r = sshkey_to_certified(public)) != 0)
1.15 christos 1769: fatal("Could not upgrade key %s to certificate: %s",
1770: tmp, ssh_err(r));
1.4 adam 1771: public->cert->type = cert_key_type;
1772: public->cert->serial = (u_int64_t)cert_serial;
1773: public->cert->key_id = xstrdup(cert_key_id);
1774: public->cert->nprincipals = n;
1775: public->cert->principals = plist;
1776: public->cert->valid_after = cert_valid_from;
1777: public->cert->valid_before = cert_valid_to;
1.18 christos 1778: prepare_options_buf(public->cert->critical, OPTIONS_CRITICAL);
1779: prepare_options_buf(public->cert->extensions,
1780: OPTIONS_EXTENSIONS);
1.15 christos 1781: if ((r = sshkey_from_private(ca,
1782: &public->cert->signature_key)) != 0)
1.27 christos 1783: fatal("sshkey_from_private (ca key): %s", ssh_err(r));
1.4 adam 1784:
1.27 christos 1785: if (agent_fd != -1 && (ca->flags & SSHKEY_FLAG_EXT) != 0) {
1786: if ((r = sshkey_certify_custom(public, ca,
1787: key_type_name, agent_signer, &agent_fd)) != 0)
1788: fatal("Couldn't certify key %s via agent: %s",
1789: tmp, ssh_err(r));
1790: } else {
1791: if ((sshkey_certify(public, ca, key_type_name)) != 0)
1792: fatal("Couldn't certify key %s: %s",
1793: tmp, ssh_err(r));
1794: }
1.4 adam 1795:
1796: if ((cp = strrchr(tmp, '.')) != NULL && strcmp(cp, ".pub") == 0)
1797: *cp = '\0';
1798: xasprintf(&out, "%s-cert.pub", tmp);
1.13 christos 1799: free(tmp);
1.4 adam 1800:
1801: if ((fd = open(out, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
1802: fatal("Could not open \"%s\" for writing: %s", out,
1803: strerror(errno));
1804: if ((f = fdopen(fd, "w")) == NULL)
1805: fatal("%s: fdopen: %s", __func__, strerror(errno));
1.15 christos 1806: if ((r = sshkey_write(public, f)) != 0)
1807: fatal("Could not write certified key to %s: %s",
1808: out, ssh_err(r));
1.4 adam 1809: fprintf(f, " %s\n", comment);
1810: fclose(f);
1811:
1812: if (!quiet) {
1.20 christos 1813: sshkey_format_cert_validity(public->cert,
1814: valid, sizeof(valid));
1.4 adam 1815: logit("Signed %s key %s: id \"%s\" serial %llu%s%s "
1.20 christos 1816: "valid %s", sshkey_cert_type(public),
1.6 christos 1817: out, public->cert->key_id,
1818: (unsigned long long)public->cert->serial,
1.4 adam 1819: cert_principals != NULL ? " for " : "",
1820: cert_principals != NULL ? cert_principals : "",
1.20 christos 1821: valid);
1.4 adam 1822: }
1823:
1.15 christos 1824: sshkey_free(public);
1.13 christos 1825: free(out);
1.4 adam 1826: }
1.14 christos 1827: #ifdef ENABLE_PKCS11
1.4 adam 1828: pkcs11_terminate();
1.14 christos 1829: #endif
1.4 adam 1830: exit(0);
1831: }
1832:
1833: static u_int64_t
1834: parse_relative_time(const char *s, time_t now)
1835: {
1836: int64_t mul, secs;
1837:
1838: mul = *s == '-' ? -1 : 1;
1839:
1840: if ((secs = convtime(s + 1)) == -1)
1841: fatal("Invalid relative certificate time %s", s);
1842: if (mul == -1 && secs > now)
1843: fatal("Certificate time %s cannot be represented", s);
1844: return now + (u_int64_t)(secs * mul);
1845: }
1846:
1847: static void
1848: parse_cert_times(char *timespec)
1849: {
1850: char *from, *to;
1851: time_t now = time(NULL);
1852: int64_t secs;
1853:
1854: /* +timespec relative to now */
1855: if (*timespec == '+' && strchr(timespec, ':') == NULL) {
1856: if ((secs = convtime(timespec + 1)) == -1)
1857: fatal("Invalid relative certificate life %s", timespec);
1858: cert_valid_to = now + secs;
1859: /*
1860: * Backdate certificate one minute to avoid problems on hosts
1861: * with poorly-synchronised clocks.
1862: */
1863: cert_valid_from = ((now - 59)/ 60) * 60;
1864: return;
1865: }
1866:
1867: /*
1868: * from:to, where
1.30 ! christos 1869: * from := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | "always"
! 1870: * to := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | "forever"
1.4 adam 1871: */
1872: from = xstrdup(timespec);
1873: to = strchr(from, ':');
1874: if (to == NULL || from == to || *(to + 1) == '\0')
1875: fatal("Invalid certificate life specification %s", timespec);
1876: *to++ = '\0';
1877:
1878: if (*from == '-' || *from == '+')
1879: cert_valid_from = parse_relative_time(from, now);
1.30 ! christos 1880: else if (strcmp(from, "always") == 0)
! 1881: cert_valid_from = 0;
! 1882: else if (parse_absolute_time(from, &cert_valid_from) != 0)
! 1883: fatal("Invalid from time \"%s\"", from);
1.4 adam 1884:
1885: if (*to == '-' || *to == '+')
1.14 christos 1886: cert_valid_to = parse_relative_time(to, now);
1.30 ! christos 1887: else if (strcmp(to, "forever") == 0)
! 1888: cert_valid_to = ~(u_int64_t)0;
! 1889: else if (parse_absolute_time(to, &cert_valid_to) != 0)
! 1890: fatal("Invalid to time \"%s\"", to);
1.4 adam 1891:
1892: if (cert_valid_to <= cert_valid_from)
1893: fatal("Empty certificate validity interval");
1.13 christos 1894: free(from);
1.4 adam 1895: }
1896:
1897: static void
1898: add_cert_option(char *opt)
1899: {
1.27 christos 1900: char *val, *cp;
1901: int iscrit = 0;
1.4 adam 1902:
1.7 christos 1903: if (strcasecmp(opt, "clear") == 0)
1.4 adam 1904: certflags_flags = 0;
1905: else if (strcasecmp(opt, "no-x11-forwarding") == 0)
1906: certflags_flags &= ~CERTOPT_X_FWD;
1907: else if (strcasecmp(opt, "permit-x11-forwarding") == 0)
1908: certflags_flags |= CERTOPT_X_FWD;
1909: else if (strcasecmp(opt, "no-agent-forwarding") == 0)
1910: certflags_flags &= ~CERTOPT_AGENT_FWD;
1911: else if (strcasecmp(opt, "permit-agent-forwarding") == 0)
1912: certflags_flags |= CERTOPT_AGENT_FWD;
1913: else if (strcasecmp(opt, "no-port-forwarding") == 0)
1914: certflags_flags &= ~CERTOPT_PORT_FWD;
1915: else if (strcasecmp(opt, "permit-port-forwarding") == 0)
1916: certflags_flags |= CERTOPT_PORT_FWD;
1917: else if (strcasecmp(opt, "no-pty") == 0)
1918: certflags_flags &= ~CERTOPT_PTY;
1919: else if (strcasecmp(opt, "permit-pty") == 0)
1920: certflags_flags |= CERTOPT_PTY;
1921: else if (strcasecmp(opt, "no-user-rc") == 0)
1922: certflags_flags &= ~CERTOPT_USER_RC;
1923: else if (strcasecmp(opt, "permit-user-rc") == 0)
1924: certflags_flags |= CERTOPT_USER_RC;
1925: else if (strncasecmp(opt, "force-command=", 14) == 0) {
1926: val = opt + 14;
1927: if (*val == '\0')
1928: fatal("Empty force-command option");
1929: if (certflags_command != NULL)
1930: fatal("force-command already specified");
1931: certflags_command = xstrdup(val);
1932: } else if (strncasecmp(opt, "source-address=", 15) == 0) {
1933: val = opt + 15;
1934: if (*val == '\0')
1935: fatal("Empty source-address option");
1936: if (certflags_src_addr != NULL)
1937: fatal("source-address already specified");
1938: if (addr_match_cidr_list(NULL, val) != 0)
1939: fatal("Invalid source-address list");
1940: certflags_src_addr = xstrdup(val);
1.27 christos 1941: } else if (strncasecmp(opt, "extension:", 10) == 0 ||
1942: (iscrit = (strncasecmp(opt, "critical:", 9) == 0))) {
1943: val = xstrdup(strchr(opt, ':') + 1);
1944: if ((cp = strchr(val, '=')) != NULL)
1945: *cp++ = '\0';
1946: cert_userext = xreallocarray(cert_userext, ncert_userext + 1,
1947: sizeof(*cert_userext));
1948: cert_userext[ncert_userext].key = val;
1949: cert_userext[ncert_userext].val = cp == NULL ?
1950: NULL : xstrdup(cp);
1951: cert_userext[ncert_userext].crit = iscrit;
1952: ncert_userext++;
1.4 adam 1953: } else
1954: fatal("Unsupported certificate option \"%s\"", opt);
1955: }
1956:
1957: static void
1.18 christos 1958: show_options(struct sshbuf *optbuf, int in_critical)
1.4 adam 1959: {
1.14 christos 1960: char *name, *arg;
1.15 christos 1961: struct sshbuf *options, *option = NULL;
1962: int r;
1963:
1964: if ((options = sshbuf_fromb(optbuf)) == NULL)
1965: fatal("%s: sshbuf_fromb failed", __func__);
1966: while (sshbuf_len(options) != 0) {
1967: sshbuf_free(option);
1968: option = NULL;
1969: if ((r = sshbuf_get_cstring(options, &name, NULL)) != 0 ||
1970: (r = sshbuf_froms(options, &option)) != 0)
1971: fatal("%s: buffer error: %s", __func__, ssh_err(r));
1.4 adam 1972: printf(" %s", name);
1.18 christos 1973: if (!in_critical &&
1.4 adam 1974: (strcmp(name, "permit-X11-forwarding") == 0 ||
1975: strcmp(name, "permit-agent-forwarding") == 0 ||
1976: strcmp(name, "permit-port-forwarding") == 0 ||
1977: strcmp(name, "permit-pty") == 0 ||
1978: strcmp(name, "permit-user-rc") == 0))
1979: printf("\n");
1.18 christos 1980: else if (in_critical &&
1.4 adam 1981: (strcmp(name, "force-command") == 0 ||
1982: strcmp(name, "source-address") == 0)) {
1.15 christos 1983: if ((r = sshbuf_get_cstring(option, &arg, NULL)) != 0)
1984: fatal("%s: buffer error: %s",
1985: __func__, ssh_err(r));
1.14 christos 1986: printf(" %s\n", arg);
1987: free(arg);
1.4 adam 1988: } else {
1.15 christos 1989: printf(" UNKNOWN OPTION (len %zu)\n",
1990: sshbuf_len(option));
1991: sshbuf_reset(option);
1.4 adam 1992: }
1.13 christos 1993: free(name);
1.15 christos 1994: if (sshbuf_len(option) != 0)
1.4 adam 1995: fatal("Option corrupt: extra data at end");
1996: }
1.15 christos 1997: sshbuf_free(option);
1998: sshbuf_free(options);
1.4 adam 1999: }
2000:
1.20 christos 2001: static void
2002: print_cert(struct sshkey *key)
1.4 adam 2003: {
1.20 christos 2004: char valid[64], *key_fp, *ca_fp;
1.18 christos 2005: u_int i;
1.4 adam 2006:
1.15 christos 2007: key_fp = sshkey_fingerprint(key, fingerprint_hash, SSH_FP_DEFAULT);
2008: ca_fp = sshkey_fingerprint(key->cert->signature_key,
2009: fingerprint_hash, SSH_FP_DEFAULT);
2010: if (key_fp == NULL || ca_fp == NULL)
2011: fatal("%s: sshkey_fingerprint fail", __func__);
1.20 christos 2012: sshkey_format_cert_validity(key->cert, valid, sizeof(valid));
1.4 adam 2013:
1.15 christos 2014: printf(" Type: %s %s certificate\n", sshkey_ssh_name(key),
2015: sshkey_cert_type(key));
2016: printf(" Public key: %s %s\n", sshkey_type(key), key_fp);
1.4 adam 2017: printf(" Signing CA: %s %s\n",
1.15 christos 2018: sshkey_type(key->cert->signature_key), ca_fp);
1.4 adam 2019: printf(" Key ID: \"%s\"\n", key->cert->key_id);
1.18 christos 2020: printf(" Serial: %llu\n", (unsigned long long)key->cert->serial);
1.20 christos 2021: printf(" Valid: %s\n", valid);
1.4 adam 2022: printf(" Principals: ");
2023: if (key->cert->nprincipals == 0)
2024: printf("(none)\n");
2025: else {
2026: for (i = 0; i < key->cert->nprincipals; i++)
2027: printf("\n %s",
2028: key->cert->principals[i]);
2029: printf("\n");
2030: }
2031: printf(" Critical Options: ");
1.15 christos 2032: if (sshbuf_len(key->cert->critical) == 0)
1.4 adam 2033: printf("(none)\n");
2034: else {
2035: printf("\n");
1.18 christos 2036: show_options(key->cert->critical, 1);
1.4 adam 2037: }
1.18 christos 2038: printf(" Extensions: ");
2039: if (sshbuf_len(key->cert->extensions) == 0)
2040: printf("(none)\n");
2041: else {
2042: printf("\n");
2043: show_options(key->cert->extensions, 0);
1.4 adam 2044: }
1.20 christos 2045: }
2046:
1.21 christos 2047: __dead static void
1.20 christos 2048: do_show_cert(struct passwd *pw)
2049: {
2050: struct sshkey *key = NULL;
2051: int r, is_stdin = 0, ok = 0;
2052: FILE *f;
2053: char *cp, line[SSH_MAX_PUBKEY_BYTES];
2054: const char *path;
1.24 christos 2055: u_long lnum = 0;
1.20 christos 2056:
2057: if (!have_identity)
2058: ask_filename(pw, "Enter file in which the key is");
2059:
2060: path = identity_file;
2061: if (strcmp(path, "-") == 0) {
2062: f = stdin;
2063: path = "(stdin)";
2064: is_stdin = 1;
2065: } else if ((f = fopen(identity_file, "r")) == NULL)
2066: fatal("fopen %s: %s", identity_file, strerror(errno));
2067:
2068: while (read_keyfile_line(f, path, line, sizeof(line), &lnum) == 0) {
2069: sshkey_free(key);
2070: key = NULL;
2071: /* Trim leading space and comments */
2072: cp = line + strspn(line, " \t");
2073: if (*cp == '#' || *cp == '\0')
2074: continue;
2075: if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
1.27 christos 2076: fatal("sshkey_new");
1.20 christos 2077: if ((r = sshkey_read(key, &cp)) != 0) {
2078: error("%s:%lu: invalid key: %s", path,
2079: lnum, ssh_err(r));
2080: continue;
2081: }
2082: if (!sshkey_is_cert(key)) {
2083: error("%s:%lu is not a certificate", path, lnum);
2084: continue;
2085: }
2086: ok = 1;
2087: if (!is_stdin && lnum == 1)
2088: printf("%s:\n", path);
2089: else
2090: printf("%s:%lu:\n", path, lnum);
2091: print_cert(key);
2092: }
2093: sshkey_free(key);
2094: fclose(f);
2095: exit(ok ? 0 : 1);
1.4 adam 2096: }
2097:
1.14 christos 2098: #ifdef WITH_OPENSSL
1.11 christos 2099: static void
2100: load_krl(const char *path, struct ssh_krl **krlp)
2101: {
1.15 christos 2102: struct sshbuf *krlbuf;
2103: int r, fd;
1.11 christos 2104:
1.15 christos 2105: if ((krlbuf = sshbuf_new()) == NULL)
2106: fatal("sshbuf_new failed");
1.11 christos 2107: if ((fd = open(path, O_RDONLY)) == -1)
2108: fatal("open %s: %s", path, strerror(errno));
1.15 christos 2109: if ((r = sshkey_load_file(fd, krlbuf)) != 0)
2110: fatal("Unable to load KRL: %s", ssh_err(r));
1.11 christos 2111: close(fd);
2112: /* XXX check sigs */
1.15 christos 2113: if ((r = ssh_krl_from_blob(krlbuf, krlp, NULL, 0)) != 0 ||
1.11 christos 2114: *krlp == NULL)
1.15 christos 2115: fatal("Invalid KRL file: %s", ssh_err(r));
2116: sshbuf_free(krlbuf);
1.11 christos 2117: }
2118:
2119: static void
1.15 christos 2120: update_krl_from_file(struct passwd *pw, const char *file, int wild_ca,
2121: const struct sshkey *ca, struct ssh_krl *krl)
1.11 christos 2122: {
1.15 christos 2123: struct sshkey *key = NULL;
1.11 christos 2124: u_long lnum = 0;
2125: char *path, *cp, *ep, line[SSH_MAX_PUBKEY_BYTES];
2126: unsigned long long serial, serial2;
2127: int i, was_explicit_key, was_sha1, r;
2128: FILE *krl_spec;
2129:
2130: path = tilde_expand_filename(file, pw->pw_uid);
2131: if (strcmp(path, "-") == 0) {
2132: krl_spec = stdin;
2133: free(path);
2134: path = xstrdup("(standard input)");
2135: } else if ((krl_spec = fopen(path, "r")) == NULL)
2136: fatal("fopen %s: %s", path, strerror(errno));
2137:
2138: if (!quiet)
2139: printf("Revoking from %s\n", path);
2140: while (read_keyfile_line(krl_spec, path, line, sizeof(line),
2141: &lnum) == 0) {
2142: was_explicit_key = was_sha1 = 0;
2143: cp = line + strspn(line, " \t");
2144: /* Trim trailing space, comments and strip \n */
2145: for (i = 0, r = -1; cp[i] != '\0'; i++) {
2146: if (cp[i] == '#' || cp[i] == '\n') {
2147: cp[i] = '\0';
2148: break;
2149: }
2150: if (cp[i] == ' ' || cp[i] == '\t') {
2151: /* Remember the start of a span of whitespace */
2152: if (r == -1)
2153: r = i;
2154: } else
2155: r = -1;
2156: }
2157: if (r != -1)
2158: cp[r] = '\0';
2159: if (*cp == '\0')
2160: continue;
2161: if (strncasecmp(cp, "serial:", 7) == 0) {
1.15 christos 2162: if (ca == NULL && !wild_ca) {
1.14 christos 2163: fatal("revoking certificates by serial number "
1.11 christos 2164: "requires specification of a CA key");
2165: }
2166: cp += 7;
2167: cp = cp + strspn(cp, " \t");
2168: errno = 0;
2169: serial = strtoull(cp, &ep, 0);
2170: if (*cp == '\0' || (*ep != '\0' && *ep != '-'))
2171: fatal("%s:%lu: invalid serial \"%s\"",
2172: path, lnum, cp);
2173: if (errno == ERANGE && serial == ULLONG_MAX)
2174: fatal("%s:%lu: serial out of range",
2175: path, lnum);
2176: serial2 = serial;
2177: if (*ep == '-') {
2178: cp = ep + 1;
2179: errno = 0;
2180: serial2 = strtoull(cp, &ep, 0);
2181: if (*cp == '\0' || *ep != '\0')
2182: fatal("%s:%lu: invalid serial \"%s\"",
2183: path, lnum, cp);
2184: if (errno == ERANGE && serial2 == ULLONG_MAX)
2185: fatal("%s:%lu: serial out of range",
2186: path, lnum);
2187: if (serial2 <= serial)
2188: fatal("%s:%lu: invalid serial range "
2189: "%llu:%llu", path, lnum,
2190: (unsigned long long)serial,
2191: (unsigned long long)serial2);
2192: }
2193: if (ssh_krl_revoke_cert_by_serial_range(krl,
2194: ca, serial, serial2) != 0) {
2195: fatal("%s: revoke serial failed",
2196: __func__);
2197: }
2198: } else if (strncasecmp(cp, "id:", 3) == 0) {
1.15 christos 2199: if (ca == NULL && !wild_ca) {
1.14 christos 2200: fatal("revoking certificates by key ID "
1.11 christos 2201: "requires specification of a CA key");
2202: }
2203: cp += 3;
2204: cp = cp + strspn(cp, " \t");
2205: if (ssh_krl_revoke_cert_by_key_id(krl, ca, cp) != 0)
2206: fatal("%s: revoke key ID failed", __func__);
2207: } else {
2208: if (strncasecmp(cp, "key:", 4) == 0) {
2209: cp += 4;
2210: cp = cp + strspn(cp, " \t");
2211: was_explicit_key = 1;
2212: } else if (strncasecmp(cp, "sha1:", 5) == 0) {
2213: cp += 5;
2214: cp = cp + strspn(cp, " \t");
2215: was_sha1 = 1;
2216: } else {
2217: /*
2218: * Just try to process the line as a key.
2219: * Parsing will fail if it isn't.
2220: */
2221: }
1.15 christos 2222: if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
1.27 christos 2223: fatal("sshkey_new");
1.15 christos 2224: if ((r = sshkey_read(key, &cp)) != 0)
2225: fatal("%s:%lu: invalid key: %s",
2226: path, lnum, ssh_err(r));
1.11 christos 2227: if (was_explicit_key)
2228: r = ssh_krl_revoke_key_explicit(krl, key);
2229: else if (was_sha1)
2230: r = ssh_krl_revoke_key_sha1(krl, key);
2231: else
2232: r = ssh_krl_revoke_key(krl, key);
2233: if (r != 0)
1.15 christos 2234: fatal("%s: revoke key failed: %s",
2235: __func__, ssh_err(r));
2236: sshkey_free(key);
1.11 christos 2237: }
2238: }
2239: if (strcmp(path, "-") != 0)
2240: fclose(krl_spec);
1.13 christos 2241: free(path);
1.11 christos 2242: }
2243:
2244: static void
2245: do_gen_krl(struct passwd *pw, int updating, int argc, char **argv)
2246: {
2247: struct ssh_krl *krl;
2248: struct stat sb;
1.15 christos 2249: struct sshkey *ca = NULL;
2250: int fd, i, r, wild_ca = 0;
1.11 christos 2251: char *tmp;
1.15 christos 2252: struct sshbuf *kbuf;
1.11 christos 2253:
2254: if (*identity_file == '\0')
2255: fatal("KRL generation requires an output file");
2256: if (stat(identity_file, &sb) == -1) {
2257: if (errno != ENOENT)
2258: fatal("Cannot access KRL \"%s\": %s",
2259: identity_file, strerror(errno));
2260: if (updating)
2261: fatal("KRL \"%s\" does not exist", identity_file);
2262: }
2263: if (ca_key_path != NULL) {
1.15 christos 2264: if (strcasecmp(ca_key_path, "none") == 0)
2265: wild_ca = 1;
2266: else {
2267: tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
2268: if ((r = sshkey_load_public(tmp, &ca, NULL)) != 0)
2269: fatal("Cannot load CA public key %s: %s",
2270: tmp, ssh_err(r));
2271: free(tmp);
2272: }
1.11 christos 2273: }
2274:
2275: if (updating)
2276: load_krl(identity_file, &krl);
2277: else if ((krl = ssh_krl_init()) == NULL)
2278: fatal("couldn't create KRL");
2279:
2280: if (cert_serial != 0)
2281: ssh_krl_set_version(krl, cert_serial);
2282: if (identity_comment != NULL)
2283: ssh_krl_set_comment(krl, identity_comment);
2284:
2285: for (i = 0; i < argc; i++)
1.15 christos 2286: update_krl_from_file(pw, argv[i], wild_ca, ca, krl);
1.11 christos 2287:
1.15 christos 2288: if ((kbuf = sshbuf_new()) == NULL)
2289: fatal("sshbuf_new failed");
2290: if (ssh_krl_to_blob(krl, kbuf, NULL, 0) != 0)
1.11 christos 2291: fatal("Couldn't generate KRL");
2292: if ((fd = open(identity_file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
2293: fatal("open %s: %s", identity_file, strerror(errno));
1.15 christos 2294: if (atomicio(vwrite, fd, __UNCONST(sshbuf_ptr(kbuf)), sshbuf_len(kbuf)) !=
2295: sshbuf_len(kbuf))
1.11 christos 2296: fatal("write %s: %s", identity_file, strerror(errno));
2297: close(fd);
1.15 christos 2298: sshbuf_free(kbuf);
1.11 christos 2299: ssh_krl_free(krl);
1.20 christos 2300: sshkey_free(ca);
1.11 christos 2301: }
2302:
1.12 joerg 2303: __dead static void
1.11 christos 2304: do_check_krl(struct passwd *pw, int argc, char **argv)
2305: {
2306: int i, r, ret = 0;
2307: char *comment;
2308: struct ssh_krl *krl;
1.15 christos 2309: struct sshkey *k;
1.11 christos 2310:
2311: if (*identity_file == '\0')
2312: fatal("KRL checking requires an input file");
2313: load_krl(identity_file, &krl);
2314: for (i = 0; i < argc; i++) {
1.15 christos 2315: if ((r = sshkey_load_public(argv[i], &k, &comment)) != 0)
2316: fatal("Cannot load public key %s: %s",
2317: argv[i], ssh_err(r));
1.11 christos 2318: r = ssh_krl_check_key(krl, k);
2319: printf("%s%s%s%s: %s\n", argv[i],
2320: *comment ? " (" : "", comment, *comment ? ")" : "",
2321: r == 0 ? "ok" : "REVOKED");
2322: if (r != 0)
2323: ret = 1;
1.15 christos 2324: sshkey_free(k);
1.11 christos 2325: free(comment);
2326: }
2327: ssh_krl_free(krl);
2328: exit(ret);
2329: }
1.14 christos 2330: #endif
1.11 christos 2331:
1.12 joerg 2332: __dead static void
1.1 christos 2333: usage(void)
2334: {
1.14 christos 2335: fprintf(stderr,
1.27 christos 2336: "usage: ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa]\n"
1.14 christos 2337: " [-N new_passphrase] [-C comment] [-f output_keyfile]\n"
2338: " ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile]\n"
2339: " ssh-keygen -i [-m key_format] [-f input_keyfile]\n"
2340: " ssh-keygen -e [-m key_format] [-f input_keyfile]\n"
2341: " ssh-keygen -y [-f input_keyfile]\n"
2342: " ssh-keygen -c [-P passphrase] [-C comment] [-f keyfile]\n"
1.15 christos 2343: " ssh-keygen -l [-v] [-E fingerprint_hash] [-f input_keyfile]\n"
1.27 christos 2344: " ssh-keygen -B [-f input_keyfile]\n");
1.4 adam 2345: #ifdef ENABLE_PKCS11
1.14 christos 2346: fprintf(stderr,
2347: " ssh-keygen -D pkcs11\n");
1.4 adam 2348: #endif
1.14 christos 2349: fprintf(stderr,
2350: " ssh-keygen -F hostname [-f known_hosts_file] [-l]\n"
2351: " ssh-keygen -H [-f known_hosts_file]\n"
2352: " ssh-keygen -R hostname [-f known_hosts_file]\n"
2353: " ssh-keygen -r hostname [-f input_keyfile] [-g]\n"
1.17 christos 2354: #ifdef WITH_OPENSSL
1.14 christos 2355: " ssh-keygen -G output_file [-v] [-b bits] [-M memory] [-S start_point]\n"
2356: " ssh-keygen -T output_file -f input_file [-v] [-a rounds] [-J num_lines]\n"
2357: " [-j start_line] [-K checkpt] [-W generator]\n"
1.17 christos 2358: #endif
1.27 christos 2359: " ssh-keygen -s ca_key -I certificate_identity [-h] [-U]\n"
2360: " [-D pkcs11_provider] [-n principals] [-O option]\n"
2361: " [-V validity_interval] [-z serial_number] file ...\n"
1.14 christos 2362: " ssh-keygen -L [-f input_keyfile]\n"
2363: " ssh-keygen -A\n"
2364: " ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]\n"
2365: " file ...\n"
2366: " ssh-keygen -Q -f krl_file file ...\n");
1.1 christos 2367: exit(1);
2368: }
2369:
2370: /*
2371: * Main program for key management.
2372: */
2373: int
2374: main(int argc, char **argv)
2375: {
1.15 christos 2376: char dotsshdir[PATH_MAX], comment[1024], *passphrase1, *passphrase2;
1.17 christos 2377: char *rr_hostname = NULL, *ep, *fp, *ra;
1.15 christos 2378: struct sshkey *private, *public;
1.1 christos 2379: struct passwd *pw;
2380: struct stat st;
1.15 christos 2381: int r, opt, type, fd;
1.17 christos 2382: int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0;
2383: FILE *f;
2384: const char *errstr;
2385: #ifdef WITH_OPENSSL
2386: /* Moduli generation/screening */
2387: char out_file[PATH_MAX], *checkpoint = NULL;
1.14 christos 2388: u_int32_t memory = 0, generator_wanted = 0;
1.1 christos 2389: int do_gen_candidates = 0, do_screen_candidates = 0;
1.10 christos 2390: unsigned long start_lineno = 0, lines_to_process = 0;
1.1 christos 2391: BIGNUM *start = NULL;
1.17 christos 2392: #endif
1.1 christos 2393:
2394: extern int optind;
2395: extern char *optarg;
2396:
1.20 christos 2397: ssh_malloc_init(); /* must be called before any mallocs */
1.1 christos 2398: /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
2399: sanitise_stdfd();
2400:
1.6 christos 2401: OpenSSL_add_all_algorithms();
1.1 christos 2402: log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
2403:
1.26 christos 2404: setlocale(LC_CTYPE, "");
2405:
1.1 christos 2406: /* we need this for the home * directory. */
2407: pw = getpwuid(getuid());
1.17 christos 2408: if (!pw)
2409: fatal("No user exists for uid %lu", (u_long)getuid());
2410: if (gethostname(hostname, sizeof(hostname)) < 0)
2411: fatal("gethostname: %s", strerror(errno));
1.1 christos 2412:
1.27 christos 2413: /* Remaining characters: Ydw */
2414: while ((opt = getopt(argc, argv, "ABHLQUXceghiklopquvxy"
1.15 christos 2415: "C:D:E:F:G:I:J:K:M:N:O:P:R:S:T:V:W:Z:"
2416: "a:b:f:g:j:m:n:r:s:t:z:")) != -1) {
1.1 christos 2417: switch (opt) {
1.7 christos 2418: case 'A':
2419: gen_all_hostkeys = 1;
2420: break;
1.1 christos 2421: case 'b':
1.30 ! christos 2422: bits = (u_int32_t)strtonum(optarg, 10, 32768, &errstr);
1.1 christos 2423: if (errstr)
2424: fatal("Bits has bad value %s (%s)",
2425: optarg, errstr);
2426: break;
1.15 christos 2427: case 'E':
2428: fingerprint_hash = ssh_digest_alg_by_name(optarg);
2429: if (fingerprint_hash == -1)
2430: fatal("Invalid hash algorithm \"%s\"", optarg);
2431: break;
1.1 christos 2432: case 'F':
2433: find_host = 1;
2434: rr_hostname = optarg;
2435: break;
2436: case 'H':
2437: hash_hosts = 1;
2438: break;
1.4 adam 2439: case 'I':
2440: cert_key_id = optarg;
2441: break;
1.1 christos 2442: case 'R':
2443: delete_host = 1;
2444: rr_hostname = optarg;
2445: break;
1.4 adam 2446: case 'L':
2447: show_cert = 1;
2448: break;
1.1 christos 2449: case 'l':
2450: print_fingerprint = 1;
2451: break;
2452: case 'B':
2453: print_bubblebabble = 1;
2454: break;
1.4 adam 2455: case 'm':
2456: if (strcasecmp(optarg, "RFC4716") == 0 ||
2457: strcasecmp(optarg, "ssh2") == 0) {
2458: convert_format = FMT_RFC4716;
2459: break;
2460: }
2461: if (strcasecmp(optarg, "PKCS8") == 0) {
2462: convert_format = FMT_PKCS8;
2463: break;
2464: }
2465: if (strcasecmp(optarg, "PEM") == 0) {
2466: convert_format = FMT_PEM;
2467: break;
2468: }
2469: fatal("Unsupported conversion format \"%s\"", optarg);
2470: case 'n':
2471: cert_principals = optarg;
2472: break;
1.14 christos 2473: case 'o':
2474: use_new_format = 1;
2475: break;
1.1 christos 2476: case 'p':
2477: change_passphrase = 1;
2478: break;
2479: case 'c':
2480: change_comment = 1;
2481: break;
2482: case 'f':
1.17 christos 2483: if (strlcpy(identity_file, optarg,
2484: sizeof(identity_file)) >= sizeof(identity_file))
1.1 christos 2485: fatal("Identity filename too long");
2486: have_identity = 1;
2487: break;
2488: case 'g':
2489: print_generic = 1;
2490: break;
2491: case 'P':
2492: identity_passphrase = optarg;
2493: break;
2494: case 'N':
2495: identity_new_passphrase = optarg;
2496: break;
1.11 christos 2497: case 'Q':
2498: check_krl = 1;
2499: break;
1.4 adam 2500: case 'O':
2501: add_cert_option(optarg);
2502: break;
1.14 christos 2503: case 'Z':
2504: new_format_cipher = optarg;
2505: break;
1.1 christos 2506: case 'C':
2507: identity_comment = optarg;
2508: break;
2509: case 'q':
2510: quiet = 1;
2511: break;
2512: case 'e':
2513: case 'x':
2514: /* export key */
1.4 adam 2515: convert_to = 1;
2516: break;
2517: case 'h':
2518: cert_key_type = SSH2_CERT_TYPE_HOST;
2519: certflags_flags = 0;
1.1 christos 2520: break;
1.11 christos 2521: case 'k':
2522: gen_krl = 1;
2523: break;
1.1 christos 2524: case 'i':
2525: case 'X':
2526: /* import key */
1.4 adam 2527: convert_from = 1;
1.1 christos 2528: break;
2529: case 'y':
2530: print_public = 1;
2531: break;
1.4 adam 2532: case 's':
2533: ca_key_path = optarg;
2534: break;
1.1 christos 2535: case 't':
2536: key_type_name = optarg;
2537: break;
2538: case 'D':
1.4 adam 2539: pkcs11provider = optarg;
1.1 christos 2540: break;
1.27 christos 2541: case 'U':
2542: prefer_agent = 1;
2543: break;
1.11 christos 2544: case 'u':
2545: update_krl = 1;
2546: break;
1.1 christos 2547: case 'v':
2548: if (log_level == SYSLOG_LEVEL_INFO)
2549: log_level = SYSLOG_LEVEL_DEBUG1;
2550: else {
2551: if (log_level >= SYSLOG_LEVEL_DEBUG1 &&
2552: log_level < SYSLOG_LEVEL_DEBUG3)
2553: log_level++;
2554: }
2555: break;
2556: case 'r':
2557: rr_hostname = optarg;
2558: break;
2559: case 'a':
1.14 christos 2560: rounds = (int)strtonum(optarg, 1, INT_MAX, &errstr);
1.1 christos 2561: if (errstr)
1.14 christos 2562: fatal("Invalid number: %s (%s)",
1.1 christos 2563: optarg, errstr);
2564: break;
1.17 christos 2565: case 'V':
2566: parse_cert_times(optarg);
2567: break;
2568: case 'z':
2569: errno = 0;
2570: cert_serial = strtoull(optarg, &ep, 10);
2571: if (*optarg < '0' || *optarg > '9' || *ep != '\0' ||
2572: (errno == ERANGE && cert_serial == ULLONG_MAX))
2573: fatal("Invalid serial number \"%s\"", optarg);
1.1 christos 2574: break;
1.17 christos 2575: #ifdef WITH_OPENSSL
2576: /* Moduli generation/screening */
1.1 christos 2577: case 'G':
2578: do_gen_candidates = 1;
2579: if (strlcpy(out_file, optarg, sizeof(out_file)) >=
2580: sizeof(out_file))
2581: fatal("Output filename too long");
2582: break;
1.17 christos 2583: case 'J':
2584: lines_to_process = strtoul(optarg, NULL, 10);
1.25 christos 2585: break;
1.17 christos 2586: case 'j':
2587: start_lineno = strtoul(optarg, NULL, 10);
1.25 christos 2588: break;
1.9 christos 2589: case 'K':
1.15 christos 2590: if (strlen(optarg) >= PATH_MAX)
1.9 christos 2591: fatal("Checkpoint filename too long");
2592: checkpoint = xstrdup(optarg);
2593: break;
1.17 christos 2594: case 'M':
2595: memory = (u_int32_t)strtonum(optarg, 1, UINT_MAX,
2596: &errstr);
2597: if (errstr)
2598: fatal("Memory limit is %s: %s", errstr, optarg);
2599: break;
1.1 christos 2600: case 'S':
2601: /* XXX - also compare length against bits */
2602: if (BN_hex2bn(&start, optarg) == 0)
2603: fatal("Invalid start point.");
2604: break;
1.17 christos 2605: case 'T':
2606: do_screen_candidates = 1;
2607: if (strlcpy(out_file, optarg, sizeof(out_file)) >=
2608: sizeof(out_file))
2609: fatal("Output filename too long");
1.4 adam 2610: break;
1.17 christos 2611: case 'W':
2612: generator_wanted = (u_int32_t)strtonum(optarg, 1,
2613: UINT_MAX, &errstr);
2614: if (errstr != NULL)
2615: fatal("Desired generator invalid: %s (%s)",
2616: optarg, errstr);
1.4 adam 2617: break;
1.17 christos 2618: #endif /* WITH_OPENSSL */
1.1 christos 2619: case '?':
2620: default:
2621: usage();
2622: }
2623: }
2624:
2625: /* reinit */
2626: log_init(argv[0], log_level, SYSLOG_FACILITY_USER, 1);
2627:
1.4 adam 2628: argv += optind;
2629: argc -= optind;
2630:
2631: if (ca_key_path != NULL) {
1.11 christos 2632: if (argc < 1 && !gen_krl) {
1.17 christos 2633: error("Too few arguments.");
1.4 adam 2634: usage();
2635: }
1.11 christos 2636: } else if (argc > 0 && !gen_krl && !check_krl) {
1.17 christos 2637: error("Too many arguments.");
1.1 christos 2638: usage();
2639: }
2640: if (change_passphrase && change_comment) {
1.17 christos 2641: error("Can only have one of -p and -c.");
1.1 christos 2642: usage();
2643: }
2644: if (print_fingerprint && (delete_host || hash_hosts)) {
1.17 christos 2645: error("Cannot use -l with -H or -R.");
1.1 christos 2646: usage();
2647: }
1.14 christos 2648: #ifdef WITH_OPENSSL
1.11 christos 2649: if (gen_krl) {
2650: do_gen_krl(pw, update_krl, argc, argv);
2651: return (0);
2652: }
2653: if (check_krl) {
2654: do_check_krl(pw, argc, argv);
2655: return (0);
2656: }
1.14 christos 2657: #endif
1.4 adam 2658: if (ca_key_path != NULL) {
2659: if (cert_key_id == NULL)
2660: fatal("Must specify key id (-I) when certifying");
2661: do_ca_sign(pw, argc, argv);
2662: }
2663: if (show_cert)
2664: do_show_cert(pw);
1.1 christos 2665: if (delete_host || hash_hosts || find_host)
2666: do_known_hosts(pw, rr_hostname);
1.11 christos 2667: if (pkcs11provider != NULL)
2668: do_download(pw);
1.1 christos 2669: if (print_fingerprint || print_bubblebabble)
2670: do_fingerprint(pw);
2671: if (change_passphrase)
2672: do_change_passphrase(pw);
2673: if (change_comment)
2674: do_change_comment(pw);
1.14 christos 2675: #ifdef WITH_OPENSSL
1.4 adam 2676: if (convert_to)
2677: do_convert_to(pw);
2678: if (convert_from)
2679: do_convert_from(pw);
1.14 christos 2680: #endif
1.1 christos 2681: if (print_public)
2682: do_print_public(pw);
2683: if (rr_hostname != NULL) {
2684: unsigned int n = 0;
2685:
2686: if (have_identity) {
2687: n = do_print_resource_record(pw,
2688: identity_file, rr_hostname);
1.17 christos 2689: if (n == 0)
2690: fatal("%s: %s", identity_file, strerror(errno));
1.1 christos 2691: exit(0);
2692: } else {
2693:
2694: n += do_print_resource_record(pw,
2695: _PATH_HOST_RSA_KEY_FILE, rr_hostname);
2696: n += do_print_resource_record(pw,
2697: _PATH_HOST_DSA_KEY_FILE, rr_hostname);
1.10 christos 2698: n += do_print_resource_record(pw,
2699: _PATH_HOST_ECDSA_KEY_FILE, rr_hostname);
1.14 christos 2700: n += do_print_resource_record(pw,
2701: _PATH_HOST_ED25519_KEY_FILE, rr_hostname);
1.30 ! christos 2702: n += do_print_resource_record(pw,
! 2703: _PATH_HOST_XMSS_KEY_FILE, rr_hostname);
1.1 christos 2704: if (n == 0)
2705: fatal("no keys found.");
2706: exit(0);
2707: }
2708: }
2709:
1.17 christos 2710: #ifdef WITH_OPENSSL
1.1 christos 2711: if (do_gen_candidates) {
2712: FILE *out = fopen(out_file, "w");
2713:
2714: if (out == NULL) {
2715: error("Couldn't open modulus candidate file \"%s\": %s",
2716: out_file, strerror(errno));
2717: return (1);
2718: }
2719: if (bits == 0)
2720: bits = DEFAULT_BITS;
2721: if (gen_candidates(out, memory, bits, start) != 0)
2722: fatal("modulus candidate generation failed");
2723:
2724: return (0);
2725: }
2726:
2727: if (do_screen_candidates) {
2728: FILE *in;
1.11 christos 2729: FILE *out = fopen(out_file, "a");
1.1 christos 2730:
2731: if (have_identity && strcmp(identity_file, "-") != 0) {
2732: if ((in = fopen(identity_file, "r")) == NULL) {
2733: fatal("Couldn't open modulus candidate "
2734: "file \"%s\": %s", identity_file,
2735: strerror(errno));
2736: }
2737: } else
2738: in = stdin;
2739:
2740: if (out == NULL) {
2741: fatal("Couldn't open moduli file \"%s\": %s",
2742: out_file, strerror(errno));
2743: }
1.14 christos 2744: if (prime_test(in, out, rounds == 0 ? 100 : rounds,
2745: generator_wanted, checkpoint,
1.10 christos 2746: start_lineno, lines_to_process) != 0)
1.1 christos 2747: fatal("modulus screening failed");
2748: return (0);
2749: }
1.17 christos 2750: #endif
1.1 christos 2751:
1.7 christos 2752: if (gen_all_hostkeys) {
2753: do_gen_all_hostkeys(pw);
2754: return (0);
2755: }
2756:
1.1 christos 2757: if (key_type_name == NULL)
1.17 christos 2758: key_type_name = DEFAULT_KEY_TYPE_NAME;
1.1 christos 2759:
1.15 christos 2760: type = sshkey_type_from_name(key_type_name);
2761: type_bits_valid(type, key_type_name, &bits);
1.7 christos 2762:
1.1 christos 2763: if (!quiet)
1.15 christos 2764: printf("Generating public/private %s key pair.\n",
2765: key_type_name);
1.17 christos 2766: if ((r = sshkey_generate(type, bits, &private)) != 0)
1.27 christos 2767: fatal("sshkey_generate failed");
1.17 christos 2768: if ((r = sshkey_from_private(private, &public)) != 0)
1.27 christos 2769: fatal("sshkey_from_private failed: %s\n", ssh_err(r));
1.1 christos 2770:
2771: if (!have_identity)
2772: ask_filename(pw, "Enter file in which to save the key");
2773:
2774: /* Create ~/.ssh directory if it doesn't already exist. */
1.4 adam 2775: snprintf(dotsshdir, sizeof dotsshdir, "%s/%s",
2776: pw->pw_dir, _PATH_SSH_USER_DIR);
2777: if (strstr(identity_file, dotsshdir) != NULL) {
2778: if (stat(dotsshdir, &st) < 0) {
2779: if (errno != ENOENT) {
2780: error("Could not stat %s: %s", dotsshdir,
2781: strerror(errno));
2782: } else if (mkdir(dotsshdir, 0700) < 0) {
2783: error("Could not create directory '%s': %s",
2784: dotsshdir, strerror(errno));
2785: } else if (!quiet)
2786: printf("Created directory '%s'.\n", dotsshdir);
2787: }
1.1 christos 2788: }
2789: /* If the file already exists, ask the user to confirm. */
2790: if (stat(identity_file, &st) >= 0) {
2791: char yesno[3];
2792: printf("%s already exists.\n", identity_file);
2793: printf("Overwrite (y/n)? ");
2794: fflush(stdout);
2795: if (fgets(yesno, sizeof(yesno), stdin) == NULL)
2796: exit(1);
2797: if (yesno[0] != 'y' && yesno[0] != 'Y')
2798: exit(1);
2799: }
2800: /* Ask for a passphrase (twice). */
2801: if (identity_passphrase)
2802: passphrase1 = xstrdup(identity_passphrase);
2803: else if (identity_new_passphrase)
2804: passphrase1 = xstrdup(identity_new_passphrase);
2805: else {
2806: passphrase_again:
2807: passphrase1 =
2808: read_passphrase("Enter passphrase (empty for no "
2809: "passphrase): ", RP_ALLOW_STDIN);
2810: passphrase2 = read_passphrase("Enter same passphrase again: ",
2811: RP_ALLOW_STDIN);
2812: if (strcmp(passphrase1, passphrase2) != 0) {
2813: /*
2814: * The passphrases do not match. Clear them and
2815: * retry.
2816: */
1.14 christos 2817: explicit_bzero(passphrase1, strlen(passphrase1));
2818: explicit_bzero(passphrase2, strlen(passphrase2));
1.13 christos 2819: free(passphrase1);
2820: free(passphrase2);
1.1 christos 2821: printf("Passphrases do not match. Try again.\n");
2822: goto passphrase_again;
2823: }
2824: /* Clear the other copy of the passphrase. */
1.14 christos 2825: explicit_bzero(passphrase2, strlen(passphrase2));
1.13 christos 2826: free(passphrase2);
1.1 christos 2827: }
2828:
2829: if (identity_comment) {
2830: strlcpy(comment, identity_comment, sizeof(comment));
2831: } else {
2832: /* Create default comment field for the passphrase. */
2833: snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname);
2834: }
2835:
2836: /* Save the key with the given passphrase and comment. */
1.15 christos 2837: if ((r = sshkey_save_private(private, identity_file, passphrase1,
2838: comment, use_new_format, new_format_cipher, rounds)) != 0) {
1.17 christos 2839: error("Saving key \"%s\" failed: %s",
1.15 christos 2840: identity_file, ssh_err(r));
1.14 christos 2841: explicit_bzero(passphrase1, strlen(passphrase1));
1.13 christos 2842: free(passphrase1);
1.1 christos 2843: exit(1);
2844: }
2845: /* Clear the passphrase. */
1.14 christos 2846: explicit_bzero(passphrase1, strlen(passphrase1));
1.13 christos 2847: free(passphrase1);
1.1 christos 2848:
2849: /* Clear the private key and the random number generator. */
1.15 christos 2850: sshkey_free(private);
1.1 christos 2851:
2852: if (!quiet)
2853: printf("Your identification has been saved in %s.\n", identity_file);
2854:
2855: strlcat(identity_file, ".pub", sizeof(identity_file));
1.17 christos 2856: if ((fd = open(identity_file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
2857: fatal("Unable to save public key to %s: %s",
2858: identity_file, strerror(errno));
2859: if ((f = fdopen(fd, "w")) == NULL)
2860: fatal("fdopen %s failed: %s", identity_file, strerror(errno));
1.15 christos 2861: if ((r = sshkey_write(public, f)) != 0)
1.17 christos 2862: error("write key failed: %s", ssh_err(r));
1.1 christos 2863: fprintf(f, " %s\n", comment);
1.30 ! christos 2864: if (ferror(f) || fclose(f) != 0)
! 2865: fatal("write public failed: %s", strerror(errno));
1.1 christos 2866:
2867: if (!quiet) {
1.15 christos 2868: fp = sshkey_fingerprint(public, fingerprint_hash,
2869: SSH_FP_DEFAULT);
2870: ra = sshkey_fingerprint(public, fingerprint_hash,
1.1 christos 2871: SSH_FP_RANDOMART);
1.15 christos 2872: if (fp == NULL || ra == NULL)
2873: fatal("sshkey_fingerprint failed");
1.1 christos 2874: printf("Your public key has been saved in %s.\n",
2875: identity_file);
2876: printf("The key fingerprint is:\n");
2877: printf("%s %s\n", fp, comment);
2878: printf("The key's randomart image is:\n");
2879: printf("%s\n", ra);
1.13 christos 2880: free(ra);
2881: free(fp);
1.1 christos 2882: }
2883:
1.15 christos 2884: sshkey_free(public);
1.1 christos 2885: exit(0);
2886: }
CVSweb <webmaster@jp.NetBSD.org>