1 /* $OpenBSD: ssh-keygen.c,v 1.472 2024/01/11 01:45:36 djm Exp $ */
2 /*
3 * Author: Tatu Ylonen <[email protected]>
4 * Copyright (c) 1994 Tatu Ylonen <[email protected]>, Espoo, Finland
5 * All rights reserved
6 * Identity and host key generation and maintenance.
7 *
8 * As far as I am concerned, the code I have written for this software
9 * can be used freely for any purpose. Any derived versions of this
10 * software must be clearly marked as such, and if the derived work is
11 * incompatible with the protocol description in the RFC file, it must be
12 * called by a name other than "ssh" or "Secure Shell".
13 */
14
15 #include "includes.h"
16
17 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <sys/stat.h>
20
21 #ifdef WITH_OPENSSL
22 #include <openssl/evp.h>
23 #include <openssl/pem.h>
24 #include "openbsd-compat/openssl-compat.h"
25 #endif
26
27 #ifdef HAVE_STDINT_H
28 # include <stdint.h>
29 #endif
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <netdb.h>
33 #ifdef HAVE_PATHS_H
34 # include <paths.h>
35 #endif
36 #include <pwd.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <unistd.h>
42 #include <limits.h>
43 #include <locale.h>
44 #include <time.h>
45
46 #include "xmalloc.h"
47 #include "sshkey.h"
48 #include "authfile.h"
49 #include "sshbuf.h"
50 #include "pathnames.h"
51 #include "log.h"
52 #include "misc.h"
53 #include "match.h"
54 #include "hostfile.h"
55 #include "dns.h"
56 #include "ssh.h"
57 #include "ssh2.h"
58 #include "ssherr.h"
59 #include "ssh-pkcs11.h"
60 #include "atomicio.h"
61 #include "krl.h"
62 #include "digest.h"
63 #include "utf8.h"
64 #include "authfd.h"
65 #include "sshsig.h"
66 #include "ssh-sk.h"
67 #include "sk-api.h" /* XXX for SSH_SK_USER_PRESENCE_REQD; remove */
68 #include "cipher.h"
69
70 #ifdef WITH_OPENSSL
71 # define DEFAULT_KEY_TYPE_NAME "rsa"
72 #else
73 # define DEFAULT_KEY_TYPE_NAME "ed25519"
74 #endif
75
76 /*
77 * Default number of bits in the RSA, DSA and ECDSA keys. These value can be
78 * overridden on the command line.
79 *
80 * These values, with the exception of DSA, provide security equivalent to at
81 * least 128 bits of security according to NIST Special Publication 800-57:
82 * Recommendation for Key Management Part 1 rev 4 section 5.6.1.
83 * For DSA it (and FIPS-186-4 section 4.2) specifies that the only size for
84 * which a 160bit hash is acceptable is 1kbit, and since ssh-dss specifies only
85 * SHA1 we limit the DSA key size 1k bits.
86 */
87 #define DEFAULT_BITS 3072
88 #define DEFAULT_BITS_DSA 1024
89 #define DEFAULT_BITS_ECDSA 256
90
91 static int quiet = 0;
92
93 /* Flag indicating that we just want to see the key fingerprint */
94 static int print_fingerprint = 0;
95 static int print_bubblebabble = 0;
96
97 /* Hash algorithm to use for fingerprints. */
98 static int fingerprint_hash = SSH_FP_HASH_DEFAULT;
99
100 /* The identity file name, given on the command line or entered by the user. */
101 static char identity_file[PATH_MAX];
102 static int have_identity = 0;
103
104 /* This is set to the passphrase if given on the command line. */
105 static char *identity_passphrase = NULL;
106
107 /* This is set to the new passphrase if given on the command line. */
108 static char *identity_new_passphrase = NULL;
109
110 /* Key type when certifying */
111 static u_int cert_key_type = SSH2_CERT_TYPE_USER;
112
113 /* "key ID" of signed key */
114 static char *cert_key_id = NULL;
115
116 /* Comma-separated list of principal names for certifying keys */
117 static char *cert_principals = NULL;
118
119 /* Validity period for certificates */
120 static u_int64_t cert_valid_from = 0;
121 static u_int64_t cert_valid_to = ~0ULL;
122
123 /* Certificate options */
124 #define CERTOPT_X_FWD (1)
125 #define CERTOPT_AGENT_FWD (1<<1)
126 #define CERTOPT_PORT_FWD (1<<2)
127 #define CERTOPT_PTY (1<<3)
128 #define CERTOPT_USER_RC (1<<4)
129 #define CERTOPT_NO_REQUIRE_USER_PRESENCE (1<<5)
130 #define CERTOPT_REQUIRE_VERIFY (1<<6)
131 #define CERTOPT_DEFAULT (CERTOPT_X_FWD|CERTOPT_AGENT_FWD| \
132 CERTOPT_PORT_FWD|CERTOPT_PTY|CERTOPT_USER_RC)
133 static u_int32_t certflags_flags = CERTOPT_DEFAULT;
134 static char *certflags_command = NULL;
135 static char *certflags_src_addr = NULL;
136
137 /* Arbitrary extensions specified by user */
138 struct cert_ext {
139 char *key;
140 char *val;
141 int crit;
142 };
143 static struct cert_ext *cert_ext;
144 static size_t ncert_ext;
145
146 /* Conversion to/from various formats */
147 enum {
148 FMT_RFC4716,
149 FMT_PKCS8,
150 FMT_PEM
151 } convert_format = FMT_RFC4716;
152
153 static char *key_type_name = NULL;
154
155 /* Load key from this PKCS#11 provider */
156 static char *pkcs11provider = NULL;
157
158 /* FIDO/U2F provider to use */
159 static char *sk_provider = NULL;
160
161 /* Format for writing private keys */
162 static int private_key_format = SSHKEY_PRIVATE_OPENSSH;
163
164 /* Cipher for new-format private keys */
165 static char *openssh_format_cipher = NULL;
166
167 /* Number of KDF rounds to derive new format keys. */
168 static int rounds = 0;
169
170 /* argv0 */
171 extern char *__progname;
172
173 static char hostname[NI_MAXHOST];
174
175 #ifdef WITH_OPENSSL
176 /* moduli.c */
177 int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *);
178 int prime_test(FILE *, FILE *, u_int32_t, u_int32_t, char *, unsigned long,
179 unsigned long);
180 #endif
181
182 static void
type_bits_valid(int type,const char * name,u_int32_t * bitsp)183 type_bits_valid(int type, const char *name, u_int32_t *bitsp)
184 {
185 if (type == KEY_UNSPEC)
186 fatal("unknown key type %s", key_type_name);
187 if (*bitsp == 0) {
188 #ifdef WITH_OPENSSL
189 int nid;
190
191 switch(type) {
192 case KEY_DSA:
193 *bitsp = DEFAULT_BITS_DSA;
194 break;
195 case KEY_ECDSA:
196 if (name != NULL &&
197 (nid = sshkey_ecdsa_nid_from_name(name)) > 0)
198 *bitsp = sshkey_curve_nid_to_bits(nid);
199 if (*bitsp == 0)
200 *bitsp = DEFAULT_BITS_ECDSA;
201 break;
202 case KEY_RSA:
203 *bitsp = DEFAULT_BITS;
204 break;
205 }
206 #endif
207 }
208 #ifdef WITH_OPENSSL
209 switch (type) {
210 case KEY_DSA:
211 if (*bitsp != 1024)
212 fatal("Invalid DSA key length: must be 1024 bits");
213 break;
214 case KEY_RSA:
215 if (*bitsp < SSH_RSA_MINIMUM_MODULUS_SIZE)
216 fatal("Invalid RSA key length: minimum is %d bits",
217 SSH_RSA_MINIMUM_MODULUS_SIZE);
218 else if (*bitsp > OPENSSL_RSA_MAX_MODULUS_BITS)
219 fatal("Invalid RSA key length: maximum is %d bits",
220 OPENSSL_RSA_MAX_MODULUS_BITS);
221 break;
222 case KEY_ECDSA:
223 if (sshkey_ecdsa_bits_to_nid(*bitsp) == -1)
224 #ifdef OPENSSL_HAS_NISTP521
225 fatal("Invalid ECDSA key length: valid lengths are "
226 "256, 384 or 521 bits");
227 #else
228 fatal("Invalid ECDSA key length: valid lengths are "
229 "256 or 384 bits");
230 #endif
231 }
232 #endif
233 }
234
235 /*
236 * Checks whether a file exists and, if so, asks the user whether they wish
237 * to overwrite it.
238 * Returns nonzero if the file does not already exist or if the user agrees to
239 * overwrite, or zero otherwise.
240 */
241 static int
confirm_overwrite(const char * filename)242 confirm_overwrite(const char *filename)
243 {
244 char yesno[3];
245 struct stat st;
246
247 if (stat(filename, &st) != 0)
248 return 1;
249 printf("%s already exists.\n", filename);
250 printf("Overwrite (y/n)? ");
251 fflush(stdout);
252 if (fgets(yesno, sizeof(yesno), stdin) == NULL)
253 return 0;
254 if (yesno[0] != 'y' && yesno[0] != 'Y')
255 return 0;
256 return 1;
257 }
258
259 static void
ask_filename(struct passwd * pw,const char * prompt)260 ask_filename(struct passwd *pw, const char *prompt)
261 {
262 char buf[1024];
263 char *name = NULL;
264
265 if (key_type_name == NULL)
266 name = _PATH_SSH_CLIENT_ID_RSA;
267 else {
268 switch (sshkey_type_from_name(key_type_name)) {
269 #ifdef WITH_DSA
270 case KEY_DSA_CERT:
271 case KEY_DSA:
272 name = _PATH_SSH_CLIENT_ID_DSA;
273 break;
274 #endif
275 #ifdef OPENSSL_HAS_ECC
276 case KEY_ECDSA_CERT:
277 case KEY_ECDSA:
278 name = _PATH_SSH_CLIENT_ID_ECDSA;
279 break;
280 case KEY_ECDSA_SK_CERT:
281 case KEY_ECDSA_SK:
282 name = _PATH_SSH_CLIENT_ID_ECDSA_SK;
283 break;
284 #endif
285 case KEY_RSA_CERT:
286 case KEY_RSA:
287 name = _PATH_SSH_CLIENT_ID_RSA;
288 break;
289 case KEY_ED25519:
290 case KEY_ED25519_CERT:
291 name = _PATH_SSH_CLIENT_ID_ED25519;
292 break;
293 case KEY_ED25519_SK:
294 case KEY_ED25519_SK_CERT:
295 name = _PATH_SSH_CLIENT_ID_ED25519_SK;
296 break;
297 case KEY_XMSS:
298 case KEY_XMSS_CERT:
299 name = _PATH_SSH_CLIENT_ID_XMSS;
300 break;
301 default:
302 fatal("bad key type");
303 }
304 }
305 snprintf(identity_file, sizeof(identity_file),
306 "%s/%s", pw->pw_dir, name);
307 printf("%s (%s): ", prompt, identity_file);
308 fflush(stdout);
309 if (fgets(buf, sizeof(buf), stdin) == NULL)
310 exit(1);
311 buf[strcspn(buf, "\n")] = '\0';
312 if (strcmp(buf, "") != 0)
313 strlcpy(identity_file, buf, sizeof(identity_file));
314 have_identity = 1;
315 }
316
317 static struct sshkey *
load_identity(const char * filename,char ** commentp)318 load_identity(const char *filename, char **commentp)
319 {
320 char *pass;
321 struct sshkey *prv;
322 int r;
323
324 if (commentp != NULL)
325 *commentp = NULL;
326 if ((r = sshkey_load_private(filename, "", &prv, commentp)) == 0)
327 return prv;
328 if (r != SSH_ERR_KEY_WRONG_PASSPHRASE)
329 fatal_r(r, "Load key \"%s\"", filename);
330 if (identity_passphrase)
331 pass = xstrdup(identity_passphrase);
332 else
333 pass = read_passphrase("Enter passphrase: ", RP_ALLOW_STDIN);
334 r = sshkey_load_private(filename, pass, &prv, commentp);
335 freezero(pass, strlen(pass));
336 if (r != 0)
337 fatal_r(r, "Load key \"%s\"", filename);
338 return prv;
339 }
340
341 #define SSH_COM_PUBLIC_BEGIN "---- BEGIN SSH2 PUBLIC KEY ----"
342 #define SSH_COM_PUBLIC_END "---- END SSH2 PUBLIC KEY ----"
343 #define SSH_COM_PRIVATE_BEGIN "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"
344 #define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb
345
346 #ifdef WITH_OPENSSL
347 static void
do_convert_to_ssh2(struct passwd * pw,struct sshkey * k)348 do_convert_to_ssh2(struct passwd *pw, struct sshkey *k)
349 {
350 struct sshbuf *b;
351 char comment[61], *b64;
352 int r;
353
354 if ((b = sshbuf_new()) == NULL)
355 fatal_f("sshbuf_new failed");
356 if ((r = sshkey_putb(k, b)) != 0)
357 fatal_fr(r, "put key");
358 if ((b64 = sshbuf_dtob64_string(b, 1)) == NULL)
359 fatal_f("sshbuf_dtob64_string failed");
360
361 /* Comment + surrounds must fit into 72 chars (RFC 4716 sec 3.3) */
362 snprintf(comment, sizeof(comment),
363 "%u-bit %s, converted by %s@%s from OpenSSH",
364 sshkey_size(k), sshkey_type(k),
365 pw->pw_name, hostname);
366
367 sshkey_free(k);
368 sshbuf_free(b);
369
370 fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN);
371 fprintf(stdout, "Comment: \"%s\"\n%s", comment, b64);
372 fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END);
373 free(b64);
374 exit(0);
375 }
376
377 static void
do_convert_to_pkcs8(struct sshkey * k)378 do_convert_to_pkcs8(struct sshkey *k)
379 {
380 switch (sshkey_type_plain(k->type)) {
381 case KEY_RSA:
382 if (!PEM_write_RSA_PUBKEY(stdout, k->rsa))
383 fatal("PEM_write_RSA_PUBKEY failed");
384 break;
385 #ifdef WITH_DSA
386 case KEY_DSA:
387 if (!PEM_write_DSA_PUBKEY(stdout, k->dsa))
388 fatal("PEM_write_DSA_PUBKEY failed");
389 break;
390 #endif
391 #ifdef OPENSSL_HAS_ECC
392 case KEY_ECDSA:
393 if (!PEM_write_EC_PUBKEY(stdout, k->ecdsa))
394 fatal("PEM_write_EC_PUBKEY failed");
395 break;
396 #endif
397 default:
398 fatal_f("unsupported key type %s", sshkey_type(k));
399 }
400 exit(0);
401 }
402
403 static void
do_convert_to_pem(struct sshkey * k)404 do_convert_to_pem(struct sshkey *k)
405 {
406 switch (sshkey_type_plain(k->type)) {
407 case KEY_RSA:
408 if (!PEM_write_RSAPublicKey(stdout, k->rsa))
409 fatal("PEM_write_RSAPublicKey failed");
410 break;
411 #ifdef WITH_DSA
412 case KEY_DSA:
413 if (!PEM_write_DSA_PUBKEY(stdout, k->dsa))
414 fatal("PEM_write_DSA_PUBKEY failed");
415 break;
416 #endif
417 #ifdef OPENSSL_HAS_ECC
418 case KEY_ECDSA:
419 if (!PEM_write_EC_PUBKEY(stdout, k->ecdsa))
420 fatal("PEM_write_EC_PUBKEY failed");
421 break;
422 #endif
423 default:
424 fatal_f("unsupported key type %s", sshkey_type(k));
425 }
426 exit(0);
427 }
428
429 static void
do_convert_to(struct passwd * pw)430 do_convert_to(struct passwd *pw)
431 {
432 struct sshkey *k;
433 struct stat st;
434 int r;
435
436 if (!have_identity)
437 ask_filename(pw, "Enter file in which the key is");
438 if (stat(identity_file, &st) == -1)
439 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
440 if ((r = sshkey_load_public(identity_file, &k, NULL)) != 0)
441 k = load_identity(identity_file, NULL);
442 switch (convert_format) {
443 case FMT_RFC4716:
444 do_convert_to_ssh2(pw, k);
445 break;
446 case FMT_PKCS8:
447 do_convert_to_pkcs8(k);
448 break;
449 case FMT_PEM:
450 do_convert_to_pem(k);
451 break;
452 default:
453 fatal_f("unknown key format %d", convert_format);
454 }
455 exit(0);
456 }
457
458 /*
459 * This is almost exactly the bignum1 encoding, but with 32 bit for length
460 * instead of 16.
461 */
462 static void
buffer_get_bignum_bits(struct sshbuf * b,BIGNUM * value)463 buffer_get_bignum_bits(struct sshbuf *b, BIGNUM *value)
464 {
465 u_int bytes, bignum_bits;
466 int r;
467
468 if ((r = sshbuf_get_u32(b, &bignum_bits)) != 0)
469 fatal_fr(r, "parse");
470 bytes = (bignum_bits + 7) / 8;
471 if (sshbuf_len(b) < bytes)
472 fatal_f("input buffer too small: need %d have %zu",
473 bytes, sshbuf_len(b));
474 if (BN_bin2bn(sshbuf_ptr(b), bytes, value) == NULL)
475 fatal_f("BN_bin2bn failed");
476 if ((r = sshbuf_consume(b, bytes)) != 0)
477 fatal_fr(r, "consume");
478 }
479
480 static struct sshkey *
do_convert_private_ssh2(struct sshbuf * b)481 do_convert_private_ssh2(struct sshbuf *b)
482 {
483 struct sshkey *key = NULL;
484 char *type, *cipher;
485 const char *alg = NULL;
486 u_char e1, e2, e3, *sig = NULL, data[] = "abcde12345";
487 int r, rlen, ktype;
488 u_int magic, i1, i2, i3, i4;
489 size_t slen;
490 u_long e;
491 #ifdef WITH_DSA
492 BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL;
493 BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL;
494 #endif
495 BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
496 BIGNUM *rsa_p = NULL, *rsa_q = NULL, *rsa_iqmp = NULL;
497
498 if ((r = sshbuf_get_u32(b, &magic)) != 0)
499 fatal_fr(r, "parse magic");
500
501 if (magic != SSH_COM_PRIVATE_KEY_MAGIC) {
502 error("bad magic 0x%x != 0x%x", magic,
503 SSH_COM_PRIVATE_KEY_MAGIC);
504 return NULL;
505 }
506 if ((r = sshbuf_get_u32(b, &i1)) != 0 ||
507 (r = sshbuf_get_cstring(b, &type, NULL)) != 0 ||
508 (r = sshbuf_get_cstring(b, &cipher, NULL)) != 0 ||
509 (r = sshbuf_get_u32(b, &i2)) != 0 ||
510 (r = sshbuf_get_u32(b, &i3)) != 0 ||
511 (r = sshbuf_get_u32(b, &i4)) != 0)
512 fatal_fr(r, "parse");
513 debug("ignore (%d %d %d %d)", i1, i2, i3, i4);
514 if (strcmp(cipher, "none") != 0) {
515 error("unsupported cipher %s", cipher);
516 free(cipher);
517 free(type);
518 return NULL;
519 }
520 free(cipher);
521
522 if (strstr(type, "rsa")) {
523 ktype = KEY_RSA;
524 #ifdef WITH_DSA
525 } else if (strstr(type, "dsa")) {
526 ktype = KEY_DSA;
527 #endif
528 } else {
529 free(type);
530 return NULL;
531 }
532 if ((key = sshkey_new(ktype)) == NULL)
533 fatal("sshkey_new failed");
534 free(type);
535
536 switch (key->type) {
537 #ifdef WITH_DSA
538 case KEY_DSA:
539 if ((dsa_p = BN_new()) == NULL ||
540 (dsa_q = BN_new()) == NULL ||
541 (dsa_g = BN_new()) == NULL ||
542 (dsa_pub_key = BN_new()) == NULL ||
543 (dsa_priv_key = BN_new()) == NULL)
544 fatal_f("BN_new");
545 buffer_get_bignum_bits(b, dsa_p);
546 buffer_get_bignum_bits(b, dsa_g);
547 buffer_get_bignum_bits(b, dsa_q);
548 buffer_get_bignum_bits(b, dsa_pub_key);
549 buffer_get_bignum_bits(b, dsa_priv_key);
550 if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g))
551 fatal_f("DSA_set0_pqg failed");
552 dsa_p = dsa_q = dsa_g = NULL; /* transferred */
553 if (!DSA_set0_key(key->dsa, dsa_pub_key, dsa_priv_key))
554 fatal_f("DSA_set0_key failed");
555 dsa_pub_key = dsa_priv_key = NULL; /* transferred */
556 break;
557 #endif
558 case KEY_RSA:
559 if ((r = sshbuf_get_u8(b, &e1)) != 0 ||
560 (e1 < 30 && (r = sshbuf_get_u8(b, &e2)) != 0) ||
561 (e1 < 30 && (r = sshbuf_get_u8(b, &e3)) != 0))
562 fatal_fr(r, "parse RSA");
563 e = e1;
564 debug("e %lx", e);
565 if (e < 30) {
566 e <<= 8;
567 e += e2;
568 debug("e %lx", e);
569 e <<= 8;
570 e += e3;
571 debug("e %lx", e);
572 }
573 if ((rsa_e = BN_new()) == NULL)
574 fatal_f("BN_new");
575 if (!BN_set_word(rsa_e, e)) {
576 BN_clear_free(rsa_e);
577 sshkey_free(key);
578 return NULL;
579 }
580 if ((rsa_n = BN_new()) == NULL ||
581 (rsa_d = BN_new()) == NULL ||
582 (rsa_p = BN_new()) == NULL ||
583 (rsa_q = BN_new()) == NULL ||
584 (rsa_iqmp = BN_new()) == NULL)
585 fatal_f("BN_new");
586 buffer_get_bignum_bits(b, rsa_d);
587 buffer_get_bignum_bits(b, rsa_n);
588 buffer_get_bignum_bits(b, rsa_iqmp);
589 buffer_get_bignum_bits(b, rsa_q);
590 buffer_get_bignum_bits(b, rsa_p);
591 if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, rsa_d))
592 fatal_f("RSA_set0_key failed");
593 rsa_n = rsa_e = rsa_d = NULL; /* transferred */
594 if (!RSA_set0_factors(key->rsa, rsa_p, rsa_q))
595 fatal_f("RSA_set0_factors failed");
596 rsa_p = rsa_q = NULL; /* transferred */
597 if ((r = ssh_rsa_complete_crt_parameters(key, rsa_iqmp)) != 0)
598 fatal_fr(r, "generate RSA parameters");
599 BN_clear_free(rsa_iqmp);
600 alg = "rsa-sha2-256";
601 break;
602 }
603 rlen = sshbuf_len(b);
604 if (rlen != 0)
605 error_f("remaining bytes in key blob %d", rlen);
606
607 /* try the key */
608 if ((r = sshkey_sign(key, &sig, &slen, data, sizeof(data),
609 alg, NULL, NULL, 0)) != 0)
610 error_fr(r, "signing with converted key failed");
611 else if ((r = sshkey_verify(key, sig, slen, data, sizeof(data),
612 alg, 0, NULL)) != 0)
613 error_fr(r, "verification with converted key failed");
614 if (r != 0) {
615 sshkey_free(key);
616 free(sig);
617 return NULL;
618 }
619 free(sig);
620 return key;
621 }
622
623 static int
get_line(FILE * fp,char * line,size_t len)624 get_line(FILE *fp, char *line, size_t len)
625 {
626 int c;
627 size_t pos = 0;
628
629 line[0] = '\0';
630 while ((c = fgetc(fp)) != EOF) {
631 if (pos >= len - 1)
632 fatal("input line too long.");
633 switch (c) {
634 case '\r':
635 c = fgetc(fp);
636 if (c != EOF && c != '\n' && ungetc(c, fp) == EOF)
637 fatal("unget: %s", strerror(errno));
638 return pos;
639 case '\n':
640 return pos;
641 }
642 line[pos++] = c;
643 line[pos] = '\0';
644 }
645 /* We reached EOF */
646 return -1;
647 }
648
649 static void
do_convert_from_ssh2(struct passwd * pw,struct sshkey ** k,int * private)650 do_convert_from_ssh2(struct passwd *pw, struct sshkey **k, int *private)
651 {
652 int r, blen, escaped = 0;
653 u_int len;
654 char line[1024];
655 struct sshbuf *buf;
656 char encoded[8096];
657 FILE *fp;
658
659 if ((buf = sshbuf_new()) == NULL)
660 fatal("sshbuf_new failed");
661 if ((fp = fopen(identity_file, "r")) == NULL)
662 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
663 encoded[0] = '\0';
664 while ((blen = get_line(fp, line, sizeof(line))) != -1) {
665 if (blen > 0 && line[blen - 1] == '\\')
666 escaped++;
667 if (strncmp(line, "----", 4) == 0 ||
668 strstr(line, ": ") != NULL) {
669 if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL)
670 *private = 1;
671 if (strstr(line, " END ") != NULL) {
672 break;
673 }
674 /* fprintf(stderr, "ignore: %s", line); */
675 continue;
676 }
677 if (escaped) {
678 escaped--;
679 /* fprintf(stderr, "escaped: %s", line); */
680 continue;
681 }
682 strlcat(encoded, line, sizeof(encoded));
683 }
684 len = strlen(encoded);
685 if (((len % 4) == 3) &&
686 (encoded[len-1] == '=') &&
687 (encoded[len-2] == '=') &&
688 (encoded[len-3] == '='))
689 encoded[len-3] = '\0';
690 if ((r = sshbuf_b64tod(buf, encoded)) != 0)
691 fatal_fr(r, "base64 decode");
692 if (*private) {
693 if ((*k = do_convert_private_ssh2(buf)) == NULL)
694 fatal_f("private key conversion failed");
695 } else if ((r = sshkey_fromb(buf, k)) != 0)
696 fatal_fr(r, "parse key");
697 sshbuf_free(buf);
698 fclose(fp);
699 }
700
701 static void
do_convert_from_pkcs8(struct sshkey ** k,int * private)702 do_convert_from_pkcs8(struct sshkey **k, int *private)
703 {
704 EVP_PKEY *pubkey;
705 FILE *fp;
706
707 if ((fp = fopen(identity_file, "r")) == NULL)
708 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
709 if ((pubkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) {
710 fatal_f("%s is not a recognised public key format",
711 identity_file);
712 }
713 fclose(fp);
714 switch (EVP_PKEY_base_id(pubkey)) {
715 case EVP_PKEY_RSA:
716 if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
717 fatal("sshkey_new failed");
718 (*k)->type = KEY_RSA;
719 (*k)->rsa = EVP_PKEY_get1_RSA(pubkey);
720 break;
721 #ifdef WITH_DSA
722 case EVP_PKEY_DSA:
723 if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
724 fatal("sshkey_new failed");
725 (*k)->type = KEY_DSA;
726 (*k)->dsa = EVP_PKEY_get1_DSA(pubkey);
727 break;
728 #endif
729 #ifdef OPENSSL_HAS_ECC
730 case EVP_PKEY_EC:
731 if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
732 fatal("sshkey_new failed");
733 (*k)->type = KEY_ECDSA;
734 (*k)->ecdsa = EVP_PKEY_get1_EC_KEY(pubkey);
735 (*k)->ecdsa_nid = sshkey_ecdsa_key_to_nid((*k)->ecdsa);
736 break;
737 #endif
738 default:
739 fatal_f("unsupported pubkey type %d",
740 EVP_PKEY_base_id(pubkey));
741 }
742 EVP_PKEY_free(pubkey);
743 return;
744 }
745
746 static void
do_convert_from_pem(struct sshkey ** k,int * private)747 do_convert_from_pem(struct sshkey **k, int *private)
748 {
749 FILE *fp;
750 RSA *rsa;
751
752 if ((fp = fopen(identity_file, "r")) == NULL)
753 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
754 if ((rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL)) != NULL) {
755 if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
756 fatal("sshkey_new failed");
757 (*k)->type = KEY_RSA;
758 (*k)->rsa = rsa;
759 fclose(fp);
760 return;
761 }
762 fatal_f("unrecognised raw private key format");
763 }
764
765 static void
do_convert_from(struct passwd * pw)766 do_convert_from(struct passwd *pw)
767 {
768 struct sshkey *k = NULL;
769 int r, private = 0, ok = 0;
770 struct stat st;
771
772 if (!have_identity)
773 ask_filename(pw, "Enter file in which the key is");
774 if (stat(identity_file, &st) == -1)
775 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
776
777 switch (convert_format) {
778 case FMT_RFC4716:
779 do_convert_from_ssh2(pw, &k, &private);
780 break;
781 case FMT_PKCS8:
782 do_convert_from_pkcs8(&k, &private);
783 break;
784 case FMT_PEM:
785 do_convert_from_pem(&k, &private);
786 break;
787 default:
788 fatal_f("unknown key format %d", convert_format);
789 }
790
791 if (!private) {
792 if ((r = sshkey_write(k, stdout)) == 0)
793 ok = 1;
794 if (ok)
795 fprintf(stdout, "\n");
796 } else {
797 switch (k->type) {
798 #ifdef WITH_DSA
799 case KEY_DSA:
800 ok = PEM_write_DSAPrivateKey(stdout, k->dsa, NULL,
801 NULL, 0, NULL, NULL);
802 break;
803 #endif
804 #ifdef OPENSSL_HAS_ECC
805 case KEY_ECDSA:
806 ok = PEM_write_ECPrivateKey(stdout, k->ecdsa, NULL,
807 NULL, 0, NULL, NULL);
808 break;
809 #endif
810 case KEY_RSA:
811 ok = PEM_write_RSAPrivateKey(stdout, k->rsa, NULL,
812 NULL, 0, NULL, NULL);
813 break;
814 default:
815 fatal_f("unsupported key type %s", sshkey_type(k));
816 }
817 }
818
819 if (!ok)
820 fatal("key write failed");
821 sshkey_free(k);
822 exit(0);
823 }
824 #endif
825
826 static void
do_print_public(struct passwd * pw)827 do_print_public(struct passwd *pw)
828 {
829 struct sshkey *prv;
830 struct stat st;
831 int r;
832 char *comment = NULL;
833
834 if (!have_identity)
835 ask_filename(pw, "Enter file in which the key is");
836 if (stat(identity_file, &st) == -1)
837 fatal("%s: %s", identity_file, strerror(errno));
838 prv = load_identity(identity_file, &comment);
839 if ((r = sshkey_write(prv, stdout)) != 0)
840 fatal_fr(r, "write key");
841 if (comment != NULL && *comment != '\0')
842 fprintf(stdout, " %s", comment);
843 fprintf(stdout, "\n");
844 if (sshkey_is_sk(prv)) {
845 debug("sk_application: \"%s\", sk_flags 0x%02x",
846 prv->sk_application, prv->sk_flags);
847 }
848 sshkey_free(prv);
849 free(comment);
850 exit(0);
851 }
852
853 static void
do_download(struct passwd * pw)854 do_download(struct passwd *pw)
855 {
856 #ifdef ENABLE_PKCS11
857 struct sshkey **keys = NULL;
858 int i, nkeys;
859 enum sshkey_fp_rep rep;
860 int fptype;
861 char *fp, *ra, **comments = NULL;
862
863 fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash;
864 rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
865
866 pkcs11_init(1);
867 nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys, &comments);
868 if (nkeys <= 0)
869 fatal("cannot read public key from pkcs11");
870 for (i = 0; i < nkeys; i++) {
871 if (print_fingerprint) {
872 fp = sshkey_fingerprint(keys[i], fptype, rep);
873 ra = sshkey_fingerprint(keys[i], fingerprint_hash,
874 SSH_FP_RANDOMART);
875 if (fp == NULL || ra == NULL)
876 fatal_f("sshkey_fingerprint fail");
877 printf("%u %s %s (PKCS11 key)\n", sshkey_size(keys[i]),
878 fp, sshkey_type(keys[i]));
879 if (log_level_get() >= SYSLOG_LEVEL_VERBOSE)
880 printf("%s\n", ra);
881 free(ra);
882 free(fp);
883 } else {
884 (void) sshkey_write(keys[i], stdout); /* XXX check */
885 fprintf(stdout, "%s%s\n",
886 *(comments[i]) == '\0' ? "" : " ", comments[i]);
887 }
888 free(comments[i]);
889 sshkey_free(keys[i]);
890 }
891 free(comments);
892 free(keys);
893 pkcs11_terminate();
894 exit(0);
895 #else
896 fatal("no pkcs11 support");
897 #endif /* ENABLE_PKCS11 */
898 }
899
900 static struct sshkey *
try_read_key(char ** cpp)901 try_read_key(char **cpp)
902 {
903 struct sshkey *ret;
904 int r;
905
906 if ((ret = sshkey_new(KEY_UNSPEC)) == NULL)
907 fatal("sshkey_new failed");
908 if ((r = sshkey_read(ret, cpp)) == 0)
909 return ret;
910 /* Not a key */
911 sshkey_free(ret);
912 return NULL;
913 }
914
915 static void
fingerprint_one_key(const struct sshkey * public,const char * comment)916 fingerprint_one_key(const struct sshkey *public, const char *comment)
917 {
918 char *fp = NULL, *ra = NULL;
919 enum sshkey_fp_rep rep;
920 int fptype;
921
922 fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash;
923 rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
924 fp = sshkey_fingerprint(public, fptype, rep);
925 ra = sshkey_fingerprint(public, fingerprint_hash, SSH_FP_RANDOMART);
926 if (fp == NULL || ra == NULL)
927 fatal_f("sshkey_fingerprint failed");
928 mprintf("%u %s %s (%s)\n", sshkey_size(public), fp,
929 comment ? comment : "no comment", sshkey_type(public));
930 if (log_level_get() >= SYSLOG_LEVEL_VERBOSE)
931 printf("%s\n", ra);
932 free(ra);
933 free(fp);
934 }
935
936 static void
fingerprint_private(const char * path)937 fingerprint_private(const char *path)
938 {
939 struct stat st;
940 char *comment = NULL;
941 struct sshkey *privkey = NULL, *pubkey = NULL;
942 int r;
943
944 if (stat(identity_file, &st) == -1)
945 fatal("%s: %s", path, strerror(errno));
946 if ((r = sshkey_load_public(path, &pubkey, &comment)) != 0)
947 debug_r(r, "load public \"%s\"", path);
948 if (pubkey == NULL || comment == NULL || *comment == '\0') {
949 free(comment);
950 if ((r = sshkey_load_private(path, NULL,
951 &privkey, &comment)) != 0)
952 debug_r(r, "load private \"%s\"", path);
953 }
954 if (pubkey == NULL && privkey == NULL)
955 fatal("%s is not a key file.", path);
956
957 fingerprint_one_key(pubkey == NULL ? privkey : pubkey, comment);
958 sshkey_free(pubkey);
959 sshkey_free(privkey);
960 free(comment);
961 }
962
963 static void
do_fingerprint(struct passwd * pw)964 do_fingerprint(struct passwd *pw)
965 {
966 FILE *f;
967 struct sshkey *public = NULL;
968 char *comment = NULL, *cp, *ep, *line = NULL;
969 size_t linesize = 0;
970 int i, invalid = 1;
971 const char *path;
972 u_long lnum = 0;
973
974 if (!have_identity)
975 ask_filename(pw, "Enter file in which the key is");
976 path = identity_file;
977
978 if (strcmp(identity_file, "-") == 0) {
979 f = stdin;
980 path = "(stdin)";
981 } else if ((f = fopen(path, "r")) == NULL)
982 fatal("%s: %s: %s", __progname, path, strerror(errno));
983
984 while (getline(&line, &linesize, f) != -1) {
985 lnum++;
986 cp = line;
987 cp[strcspn(cp, "\n")] = '\0';
988 /* Trim leading space and comments */
989 cp = line + strspn(line, " \t");
990 if (*cp == '#' || *cp == '\0')
991 continue;
992
993 /*
994 * Input may be plain keys, private keys, authorized_keys
995 * or known_hosts.
996 */
997
998 /*
999 * Try private keys first. Assume a key is private if
1000 * "SSH PRIVATE KEY" appears on the first line and we're
1001 * not reading from stdin (XXX support private keys on stdin).
1002 */
1003 if (lnum == 1 && strcmp(identity_file, "-") != 0 &&
1004 strstr(cp, "PRIVATE KEY") != NULL) {
1005 free(line);
1006 fclose(f);
1007 fingerprint_private(path);
1008 exit(0);
1009 }
1010
1011 /*
1012 * If it's not a private key, then this must be prepared to
1013 * accept a public key prefixed with a hostname or options.
1014 * Try a bare key first, otherwise skip the leading stuff.
1015 */
1016 comment = NULL;
1017 if ((public = try_read_key(&cp)) == NULL) {
1018 i = strtol(cp, &ep, 10);
1019 if (i == 0 || ep == NULL ||
1020 (*ep != ' ' && *ep != '\t')) {
1021 int quoted = 0;
1022
1023 comment = cp;
1024 for (; *cp && (quoted || (*cp != ' ' &&
1025 *cp != '\t')); cp++) {
1026 if (*cp == '\\' && cp[1] == '"')
1027 cp++; /* Skip both */
1028 else if (*cp == '"')
1029 quoted = !quoted;
1030 }
1031 if (!*cp)
1032 continue;
1033 *cp++ = '\0';
1034 }
1035 }
1036 /* Retry after parsing leading hostname/key options */
1037 if (public == NULL && (public = try_read_key(&cp)) == NULL) {
1038 debug("%s:%lu: not a public key", path, lnum);
1039 continue;
1040 }
1041
1042 /* Find trailing comment, if any */
1043 for (; *cp == ' ' || *cp == '\t'; cp++)
1044 ;
1045 if (*cp != '\0' && *cp != '#')
1046 comment = cp;
1047
1048 fingerprint_one_key(public, comment);
1049 sshkey_free(public);
1050 invalid = 0; /* One good key in the file is sufficient */
1051 }
1052 fclose(f);
1053 free(line);
1054
1055 if (invalid)
1056 fatal("%s is not a public key file.", path);
1057 exit(0);
1058 }
1059
1060 static void
do_gen_all_hostkeys(struct passwd * pw)1061 do_gen_all_hostkeys(struct passwd *pw)
1062 {
1063 struct {
1064 char *key_type;
1065 char *key_type_display;
1066 char *path;
1067 } key_types[] = {
1068 #ifdef WITH_OPENSSL
1069 { "rsa", "RSA" ,_PATH_HOST_RSA_KEY_FILE },
1070 #ifdef OPENSSL_HAS_ECC
1071 { "ecdsa", "ECDSA",_PATH_HOST_ECDSA_KEY_FILE },
1072 #endif /* OPENSSL_HAS_ECC */
1073 #endif /* WITH_OPENSSL */
1074 { "ed25519", "ED25519",_PATH_HOST_ED25519_KEY_FILE },
1075 #ifdef WITH_XMSS
1076 { "xmss", "XMSS",_PATH_HOST_XMSS_KEY_FILE },
1077 #endif /* WITH_XMSS */
1078 { NULL, NULL, NULL }
1079 };
1080
1081 u_int32_t bits = 0;
1082 int first = 0;
1083 struct stat st;
1084 struct sshkey *private, *public;
1085 char comment[1024], *prv_tmp, *pub_tmp, *prv_file, *pub_file;
1086 int i, type, fd, r;
1087
1088 for (i = 0; key_types[i].key_type; i++) {
1089 public = private = NULL;
1090 prv_tmp = pub_tmp = prv_file = pub_file = NULL;
1091
1092 xasprintf(&prv_file, "%s%s",
1093 identity_file, key_types[i].path);
1094
1095 /* Check whether private key exists and is not zero-length */
1096 if (stat(prv_file, &st) == 0) {
1097 if (st.st_size != 0)
1098 goto next;
1099 } else if (errno != ENOENT) {
1100 error("Could not stat %s: %s", key_types[i].path,
1101 strerror(errno));
1102 goto failnext;
1103 }
1104
1105 /*
1106 * Private key doesn't exist or is invalid; proceed with
1107 * key generation.
1108 */
1109 xasprintf(&prv_tmp, "%s%s.XXXXXXXXXX",
1110 identity_file, key_types[i].path);
1111 xasprintf(&pub_tmp, "%s%s.pub.XXXXXXXXXX",
1112 identity_file, key_types[i].path);
1113 xasprintf(&pub_file, "%s%s.pub",
1114 identity_file, key_types[i].path);
1115
1116 if (first == 0) {
1117 first = 1;
1118 printf("%s: generating new host keys: ", __progname);
1119 }
1120 printf("%s ", key_types[i].key_type_display);
1121 fflush(stdout);
1122 type = sshkey_type_from_name(key_types[i].key_type);
1123 if ((fd = mkstemp(prv_tmp)) == -1) {
1124 error("Could not save your private key in %s: %s",
1125 prv_tmp, strerror(errno));
1126 goto failnext;
1127 }
1128 (void)close(fd); /* just using mkstemp() to reserve a name */
1129 bits = 0;
1130 type_bits_valid(type, NULL, &bits);
1131 if ((r = sshkey_generate(type, bits, &private)) != 0) {
1132 error_r(r, "sshkey_generate failed");
1133 goto failnext;
1134 }
1135 if ((r = sshkey_from_private(private, &public)) != 0)
1136 fatal_fr(r, "sshkey_from_private");
1137 snprintf(comment, sizeof comment, "%s@%s", pw->pw_name,
1138 hostname);
1139 if ((r = sshkey_save_private(private, prv_tmp, "",
1140 comment, private_key_format, openssh_format_cipher,
1141 rounds)) != 0) {
1142 error_r(r, "Saving key \"%s\" failed", prv_tmp);
1143 goto failnext;
1144 }
1145 if ((fd = mkstemp(pub_tmp)) == -1) {
1146 error("Could not save your public key in %s: %s",
1147 pub_tmp, strerror(errno));
1148 goto failnext;
1149 }
1150 (void)fchmod(fd, 0644);
1151 (void)close(fd);
1152 if ((r = sshkey_save_public(public, pub_tmp, comment)) != 0) {
1153 error_r(r, "Unable to save public key to %s",
1154 identity_file);
1155 goto failnext;
1156 }
1157
1158 /* Rename temporary files to their permanent locations. */
1159 if (rename(pub_tmp, pub_file) != 0) {
1160 error("Unable to move %s into position: %s",
1161 pub_file, strerror(errno));
1162 goto failnext;
1163 }
1164 if (rename(prv_tmp, prv_file) != 0) {
1165 error("Unable to move %s into position: %s",
1166 key_types[i].path, strerror(errno));
1167 failnext:
1168 first = 0;
1169 goto next;
1170 }
1171 next:
1172 sshkey_free(private);
1173 sshkey_free(public);
1174 free(prv_tmp);
1175 free(pub_tmp);
1176 free(prv_file);
1177 free(pub_file);
1178 }
1179 if (first != 0)
1180 printf("\n");
1181 }
1182
1183 struct known_hosts_ctx {
1184 const char *host; /* Hostname searched for in find/delete case */
1185 FILE *out; /* Output file, stdout for find_hosts case */
1186 int has_unhashed; /* When hashing, original had unhashed hosts */
1187 int found_key; /* For find/delete, host was found */
1188 int invalid; /* File contained invalid items; don't delete */
1189 int hash_hosts; /* Hash hostnames as we go */
1190 int find_host; /* Search for specific hostname */
1191 int delete_host; /* Delete host from known_hosts */
1192 };
1193
1194 static int
known_hosts_hash(struct hostkey_foreach_line * l,void * _ctx)1195 known_hosts_hash(struct hostkey_foreach_line *l, void *_ctx)
1196 {
1197 struct known_hosts_ctx *ctx = (struct known_hosts_ctx *)_ctx;
1198 char *hashed, *cp, *hosts, *ohosts;
1199 int has_wild = l->hosts && strcspn(l->hosts, "*?!") != strlen(l->hosts);
1200 int was_hashed = l->hosts && l->hosts[0] == HASH_DELIM;
1201
1202 switch (l->status) {
1203 case HKF_STATUS_OK:
1204 case HKF_STATUS_MATCHED:
1205 /*
1206 * Don't hash hosts already hashed, with wildcard
1207 * characters or a CA/revocation marker.
1208 */
1209 if (was_hashed || has_wild || l->marker != MRK_NONE) {
1210 fprintf(ctx->out, "%s\n", l->line);
1211 if (has_wild && !ctx->find_host) {
1212 logit("%s:%lu: ignoring host name "
1213 "with wildcard: %.64s", l->path,
1214 l->linenum, l->hosts);
1215 }
1216 return 0;
1217 }
1218 /*
1219 * Split any comma-separated hostnames from the host list,
1220 * hash and store separately.
1221 */
1222 ohosts = hosts = xstrdup(l->hosts);
1223 while ((cp = strsep(&hosts, ",")) != NULL && *cp != '\0') {
1224 lowercase(cp);
1225 if ((hashed = host_hash(cp, NULL, 0)) == NULL)
1226 fatal("hash_host failed");
1227 fprintf(ctx->out, "%s %s\n", hashed, l->rawkey);
1228 free(hashed);
1229 ctx->has_unhashed = 1;
1230 }
1231 free(ohosts);
1232 return 0;
1233 case HKF_STATUS_INVALID:
1234 /* Retain invalid lines, but mark file as invalid. */
1235 ctx->invalid = 1;
1236 logit("%s:%lu: invalid line", l->path, l->linenum);
1237 /* FALLTHROUGH */
1238 default:
1239 fprintf(ctx->out, "%s\n", l->line);
1240 return 0;
1241 }
1242 /* NOTREACHED */
1243 return -1;
1244 }
1245
1246 static int
known_hosts_find_delete(struct hostkey_foreach_line * l,void * _ctx)1247 known_hosts_find_delete(struct hostkey_foreach_line *l, void *_ctx)
1248 {
1249 struct known_hosts_ctx *ctx = (struct known_hosts_ctx *)_ctx;
1250 enum sshkey_fp_rep rep;
1251 int fptype;
1252 char *fp = NULL, *ra = NULL;
1253
1254 fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash;
1255 rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
1256
1257 if (l->status == HKF_STATUS_MATCHED) {
1258 if (ctx->delete_host) {
1259 if (l->marker != MRK_NONE) {
1260 /* Don't remove CA and revocation lines */
1261 fprintf(ctx->out, "%s\n", l->line);
1262 } else {
1263 /*
1264 * Hostname matches and has no CA/revoke
1265 * marker, delete it by *not* writing the
1266 * line to ctx->out.
1267 */
1268 ctx->found_key = 1;
1269 if (!quiet)
1270 printf("# Host %s found: line %lu\n",
1271 ctx->host, l->linenum);
1272 }
1273 return 0;
1274 } else if (ctx->find_host) {
1275 ctx->found_key = 1;
1276 if (!quiet) {
1277 printf("# Host %s found: line %lu %s\n",
1278 ctx->host,
1279 l->linenum, l->marker == MRK_CA ? "CA" :
1280 (l->marker == MRK_REVOKE ? "REVOKED" : ""));
1281 }
1282 if (ctx->hash_hosts)
1283 known_hosts_hash(l, ctx);
1284 else if (print_fingerprint) {
1285 fp = sshkey_fingerprint(l->key, fptype, rep);
1286 ra = sshkey_fingerprint(l->key,
1287 fingerprint_hash, SSH_FP_RANDOMART);
1288 if (fp == NULL || ra == NULL)
1289 fatal_f("sshkey_fingerprint failed");
1290 mprintf("%s %s %s%s%s\n", ctx->host,
1291 sshkey_type(l->key), fp,
1292 l->comment[0] ? " " : "",
1293 l->comment);
1294 if (log_level_get() >= SYSLOG_LEVEL_VERBOSE)
1295 printf("%s\n", ra);
1296 free(ra);
1297 free(fp);
1298 } else
1299 fprintf(ctx->out, "%s\n", l->line);
1300 return 0;
1301 }
1302 } else if (ctx->delete_host) {
1303 /* Retain non-matching hosts when deleting */
1304 if (l->status == HKF_STATUS_INVALID) {
1305 ctx->invalid = 1;
1306 logit("%s:%lu: invalid line", l->path, l->linenum);
1307 }
1308 fprintf(ctx->out, "%s\n", l->line);
1309 }
1310 return 0;
1311 }
1312
1313 static void
do_known_hosts(struct passwd * pw,const char * name,int find_host,int delete_host,int hash_hosts)1314 do_known_hosts(struct passwd *pw, const char *name, int find_host,
1315 int delete_host, int hash_hosts)
1316 {
1317 char *cp, tmp[PATH_MAX], old[PATH_MAX];
1318 int r, fd, oerrno, inplace = 0;
1319 struct known_hosts_ctx ctx;
1320 u_int foreach_options;
1321 struct stat sb;
1322
1323 if (!have_identity) {
1324 cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid);
1325 if (strlcpy(identity_file, cp, sizeof(identity_file)) >=
1326 sizeof(identity_file))
1327 fatal("Specified known hosts path too long");
1328 free(cp);
1329 have_identity = 1;
1330 }
1331 if (stat(identity_file, &sb) != 0)
1332 fatal("Cannot stat %s: %s", identity_file, strerror(errno));
1333
1334 memset(&ctx, 0, sizeof(ctx));
1335 ctx.out = stdout;
1336 ctx.host = name;
1337 ctx.hash_hosts = hash_hosts;
1338 ctx.find_host = find_host;
1339 ctx.delete_host = delete_host;
1340
1341 /*
1342 * Find hosts goes to stdout, hash and deletions happen in-place
1343 * A corner case is ssh-keygen -HF foo, which should go to stdout
1344 */
1345 if (!find_host && (hash_hosts || delete_host)) {
1346 if (strlcpy(tmp, identity_file, sizeof(tmp)) >= sizeof(tmp) ||
1347 strlcat(tmp, ".XXXXXXXXXX", sizeof(tmp)) >= sizeof(tmp) ||
1348 strlcpy(old, identity_file, sizeof(old)) >= sizeof(old) ||
1349 strlcat(old, ".old", sizeof(old)) >= sizeof(old))
1350 fatal("known_hosts path too long");
1351 umask(077);
1352 if ((fd = mkstemp(tmp)) == -1)
1353 fatal("mkstemp: %s", strerror(errno));
1354 if ((ctx.out = fdopen(fd, "w")) == NULL) {
1355 oerrno = errno;
1356 unlink(tmp);
1357 fatal("fdopen: %s", strerror(oerrno));
1358 }
1359 (void)fchmod(fd, sb.st_mode & 0644);
1360 inplace = 1;
1361 }
1362 /* XXX support identity_file == "-" for stdin */
1363 foreach_options = find_host ? HKF_WANT_MATCH : 0;
1364 foreach_options |= print_fingerprint ? HKF_WANT_PARSE_KEY : 0;
1365 if ((r = hostkeys_foreach(identity_file, (find_host || !hash_hosts) ?
1366 known_hosts_find_delete : known_hosts_hash, &ctx, name, NULL,
1367 foreach_options, 0)) != 0) {
1368 if (inplace)
1369 unlink(tmp);
1370 fatal_fr(r, "hostkeys_foreach");
1371 }
1372
1373 if (inplace)
1374 fclose(ctx.out);
1375
1376 if (ctx.invalid) {
1377 error("%s is not a valid known_hosts file.", identity_file);
1378 if (inplace) {
1379 error("Not replacing existing known_hosts "
1380 "file because of errors");
1381 unlink(tmp);
1382 }
1383 exit(1);
1384 } else if (delete_host && !ctx.found_key) {
1385 logit("Host %s not found in %s", name, identity_file);
1386 if (inplace)
1387 unlink(tmp);
1388 } else if (inplace) {
1389 /* Backup existing file */
1390 if (unlink(old) == -1 && errno != ENOENT)
1391 fatal("unlink %.100s: %s", old, strerror(errno));
1392 if (link(identity_file, old) == -1)
1393 fatal("link %.100s to %.100s: %s", identity_file, old,
1394 strerror(errno));
1395 /* Move new one into place */
1396 if (rename(tmp, identity_file) == -1) {
1397 error("rename\"%s\" to \"%s\": %s", tmp, identity_file,
1398 strerror(errno));
1399 unlink(tmp);
1400 unlink(old);
1401 exit(1);
1402 }
1403
1404 printf("%s updated.\n", identity_file);
1405 printf("Original contents retained as %s\n", old);
1406 if (ctx.has_unhashed) {
1407 logit("WARNING: %s contains unhashed entries", old);
1408 logit("Delete this file to ensure privacy "
1409 "of hostnames");
1410 }
1411 }
1412
1413 exit (find_host && !ctx.found_key);
1414 }
1415
1416 /*
1417 * Perform changing a passphrase. The argument is the passwd structure
1418 * for the current user.
1419 */
1420 static void
do_change_passphrase(struct passwd * pw)1421 do_change_passphrase(struct passwd *pw)
1422 {
1423 char *comment;
1424 char *old_passphrase, *passphrase1, *passphrase2;
1425 struct stat st;
1426 struct sshkey *private;
1427 int r;
1428
1429 if (!have_identity)
1430 ask_filename(pw, "Enter file in which the key is");
1431 if (stat(identity_file, &st) == -1)
1432 fatal("%s: %s", identity_file, strerror(errno));
1433 /* Try to load the file with empty passphrase. */
1434 r = sshkey_load_private(identity_file, "", &private, &comment);
1435 if (r == SSH_ERR_KEY_WRONG_PASSPHRASE) {
1436 if (identity_passphrase)
1437 old_passphrase = xstrdup(identity_passphrase);
1438 else
1439 old_passphrase =
1440 read_passphrase("Enter old passphrase: ",
1441 RP_ALLOW_STDIN);
1442 r = sshkey_load_private(identity_file, old_passphrase,
1443 &private, &comment);
1444 freezero(old_passphrase, strlen(old_passphrase));
1445 if (r != 0)
1446 goto badkey;
1447 } else if (r != 0) {
1448 badkey:
1449 fatal_r(r, "Failed to load key %s", identity_file);
1450 }
1451 if (comment)
1452 mprintf("Key has comment '%s'\n", comment);
1453
1454 /* Ask the new passphrase (twice). */
1455 if (identity_new_passphrase) {
1456 passphrase1 = xstrdup(identity_new_passphrase);
1457 passphrase2 = NULL;
1458 } else {
1459 passphrase1 =
1460 read_passphrase("Enter new passphrase (empty for no "
1461 "passphrase): ", RP_ALLOW_STDIN);
1462 passphrase2 = read_passphrase("Enter same passphrase again: ",
1463 RP_ALLOW_STDIN);
1464
1465 /* Verify that they are the same. */
1466 if (strcmp(passphrase1, passphrase2) != 0) {
1467 explicit_bzero(passphrase1, strlen(passphrase1));
1468 explicit_bzero(passphrase2, strlen(passphrase2));
1469 free(passphrase1);
1470 free(passphrase2);
1471 printf("Pass phrases do not match. Try again.\n");
1472 exit(1);
1473 }
1474 /* Destroy the other copy. */
1475 freezero(passphrase2, strlen(passphrase2));
1476 }
1477
1478 /* Save the file using the new passphrase. */
1479 if ((r = sshkey_save_private(private, identity_file, passphrase1,
1480 comment, private_key_format, openssh_format_cipher, rounds)) != 0) {
1481 error_r(r, "Saving key \"%s\" failed", identity_file);
1482 freezero(passphrase1, strlen(passphrase1));
1483 sshkey_free(private);
1484 free(comment);
1485 exit(1);
1486 }
1487 /* Destroy the passphrase and the copy of the key in memory. */
1488 freezero(passphrase1, strlen(passphrase1));
1489 sshkey_free(private); /* Destroys contents */
1490 free(comment);
1491
1492 printf("Your identification has been saved with the new passphrase.\n");
1493 exit(0);
1494 }
1495
1496 /*
1497 * Print the SSHFP RR.
1498 */
1499 static int
do_print_resource_record(struct passwd * pw,char * fname,char * hname,int print_generic,char * const * opts,size_t nopts)1500 do_print_resource_record(struct passwd *pw, char *fname, char *hname,
1501 int print_generic, char * const *opts, size_t nopts)
1502 {
1503 struct sshkey *public;
1504 char *comment = NULL;
1505 struct stat st;
1506 int r, hash = -1;
1507 size_t i;
1508
1509 for (i = 0; i < nopts; i++) {
1510 if (strncasecmp(opts[i], "hashalg=", 8) == 0) {
1511 if ((hash = ssh_digest_alg_by_name(opts[i] + 8)) == -1)
1512 fatal("Unsupported hash algorithm");
1513 } else {
1514 error("Invalid option \"%s\"", opts[i]);
1515 return SSH_ERR_INVALID_ARGUMENT;
1516 }
1517 }
1518 if (fname == NULL)
1519 fatal_f("no filename");
1520 if (stat(fname, &st) == -1) {
1521 if (errno == ENOENT)
1522 return 0;
1523 fatal("%s: %s", fname, strerror(errno));
1524 }
1525 if ((r = sshkey_load_public(fname, &public, &comment)) != 0)
1526 fatal_r(r, "Failed to read v2 public key from \"%s\"", fname);
1527 export_dns_rr(hname, public, stdout, print_generic, hash);
1528 sshkey_free(public);
1529 free(comment);
1530 return 1;
1531 }
1532
1533 /*
1534 * Change the comment of a private key file.
1535 */
1536 static void
do_change_comment(struct passwd * pw,const char * identity_comment)1537 do_change_comment(struct passwd *pw, const char *identity_comment)
1538 {
1539 char new_comment[1024], *comment, *passphrase;
1540 struct sshkey *private;
1541 struct sshkey *public;
1542 struct stat st;
1543 int r;
1544
1545 if (!have_identity)
1546 ask_filename(pw, "Enter file in which the key is");
1547 if (stat(identity_file, &st) == -1)
1548 fatal("%s: %s", identity_file, strerror(errno));
1549 if ((r = sshkey_load_private(identity_file, "",
1550 &private, &comment)) == 0)
1551 passphrase = xstrdup("");
1552 else if (r != SSH_ERR_KEY_WRONG_PASSPHRASE)
1553 fatal_r(r, "Cannot load private key \"%s\"", identity_file);
1554 else {
1555 if (identity_passphrase)
1556 passphrase = xstrdup(identity_passphrase);
1557 else if (identity_new_passphrase)
1558 passphrase = xstrdup(identity_new_passphrase);
1559 else
1560 passphrase = read_passphrase("Enter passphrase: ",
1561 RP_ALLOW_STDIN);
1562 /* Try to load using the passphrase. */
1563 if ((r = sshkey_load_private(identity_file, passphrase,
1564 &private, &comment)) != 0) {
1565 freezero(passphrase, strlen(passphrase));
1566 fatal_r(r, "Cannot load private key \"%s\"",
1567 identity_file);
1568 }
1569 }
1570
1571 if (private->type != KEY_ED25519 && private->type != KEY_XMSS &&
1572 private_key_format != SSHKEY_PRIVATE_OPENSSH) {
1573 error("Comments are only supported for keys stored in "
1574 "the new format (-o).");
1575 explicit_bzero(passphrase, strlen(passphrase));
1576 sshkey_free(private);
1577 exit(1);
1578 }
1579 if (comment)
1580 printf("Old comment: %s\n", comment);
1581 else
1582 printf("No existing comment\n");
1583
1584 if (identity_comment) {
1585 strlcpy(new_comment, identity_comment, sizeof(new_comment));
1586 } else {
1587 printf("New comment: ");
1588 fflush(stdout);
1589 if (!fgets(new_comment, sizeof(new_comment), stdin)) {
1590 explicit_bzero(passphrase, strlen(passphrase));
1591 sshkey_free(private);
1592 exit(1);
1593 }
1594 new_comment[strcspn(new_comment, "\n")] = '\0';
1595 }
1596 if (comment != NULL && strcmp(comment, new_comment) == 0) {
1597 printf("No change to comment\n");
1598 free(passphrase);
1599 sshkey_free(private);
1600 free(comment);
1601 exit(0);
1602 }
1603
1604 /* Save the file using the new passphrase. */
1605 if ((r = sshkey_save_private(private, identity_file, passphrase,
1606 new_comment, private_key_format, openssh_format_cipher,
1607 rounds)) != 0) {
1608 error_r(r, "Saving key \"%s\" failed", identity_file);
1609 freezero(passphrase, strlen(passphrase));
1610 sshkey_free(private);
1611 free(comment);
1612 exit(1);
1613 }
1614 freezero(passphrase, strlen(passphrase));
1615 if ((r = sshkey_from_private(private, &public)) != 0)
1616 fatal_fr(r, "sshkey_from_private");
1617 sshkey_free(private);
1618
1619 strlcat(identity_file, ".pub", sizeof(identity_file));
1620 if ((r = sshkey_save_public(public, identity_file, new_comment)) != 0)
1621 fatal_r(r, "Unable to save public key to %s", identity_file);
1622 sshkey_free(public);
1623 free(comment);
1624
1625 if (strlen(new_comment) > 0)
1626 printf("Comment '%s' applied\n", new_comment);
1627 else
1628 printf("Comment removed\n");
1629
1630 exit(0);
1631 }
1632
1633 static void
cert_ext_add(const char * key,const char * value,int iscrit)1634 cert_ext_add(const char *key, const char *value, int iscrit)
1635 {
1636 cert_ext = xreallocarray(cert_ext, ncert_ext + 1, sizeof(*cert_ext));
1637 cert_ext[ncert_ext].key = xstrdup(key);
1638 cert_ext[ncert_ext].val = value == NULL ? NULL : xstrdup(value);
1639 cert_ext[ncert_ext].crit = iscrit;
1640 ncert_ext++;
1641 }
1642
1643 /* qsort(3) comparison function for certificate extensions */
1644 static int
cert_ext_cmp(const void * _a,const void * _b)1645 cert_ext_cmp(const void *_a, const void *_b)
1646 {
1647 const struct cert_ext *a = (const struct cert_ext *)_a;
1648 const struct cert_ext *b = (const struct cert_ext *)_b;
1649 int r;
1650
1651 if (a->crit != b->crit)
1652 return (a->crit < b->crit) ? -1 : 1;
1653 if ((r = strcmp(a->key, b->key)) != 0)
1654 return r;
1655 if ((a->val == NULL) != (b->val == NULL))
1656 return (a->val == NULL) ? -1 : 1;
1657 if (a->val != NULL && (r = strcmp(a->val, b->val)) != 0)
1658 return r;
1659 return 0;
1660 }
1661
1662 #define OPTIONS_CRITICAL 1
1663 #define OPTIONS_EXTENSIONS 2
1664 static void
prepare_options_buf(struct sshbuf * c,int which)1665 prepare_options_buf(struct sshbuf *c, int which)
1666 {
1667 struct sshbuf *b;
1668 size_t i;
1669 int r;
1670 const struct cert_ext *ext;
1671
1672 if ((b = sshbuf_new()) == NULL)
1673 fatal_f("sshbuf_new failed");
1674 sshbuf_reset(c);
1675 for (i = 0; i < ncert_ext; i++) {
1676 ext = &cert_ext[i];
1677 if ((ext->crit && (which & OPTIONS_EXTENSIONS)) ||
1678 (!ext->crit && (which & OPTIONS_CRITICAL)))
1679 continue;
1680 if (ext->val == NULL) {
1681 /* flag option */
1682 debug3_f("%s", ext->key);
1683 if ((r = sshbuf_put_cstring(c, ext->key)) != 0 ||
1684 (r = sshbuf_put_string(c, NULL, 0)) != 0)
1685 fatal_fr(r, "prepare flag");
1686 } else {
1687 /* key/value option */
1688 debug3_f("%s=%s", ext->key, ext->val);
1689 sshbuf_reset(b);
1690 if ((r = sshbuf_put_cstring(c, ext->key)) != 0 ||
1691 (r = sshbuf_put_cstring(b, ext->val)) != 0 ||
1692 (r = sshbuf_put_stringb(c, b)) != 0)
1693 fatal_fr(r, "prepare k/v");
1694 }
1695 }
1696 sshbuf_free(b);
1697 }
1698
1699 static void
finalise_cert_exts(void)1700 finalise_cert_exts(void)
1701 {
1702 /* critical options */
1703 if (certflags_command != NULL)
1704 cert_ext_add("force-command", certflags_command, 1);
1705 if (certflags_src_addr != NULL)
1706 cert_ext_add("source-address", certflags_src_addr, 1);
1707 if ((certflags_flags & CERTOPT_REQUIRE_VERIFY) != 0)
1708 cert_ext_add("verify-required", NULL, 1);
1709 /* extensions */
1710 if ((certflags_flags & CERTOPT_X_FWD) != 0)
1711 cert_ext_add("permit-X11-forwarding", NULL, 0);
1712 if ((certflags_flags & CERTOPT_AGENT_FWD) != 0)
1713 cert_ext_add("permit-agent-forwarding", NULL, 0);
1714 if ((certflags_flags & CERTOPT_PORT_FWD) != 0)
1715 cert_ext_add("permit-port-forwarding", NULL, 0);
1716 if ((certflags_flags & CERTOPT_PTY) != 0)
1717 cert_ext_add("permit-pty", NULL, 0);
1718 if ((certflags_flags & CERTOPT_USER_RC) != 0)
1719 cert_ext_add("permit-user-rc", NULL, 0);
1720 if ((certflags_flags & CERTOPT_NO_REQUIRE_USER_PRESENCE) != 0)
1721 cert_ext_add("no-touch-required", NULL, 0);
1722 /* order lexically by key */
1723 if (ncert_ext > 0)
1724 qsort(cert_ext, ncert_ext, sizeof(*cert_ext), cert_ext_cmp);
1725 }
1726
1727 static struct sshkey *
load_pkcs11_key(char * path)1728 load_pkcs11_key(char *path)
1729 {
1730 #ifdef ENABLE_PKCS11
1731 struct sshkey **keys = NULL, *public, *private = NULL;
1732 int r, i, nkeys;
1733
1734 if ((r = sshkey_load_public(path, &public, NULL)) != 0)
1735 fatal_r(r, "Couldn't load CA public key \"%s\"", path);
1736
1737 nkeys = pkcs11_add_provider(pkcs11provider, identity_passphrase,
1738 &keys, NULL);
1739 debug3_f("%d keys", nkeys);
1740 if (nkeys <= 0)
1741 fatal("cannot read public key from pkcs11");
1742 for (i = 0; i < nkeys; i++) {
1743 if (sshkey_equal_public(public, keys[i])) {
1744 private = keys[i];
1745 continue;
1746 }
1747 sshkey_free(keys[i]);
1748 }
1749 free(keys);
1750 sshkey_free(public);
1751 return private;
1752 #else
1753 fatal("no pkcs11 support");
1754 #endif /* ENABLE_PKCS11 */
1755 }
1756
1757 /* Signer for sshkey_certify_custom that uses the agent */
1758 static int
agent_signer(struct sshkey * key,u_char ** sigp,size_t * lenp,const u_char * data,size_t datalen,const char * alg,const char * provider,const char * pin,u_int compat,void * ctx)1759 agent_signer(struct sshkey *key, u_char **sigp, size_t *lenp,
1760 const u_char *data, size_t datalen,
1761 const char *alg, const char *provider, const char *pin,
1762 u_int compat, void *ctx)
1763 {
1764 int *agent_fdp = (int *)ctx;
1765
1766 return ssh_agent_sign(*agent_fdp, key, sigp, lenp,
1767 data, datalen, alg, compat);
1768 }
1769
1770 static void
do_ca_sign(struct passwd * pw,const char * ca_key_path,int prefer_agent,unsigned long long cert_serial,int cert_serial_autoinc,int argc,char ** argv)1771 do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent,
1772 unsigned long long cert_serial, int cert_serial_autoinc,
1773 int argc, char **argv)
1774 {
1775 int r, i, found, agent_fd = -1;
1776 u_int n;
1777 struct sshkey *ca, *public;
1778 char valid[64], *otmp, *tmp, *cp, *out, *comment;
1779 char *ca_fp = NULL, **plist = NULL, *pin = NULL;
1780 struct ssh_identitylist *agent_ids;
1781 size_t j;
1782 struct notifier_ctx *notifier = NULL;
1783
1784 #ifdef ENABLE_PKCS11
1785 pkcs11_init(1);
1786 #endif
1787 tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
1788 if (pkcs11provider != NULL) {
1789 /* If a PKCS#11 token was specified then try to use it */
1790 if ((ca = load_pkcs11_key(tmp)) == NULL)
1791 fatal("No PKCS#11 key matching %s found", ca_key_path);
1792 } else if (prefer_agent) {
1793 /*
1794 * Agent signature requested. Try to use agent after making
1795 * sure the public key specified is actually present in the
1796 * agent.
1797 */
1798 if ((r = sshkey_load_public(tmp, &ca, NULL)) != 0)
1799 fatal_r(r, "Cannot load CA public key %s", tmp);
1800 if ((r = ssh_get_authentication_socket(&agent_fd)) != 0)
1801 fatal_r(r, "Cannot use public key for CA signature");
1802 if ((r = ssh_fetch_identitylist(agent_fd, &agent_ids)) != 0)
1803 fatal_r(r, "Retrieve agent key list");
1804 found = 0;
1805 for (j = 0; j < agent_ids->nkeys; j++) {
1806 if (sshkey_equal(ca, agent_ids->keys[j])) {
1807 found = 1;
1808 break;
1809 }
1810 }
1811 if (!found)
1812 fatal("CA key %s not found in agent", tmp);
1813 ssh_free_identitylist(agent_ids);
1814 ca->flags |= SSHKEY_FLAG_EXT;
1815 } else {
1816 /* CA key is assumed to be a private key on the filesystem */
1817 ca = load_identity(tmp, NULL);
1818 if (sshkey_is_sk(ca) &&
1819 (ca->sk_flags & SSH_SK_USER_VERIFICATION_REQD)) {
1820 if ((pin = read_passphrase("Enter PIN for CA key: ",
1821 RP_ALLOW_STDIN)) == NULL)
1822 fatal_f("couldn't read PIN");
1823 }
1824 }
1825 free(tmp);
1826
1827 if (key_type_name != NULL) {
1828 if (sshkey_type_from_name(key_type_name) != ca->type) {
1829 fatal("CA key type %s doesn't match specified %s",
1830 sshkey_ssh_name(ca), key_type_name);
1831 }
1832 } else if (ca->type == KEY_RSA) {
1833 /* Default to a good signature algorithm */
1834 key_type_name = "rsa-sha2-512";
1835 }
1836 ca_fp = sshkey_fingerprint(ca, fingerprint_hash, SSH_FP_DEFAULT);
1837
1838 finalise_cert_exts();
1839 for (i = 0; i < argc; i++) {
1840 /* Split list of principals */
1841 n = 0;
1842 if (cert_principals != NULL) {
1843 otmp = tmp = xstrdup(cert_principals);
1844 plist = NULL;
1845 for (; (cp = strsep(&tmp, ",")) != NULL; n++) {
1846 plist = xreallocarray(plist, n + 1, sizeof(*plist));
1847 if (*(plist[n] = xstrdup(cp)) == '\0')
1848 fatal("Empty principal name");
1849 }
1850 free(otmp);
1851 }
1852 if (n > SSHKEY_CERT_MAX_PRINCIPALS)
1853 fatal("Too many certificate principals specified");
1854
1855 tmp = tilde_expand_filename(argv[i], pw->pw_uid);
1856 if ((r = sshkey_load_public(tmp, &public, &comment)) != 0)
1857 fatal_r(r, "load pubkey \"%s\"", tmp);
1858 if (sshkey_is_cert(public))
1859 fatal_f("key \"%s\" type %s cannot be certified",
1860 tmp, sshkey_type(public));
1861
1862 /* Prepare certificate to sign */
1863 if ((r = sshkey_to_certified(public)) != 0)
1864 fatal_r(r, "Could not upgrade key %s to certificate", tmp);
1865 public->cert->type = cert_key_type;
1866 public->cert->serial = (u_int64_t)cert_serial;
1867 public->cert->key_id = xstrdup(cert_key_id);
1868 public->cert->nprincipals = n;
1869 public->cert->principals = plist;
1870 public->cert->valid_after = cert_valid_from;
1871 public->cert->valid_before = cert_valid_to;
1872 prepare_options_buf(public->cert->critical, OPTIONS_CRITICAL);
1873 prepare_options_buf(public->cert->extensions,
1874 OPTIONS_EXTENSIONS);
1875 if ((r = sshkey_from_private(ca,
1876 &public->cert->signature_key)) != 0)
1877 fatal_r(r, "sshkey_from_private (ca key)");
1878
1879 if (agent_fd != -1 && (ca->flags & SSHKEY_FLAG_EXT) != 0) {
1880 if ((r = sshkey_certify_custom(public, ca,
1881 key_type_name, sk_provider, NULL, agent_signer,
1882 &agent_fd)) != 0)
1883 fatal_r(r, "Couldn't certify %s via agent", tmp);
1884 } else {
1885 if (sshkey_is_sk(ca) &&
1886 (ca->sk_flags & SSH_SK_USER_PRESENCE_REQD)) {
1887 notifier = notify_start(0,
1888 "Confirm user presence for key %s %s",
1889 sshkey_type(ca), ca_fp);
1890 }
1891 r = sshkey_certify(public, ca, key_type_name,
1892 sk_provider, pin);
1893 notify_complete(notifier, "User presence confirmed");
1894 if (r != 0)
1895 fatal_r(r, "Couldn't certify key %s", tmp);
1896 }
1897
1898 if ((cp = strrchr(tmp, '.')) != NULL && strcmp(cp, ".pub") == 0)
1899 *cp = '\0';
1900 xasprintf(&out, "%s-cert.pub", tmp);
1901 free(tmp);
1902
1903 if ((r = sshkey_save_public(public, out, comment)) != 0) {
1904 fatal_r(r, "Unable to save public key to %s",
1905 identity_file);
1906 }
1907
1908 if (!quiet) {
1909 sshkey_format_cert_validity(public->cert,
1910 valid, sizeof(valid));
1911 logit("Signed %s key %s: id \"%s\" serial %llu%s%s "
1912 "valid %s", sshkey_cert_type(public),
1913 out, public->cert->key_id,
1914 (unsigned long long)public->cert->serial,
1915 cert_principals != NULL ? " for " : "",
1916 cert_principals != NULL ? cert_principals : "",
1917 valid);
1918 }
1919
1920 sshkey_free(public);
1921 free(out);
1922 if (cert_serial_autoinc)
1923 cert_serial++;
1924 }
1925 if (pin != NULL)
1926 freezero(pin, strlen(pin));
1927 free(ca_fp);
1928 #ifdef ENABLE_PKCS11
1929 pkcs11_terminate();
1930 #endif
1931 exit(0);
1932 }
1933
1934 static u_int64_t
parse_relative_time(const char * s,time_t now)1935 parse_relative_time(const char *s, time_t now)
1936 {
1937 int64_t mul, secs;
1938
1939 mul = *s == '-' ? -1 : 1;
1940
1941 if ((secs = convtime(s + 1)) == -1)
1942 fatal("Invalid relative certificate time %s", s);
1943 if (mul == -1 && secs > now)
1944 fatal("Certificate time %s cannot be represented", s);
1945 return now + (u_int64_t)(secs * mul);
1946 }
1947
1948 static void
parse_hex_u64(const char * s,uint64_t * up)1949 parse_hex_u64(const char *s, uint64_t *up)
1950 {
1951 char *ep;
1952 unsigned long long ull;
1953
1954 errno = 0;
1955 ull = strtoull(s, &ep, 16);
1956 if (*s == '\0' || *ep != '\0')
1957 fatal("Invalid certificate time: not a number");
1958 if (errno == ERANGE && ull == ULONG_MAX)
1959 fatal_fr(SSH_ERR_SYSTEM_ERROR, "Invalid certificate time");
1960 *up = (uint64_t)ull;
1961 }
1962
1963 static void
parse_cert_times(char * timespec)1964 parse_cert_times(char *timespec)
1965 {
1966 char *from, *to;
1967 time_t now = time(NULL);
1968 int64_t secs;
1969
1970 /* +timespec relative to now */
1971 if (*timespec == '+' && strchr(timespec, ':') == NULL) {
1972 if ((secs = convtime(timespec + 1)) == -1)
1973 fatal("Invalid relative certificate life %s", timespec);
1974 cert_valid_to = now + secs;
1975 /*
1976 * Backdate certificate one minute to avoid problems on hosts
1977 * with poorly-synchronised clocks.
1978 */
1979 cert_valid_from = ((now - 59)/ 60) * 60;
1980 return;
1981 }
1982
1983 /*
1984 * from:to, where
1985 * from := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | 0x... | "always"
1986 * to := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | 0x... | "forever"
1987 */
1988 from = xstrdup(timespec);
1989 to = strchr(from, ':');
1990 if (to == NULL || from == to || *(to + 1) == '\0')
1991 fatal("Invalid certificate life specification %s", timespec);
1992 *to++ = '\0';
1993
1994 if (*from == '-' || *from == '+')
1995 cert_valid_from = parse_relative_time(from, now);
1996 else if (strcmp(from, "always") == 0)
1997 cert_valid_from = 0;
1998 else if (strncmp(from, "0x", 2) == 0)
1999 parse_hex_u64(from, &cert_valid_from);
2000 else if (parse_absolute_time(from, &cert_valid_from) != 0)
2001 fatal("Invalid from time \"%s\"", from);
2002
2003 if (*to == '-' || *to == '+')
2004 cert_valid_to = parse_relative_time(to, now);
2005 else if (strcmp(to, "forever") == 0)
2006 cert_valid_to = ~(u_int64_t)0;
2007 else if (strncmp(to, "0x", 2) == 0)
2008 parse_hex_u64(to, &cert_valid_to);
2009 else if (parse_absolute_time(to, &cert_valid_to) != 0)
2010 fatal("Invalid to time \"%s\"", to);
2011
2012 if (cert_valid_to <= cert_valid_from)
2013 fatal("Empty certificate validity interval");
2014 free(from);
2015 }
2016
2017 static void
add_cert_option(char * opt)2018 add_cert_option(char *opt)
2019 {
2020 char *val, *cp;
2021 int iscrit = 0;
2022
2023 if (strcasecmp(opt, "clear") == 0)
2024 certflags_flags = 0;
2025 else if (strcasecmp(opt, "no-x11-forwarding") == 0)
2026 certflags_flags &= ~CERTOPT_X_FWD;
2027 else if (strcasecmp(opt, "permit-x11-forwarding") == 0)
2028 certflags_flags |= CERTOPT_X_FWD;
2029 else if (strcasecmp(opt, "no-agent-forwarding") == 0)
2030 certflags_flags &= ~CERTOPT_AGENT_FWD;
2031 else if (strcasecmp(opt, "permit-agent-forwarding") == 0)
2032 certflags_flags |= CERTOPT_AGENT_FWD;
2033 else if (strcasecmp(opt, "no-port-forwarding") == 0)
2034 certflags_flags &= ~CERTOPT_PORT_FWD;
2035 else if (strcasecmp(opt, "permit-port-forwarding") == 0)
2036 certflags_flags |= CERTOPT_PORT_FWD;
2037 else if (strcasecmp(opt, "no-pty") == 0)
2038 certflags_flags &= ~CERTOPT_PTY;
2039 else if (strcasecmp(opt, "permit-pty") == 0)
2040 certflags_flags |= CERTOPT_PTY;
2041 else if (strcasecmp(opt, "no-user-rc") == 0)
2042 certflags_flags &= ~CERTOPT_USER_RC;
2043 else if (strcasecmp(opt, "permit-user-rc") == 0)
2044 certflags_flags |= CERTOPT_USER_RC;
2045 else if (strcasecmp(opt, "touch-required") == 0)
2046 certflags_flags &= ~CERTOPT_NO_REQUIRE_USER_PRESENCE;
2047 else if (strcasecmp(opt, "no-touch-required") == 0)
2048 certflags_flags |= CERTOPT_NO_REQUIRE_USER_PRESENCE;
2049 else if (strcasecmp(opt, "no-verify-required") == 0)
2050 certflags_flags &= ~CERTOPT_REQUIRE_VERIFY;
2051 else if (strcasecmp(opt, "verify-required") == 0)
2052 certflags_flags |= CERTOPT_REQUIRE_VERIFY;
2053 else if (strncasecmp(opt, "force-command=", 14) == 0) {
2054 val = opt + 14;
2055 if (*val == '\0')
2056 fatal("Empty force-command option");
2057 if (certflags_command != NULL)
2058 fatal("force-command already specified");
2059 certflags_command = xstrdup(val);
2060 } else if (strncasecmp(opt, "source-address=", 15) == 0) {
2061 val = opt + 15;
2062 if (*val == '\0')
2063 fatal("Empty source-address option");
2064 if (certflags_src_addr != NULL)
2065 fatal("source-address already specified");
2066 if (addr_match_cidr_list(NULL, val) != 0)
2067 fatal("Invalid source-address list");
2068 certflags_src_addr = xstrdup(val);
2069 } else if (strncasecmp(opt, "extension:", 10) == 0 ||
2070 (iscrit = (strncasecmp(opt, "critical:", 9) == 0))) {
2071 val = xstrdup(strchr(opt, ':') + 1);
2072 if ((cp = strchr(val, '=')) != NULL)
2073 *cp++ = '\0';
2074 cert_ext_add(val, cp, iscrit);
2075 free(val);
2076 } else
2077 fatal("Unsupported certificate option \"%s\"", opt);
2078 }
2079
2080 static void
show_options(struct sshbuf * optbuf,int in_critical)2081 show_options(struct sshbuf *optbuf, int in_critical)
2082 {
2083 char *name, *arg, *hex;
2084 struct sshbuf *options, *option = NULL;
2085 int r;
2086
2087 if ((options = sshbuf_fromb(optbuf)) == NULL)
2088 fatal_f("sshbuf_fromb failed");
2089 while (sshbuf_len(options) != 0) {
2090 sshbuf_free(option);
2091 option = NULL;
2092 if ((r = sshbuf_get_cstring(options, &name, NULL)) != 0 ||
2093 (r = sshbuf_froms(options, &option)) != 0)
2094 fatal_fr(r, "parse option");
2095 printf(" %s", name);
2096 if (!in_critical &&
2097 (strcmp(name, "permit-X11-forwarding") == 0 ||
2098 strcmp(name, "permit-agent-forwarding") == 0 ||
2099 strcmp(name, "permit-port-forwarding") == 0 ||
2100 strcmp(name, "permit-pty") == 0 ||
2101 strcmp(name, "permit-user-rc") == 0 ||
2102 strcmp(name, "no-touch-required") == 0)) {
2103 printf("\n");
2104 } else if (in_critical &&
2105 (strcmp(name, "force-command") == 0 ||
2106 strcmp(name, "source-address") == 0)) {
2107 if ((r = sshbuf_get_cstring(option, &arg, NULL)) != 0)
2108 fatal_fr(r, "parse critical");
2109 printf(" %s\n", arg);
2110 free(arg);
2111 } else if (in_critical &&
2112 strcmp(name, "verify-required") == 0) {
2113 printf("\n");
2114 } else if (sshbuf_len(option) > 0) {
2115 hex = sshbuf_dtob16(option);
2116 printf(" UNKNOWN OPTION: %s (len %zu)\n",
2117 hex, sshbuf_len(option));
2118 sshbuf_reset(option);
2119 free(hex);
2120 } else
2121 printf(" UNKNOWN FLAG OPTION\n");
2122 free(name);
2123 if (sshbuf_len(option) != 0)
2124 fatal("Option corrupt: extra data at end");
2125 }
2126 sshbuf_free(option);
2127 sshbuf_free(options);
2128 }
2129
2130 static void
print_cert(struct sshkey * key)2131 print_cert(struct sshkey *key)
2132 {
2133 char valid[64], *key_fp, *ca_fp;
2134 u_int i;
2135
2136 key_fp = sshkey_fingerprint(key, fingerprint_hash, SSH_FP_DEFAULT);
2137 ca_fp = sshkey_fingerprint(key->cert->signature_key,
2138 fingerprint_hash, SSH_FP_DEFAULT);
2139 if (key_fp == NULL || ca_fp == NULL)
2140 fatal_f("sshkey_fingerprint fail");
2141 sshkey_format_cert_validity(key->cert, valid, sizeof(valid));
2142
2143 printf(" Type: %s %s certificate\n", sshkey_ssh_name(key),
2144 sshkey_cert_type(key));
2145 printf(" Public key: %s %s\n", sshkey_type(key), key_fp);
2146 printf(" Signing CA: %s %s (using %s)\n",
2147 sshkey_type(key->cert->signature_key), ca_fp,
2148 key->cert->signature_type);
2149 printf(" Key ID: \"%s\"\n", key->cert->key_id);
2150 printf(" Serial: %llu\n", (unsigned long long)key->cert->serial);
2151 printf(" Valid: %s\n", valid);
2152 printf(" Principals: ");
2153 if (key->cert->nprincipals == 0)
2154 printf("(none)\n");
2155 else {
2156 for (i = 0; i < key->cert->nprincipals; i++)
2157 printf("\n %s",
2158 key->cert->principals[i]);
2159 printf("\n");
2160 }
2161 printf(" Critical Options: ");
2162 if (sshbuf_len(key->cert->critical) == 0)
2163 printf("(none)\n");
2164 else {
2165 printf("\n");
2166 show_options(key->cert->critical, 1);
2167 }
2168 printf(" Extensions: ");
2169 if (sshbuf_len(key->cert->extensions) == 0)
2170 printf("(none)\n");
2171 else {
2172 printf("\n");
2173 show_options(key->cert->extensions, 0);
2174 }
2175 }
2176
2177 static void
do_show_cert(struct passwd * pw)2178 do_show_cert(struct passwd *pw)
2179 {
2180 struct sshkey *key = NULL;
2181 struct stat st;
2182 int r, is_stdin = 0, ok = 0;
2183 FILE *f;
2184 char *cp, *line = NULL;
2185 const char *path;
2186 size_t linesize = 0;
2187 u_long lnum = 0;
2188
2189 if (!have_identity)
2190 ask_filename(pw, "Enter file in which the key is");
2191 if (strcmp(identity_file, "-") != 0 && stat(identity_file, &st) == -1)
2192 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
2193
2194 path = identity_file;
2195 if (strcmp(path, "-") == 0) {
2196 f = stdin;
2197 path = "(stdin)";
2198 is_stdin = 1;
2199 } else if ((f = fopen(identity_file, "r")) == NULL)
2200 fatal("fopen %s: %s", identity_file, strerror(errno));
2201
2202 while (getline(&line, &linesize, f) != -1) {
2203 lnum++;
2204 sshkey_free(key);
2205 key = NULL;
2206 /* Trim leading space and comments */
2207 cp = line + strspn(line, " \t");
2208 if (*cp == '#' || *cp == '\0')
2209 continue;
2210 if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
2211 fatal("sshkey_new");
2212 if ((r = sshkey_read(key, &cp)) != 0) {
2213 error_r(r, "%s:%lu: invalid key", path, lnum);
2214 continue;
2215 }
2216 if (!sshkey_is_cert(key)) {
2217 error("%s:%lu is not a certificate", path, lnum);
2218 continue;
2219 }
2220 ok = 1;
2221 if (!is_stdin && lnum == 1)
2222 printf("%s:\n", path);
2223 else
2224 printf("%s:%lu:\n", path, lnum);
2225 print_cert(key);
2226 }
2227 free(line);
2228 sshkey_free(key);
2229 fclose(f);
2230 exit(ok ? 0 : 1);
2231 }
2232
2233 static void
load_krl(const char * path,struct ssh_krl ** krlp)2234 load_krl(const char *path, struct ssh_krl **krlp)
2235 {
2236 struct sshbuf *krlbuf;
2237 int r;
2238
2239 if ((r = sshbuf_load_file(path, &krlbuf)) != 0)
2240 fatal_r(r, "Unable to load KRL %s", path);
2241 /* XXX check sigs */
2242 if ((r = ssh_krl_from_blob(krlbuf, krlp)) != 0 ||
2243 *krlp == NULL)
2244 fatal_r(r, "Invalid KRL file %s", path);
2245 sshbuf_free(krlbuf);
2246 }
2247
2248 static void
hash_to_blob(const char * cp,u_char ** blobp,size_t * lenp,const char * file,u_long lnum)2249 hash_to_blob(const char *cp, u_char **blobp, size_t *lenp,
2250 const char *file, u_long lnum)
2251 {
2252 char *tmp;
2253 size_t tlen;
2254 struct sshbuf *b;
2255 int r;
2256
2257 if (strncmp(cp, "SHA256:", 7) != 0)
2258 fatal("%s:%lu: unsupported hash algorithm", file, lnum);
2259 cp += 7;
2260
2261 /*
2262 * OpenSSH base64 hashes omit trailing '='
2263 * characters; put them back for decode.
2264 */
2265 if ((tlen = strlen(cp)) >= SIZE_MAX - 5)
2266 fatal_f("hash too long: %zu bytes", tlen);
2267 tmp = xmalloc(tlen + 4 + 1);
2268 strlcpy(tmp, cp, tlen + 1);
2269 while ((tlen % 4) != 0) {
2270 tmp[tlen++] = '=';
2271 tmp[tlen] = '\0';
2272 }
2273 if ((b = sshbuf_new()) == NULL)
2274 fatal_f("sshbuf_new failed");
2275 if ((r = sshbuf_b64tod(b, tmp)) != 0)
2276 fatal_r(r, "%s:%lu: decode hash failed", file, lnum);
2277 free(tmp);
2278 *lenp = sshbuf_len(b);
2279 *blobp = xmalloc(*lenp);
2280 memcpy(*blobp, sshbuf_ptr(b), *lenp);
2281 sshbuf_free(b);
2282 }
2283
2284 static void
update_krl_from_file(struct passwd * pw,const char * file,int wild_ca,const struct sshkey * ca,struct ssh_krl * krl)2285 update_krl_from_file(struct passwd *pw, const char *file, int wild_ca,
2286 const struct sshkey *ca, struct ssh_krl *krl)
2287 {
2288 struct sshkey *key = NULL;
2289 u_long lnum = 0;
2290 char *path, *cp, *ep, *line = NULL;
2291 u_char *blob = NULL;
2292 size_t blen = 0, linesize = 0;
2293 unsigned long long serial, serial2;
2294 int i, was_explicit_key, was_sha1, was_sha256, was_hash, r;
2295 FILE *krl_spec;
2296
2297 path = tilde_expand_filename(file, pw->pw_uid);
2298 if (strcmp(path, "-") == 0) {
2299 krl_spec = stdin;
2300 free(path);
2301 path = xstrdup("(standard input)");
2302 } else if ((krl_spec = fopen(path, "r")) == NULL)
2303 fatal("fopen %s: %s", path, strerror(errno));
2304
2305 if (!quiet)
2306 printf("Revoking from %s\n", path);
2307 while (getline(&line, &linesize, krl_spec) != -1) {
2308 if (linesize >= INT_MAX) {
2309 fatal_f("%s contains unparsable line, len=%zu",
2310 path, linesize);
2311 }
2312 lnum++;
2313 was_explicit_key = was_sha1 = was_sha256 = was_hash = 0;
2314 cp = line + strspn(line, " \t");
2315 /* Trim trailing space, comments and strip \n */
2316 for (i = 0, r = -1; cp[i] != '\0'; i++) {
2317 if (cp[i] == '#' || cp[i] == '\n') {
2318 cp[i] = '\0';
2319 break;
2320 }
2321 if (cp[i] == ' ' || cp[i] == '\t') {
2322 /* Remember the start of a span of whitespace */
2323 if (r == -1)
2324 r = i;
2325 } else
2326 r = -1;
2327 }
2328 if (r != -1)
2329 cp[r] = '\0';
2330 if (*cp == '\0')
2331 continue;
2332 if (strncasecmp(cp, "serial:", 7) == 0) {
2333 if (ca == NULL && !wild_ca) {
2334 fatal("revoking certificates by serial number "
2335 "requires specification of a CA key");
2336 }
2337 cp += 7;
2338 cp = cp + strspn(cp, " \t");
2339 errno = 0;
2340 serial = strtoull(cp, &ep, 0);
2341 if (*cp == '\0' || (*ep != '\0' && *ep != '-'))
2342 fatal("%s:%lu: invalid serial \"%s\"",
2343 path, lnum, cp);
2344 if (errno == ERANGE && serial == ULLONG_MAX)
2345 fatal("%s:%lu: serial out of range",
2346 path, lnum);
2347 serial2 = serial;
2348 if (*ep == '-') {
2349 cp = ep + 1;
2350 errno = 0;
2351 serial2 = strtoull(cp, &ep, 0);
2352 if (*cp == '\0' || *ep != '\0')
2353 fatal("%s:%lu: invalid serial \"%s\"",
2354 path, lnum, cp);
2355 if (errno == ERANGE && serial2 == ULLONG_MAX)
2356 fatal("%s:%lu: serial out of range",
2357 path, lnum);
2358 if (serial2 <= serial)
2359 fatal("%s:%lu: invalid serial range "
2360 "%llu:%llu", path, lnum,
2361 (unsigned long long)serial,
2362 (unsigned long long)serial2);
2363 }
2364 if (ssh_krl_revoke_cert_by_serial_range(krl,
2365 ca, serial, serial2) != 0) {
2366 fatal_f("revoke serial failed");
2367 }
2368 } else if (strncasecmp(cp, "id:", 3) == 0) {
2369 if (ca == NULL && !wild_ca) {
2370 fatal("revoking certificates by key ID "
2371 "requires specification of a CA key");
2372 }
2373 cp += 3;
2374 cp = cp + strspn(cp, " \t");
2375 if (ssh_krl_revoke_cert_by_key_id(krl, ca, cp) != 0)
2376 fatal_f("revoke key ID failed");
2377 } else if (strncasecmp(cp, "hash:", 5) == 0) {
2378 cp += 5;
2379 cp = cp + strspn(cp, " \t");
2380 hash_to_blob(cp, &blob, &blen, file, lnum);
2381 r = ssh_krl_revoke_key_sha256(krl, blob, blen);
2382 if (r != 0)
2383 fatal_fr(r, "revoke key failed");
2384 } else {
2385 if (strncasecmp(cp, "key:", 4) == 0) {
2386 cp += 4;
2387 cp = cp + strspn(cp, " \t");
2388 was_explicit_key = 1;
2389 } else if (strncasecmp(cp, "sha1:", 5) == 0) {
2390 cp += 5;
2391 cp = cp + strspn(cp, " \t");
2392 was_sha1 = 1;
2393 } else if (strncasecmp(cp, "sha256:", 7) == 0) {
2394 cp += 7;
2395 cp = cp + strspn(cp, " \t");
2396 was_sha256 = 1;
2397 /*
2398 * Just try to process the line as a key.
2399 * Parsing will fail if it isn't.
2400 */
2401 }
2402 if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
2403 fatal("sshkey_new");
2404 if ((r = sshkey_read(key, &cp)) != 0)
2405 fatal_r(r, "%s:%lu: invalid key", path, lnum);
2406 if (was_explicit_key)
2407 r = ssh_krl_revoke_key_explicit(krl, key);
2408 else if (was_sha1) {
2409 if (sshkey_fingerprint_raw(key,
2410 SSH_DIGEST_SHA1, &blob, &blen) != 0) {
2411 fatal("%s:%lu: fingerprint failed",
2412 file, lnum);
2413 }
2414 r = ssh_krl_revoke_key_sha1(krl, blob, blen);
2415 } else if (was_sha256) {
2416 if (sshkey_fingerprint_raw(key,
2417 SSH_DIGEST_SHA256, &blob, &blen) != 0) {
2418 fatal("%s:%lu: fingerprint failed",
2419 file, lnum);
2420 }
2421 r = ssh_krl_revoke_key_sha256(krl, blob, blen);
2422 } else
2423 r = ssh_krl_revoke_key(krl, key);
2424 if (r != 0)
2425 fatal_fr(r, "revoke key failed");
2426 freezero(blob, blen);
2427 blob = NULL;
2428 blen = 0;
2429 sshkey_free(key);
2430 }
2431 }
2432 if (strcmp(path, "-") != 0)
2433 fclose(krl_spec);
2434 free(line);
2435 free(path);
2436 }
2437
2438 static void
do_gen_krl(struct passwd * pw,int updating,const char * ca_key_path,unsigned long long krl_version,const char * krl_comment,int argc,char ** argv)2439 do_gen_krl(struct passwd *pw, int updating, const char *ca_key_path,
2440 unsigned long long krl_version, const char *krl_comment,
2441 int argc, char **argv)
2442 {
2443 struct ssh_krl *krl;
2444 struct stat sb;
2445 struct sshkey *ca = NULL;
2446 int i, r, wild_ca = 0;
2447 char *tmp;
2448 struct sshbuf *kbuf;
2449
2450 if (*identity_file == '\0')
2451 fatal("KRL generation requires an output file");
2452 if (stat(identity_file, &sb) == -1) {
2453 if (errno != ENOENT)
2454 fatal("Cannot access KRL \"%s\": %s",
2455 identity_file, strerror(errno));
2456 if (updating)
2457 fatal("KRL \"%s\" does not exist", identity_file);
2458 }
2459 if (ca_key_path != NULL) {
2460 if (strcasecmp(ca_key_path, "none") == 0)
2461 wild_ca = 1;
2462 else {
2463 tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
2464 if ((r = sshkey_load_public(tmp, &ca, NULL)) != 0)
2465 fatal_r(r, "Cannot load CA public key %s", tmp);
2466 free(tmp);
2467 }
2468 }
2469
2470 if (updating)
2471 load_krl(identity_file, &krl);
2472 else if ((krl = ssh_krl_init()) == NULL)
2473 fatal("couldn't create KRL");
2474
2475 if (krl_version != 0)
2476 ssh_krl_set_version(krl, krl_version);
2477 if (krl_comment != NULL)
2478 ssh_krl_set_comment(krl, krl_comment);
2479
2480 for (i = 0; i < argc; i++)
2481 update_krl_from_file(pw, argv[i], wild_ca, ca, krl);
2482
2483 if ((kbuf = sshbuf_new()) == NULL)
2484 fatal("sshbuf_new failed");
2485 if (ssh_krl_to_blob(krl, kbuf) != 0)
2486 fatal("Couldn't generate KRL");
2487 if ((r = sshbuf_write_file(identity_file, kbuf)) != 0)
2488 fatal("write %s: %s", identity_file, strerror(errno));
2489 sshbuf_free(kbuf);
2490 ssh_krl_free(krl);
2491 sshkey_free(ca);
2492 }
2493
2494 static void
do_check_krl(struct passwd * pw,int print_krl,int argc,char ** argv)2495 do_check_krl(struct passwd *pw, int print_krl, int argc, char **argv)
2496 {
2497 int i, r, ret = 0;
2498 char *comment;
2499 struct ssh_krl *krl;
2500 struct sshkey *k;
2501
2502 if (*identity_file == '\0')
2503 fatal("KRL checking requires an input file");
2504 load_krl(identity_file, &krl);
2505 if (print_krl)
2506 krl_dump(krl, stdout);
2507 for (i = 0; i < argc; i++) {
2508 if ((r = sshkey_load_public(argv[i], &k, &comment)) != 0)
2509 fatal_r(r, "Cannot load public key %s", argv[i]);
2510 r = ssh_krl_check_key(krl, k);
2511 printf("%s%s%s%s: %s\n", argv[i],
2512 *comment ? " (" : "", comment, *comment ? ")" : "",
2513 r == 0 ? "ok" : "REVOKED");
2514 if (r != 0)
2515 ret = 1;
2516 sshkey_free(k);
2517 free(comment);
2518 }
2519 ssh_krl_free(krl);
2520 exit(ret);
2521 }
2522
2523 static struct sshkey *
load_sign_key(const char * keypath,const struct sshkey * pubkey)2524 load_sign_key(const char *keypath, const struct sshkey *pubkey)
2525 {
2526 size_t i, slen, plen = strlen(keypath);
2527 char *privpath = xstrdup(keypath);
2528 static const char * const suffixes[] = { "-cert.pub", ".pub", NULL };
2529 struct sshkey *ret = NULL, *privkey = NULL;
2530 int r, waspub = 0;
2531 struct stat st;
2532
2533 /*
2534 * If passed a public key filename, then try to locate the corresponding
2535 * private key. This lets us specify certificates on the command-line
2536 * and have ssh-keygen find the appropriate private key.
2537 */
2538 for (i = 0; suffixes[i]; i++) {
2539 slen = strlen(suffixes[i]);
2540 if (plen <= slen ||
2541 strcmp(privpath + plen - slen, suffixes[i]) != 0)
2542 continue;
2543 privpath[plen - slen] = '\0';
2544 debug_f("%s looks like a public key, using private key "
2545 "path %s instead", keypath, privpath);
2546 waspub = 1;
2547 }
2548 if (waspub && stat(privpath, &st) != 0 && errno == ENOENT)
2549 fatal("No private key found for public key \"%s\"", keypath);
2550 if ((r = sshkey_load_private(privpath, "", &privkey, NULL)) != 0 &&
2551 (r != SSH_ERR_KEY_WRONG_PASSPHRASE)) {
2552 debug_fr(r, "load private key \"%s\"", privpath);
2553 fatal("No private key found for \"%s\"", privpath);
2554 } else if (privkey == NULL)
2555 privkey = load_identity(privpath, NULL);
2556
2557 if (!sshkey_equal_public(pubkey, privkey)) {
2558 error("Public key %s doesn't match private %s",
2559 keypath, privpath);
2560 goto done;
2561 }
2562 if (sshkey_is_cert(pubkey) && !sshkey_is_cert(privkey)) {
2563 /*
2564 * Graft the certificate onto the private key to make
2565 * it capable of signing.
2566 */
2567 if ((r = sshkey_to_certified(privkey)) != 0) {
2568 error_fr(r, "sshkey_to_certified");
2569 goto done;
2570 }
2571 if ((r = sshkey_cert_copy(pubkey, privkey)) != 0) {
2572 error_fr(r, "sshkey_cert_copy");
2573 goto done;
2574 }
2575 }
2576 /* success */
2577 ret = privkey;
2578 privkey = NULL;
2579 done:
2580 sshkey_free(privkey);
2581 free(privpath);
2582 return ret;
2583 }
2584
2585 static int
sign_one(struct sshkey * signkey,const char * filename,int fd,const char * sig_namespace,const char * hashalg,sshsig_signer * signer,void * signer_ctx)2586 sign_one(struct sshkey *signkey, const char *filename, int fd,
2587 const char *sig_namespace, const char *hashalg, sshsig_signer *signer,
2588 void *signer_ctx)
2589 {
2590 struct sshbuf *sigbuf = NULL, *abuf = NULL;
2591 int r = SSH_ERR_INTERNAL_ERROR, wfd = -1, oerrno;
2592 char *wfile = NULL, *asig = NULL, *fp = NULL;
2593 char *pin = NULL, *prompt = NULL;
2594
2595 if (!quiet) {
2596 if (fd == STDIN_FILENO)
2597 fprintf(stderr, "Signing data on standard input\n");
2598 else
2599 fprintf(stderr, "Signing file %s\n", filename);
2600 }
2601 if (signer == NULL && sshkey_is_sk(signkey)) {
2602 if ((signkey->sk_flags & SSH_SK_USER_VERIFICATION_REQD)) {
2603 xasprintf(&prompt, "Enter PIN for %s key: ",
2604 sshkey_type(signkey));
2605 if ((pin = read_passphrase(prompt,
2606 RP_ALLOW_STDIN)) == NULL)
2607 fatal_f("couldn't read PIN");
2608 }
2609 if ((signkey->sk_flags & SSH_SK_USER_PRESENCE_REQD)) {
2610 if ((fp = sshkey_fingerprint(signkey, fingerprint_hash,
2611 SSH_FP_DEFAULT)) == NULL)
2612 fatal_f("fingerprint failed");
2613 fprintf(stderr, "Confirm user presence for key %s %s\n",
2614 sshkey_type(signkey), fp);
2615 free(fp);
2616 }
2617 }
2618 if ((r = sshsig_sign_fd(signkey, hashalg, sk_provider, pin,
2619 fd, sig_namespace, &sigbuf, signer, signer_ctx)) != 0) {
2620 error_r(r, "Signing %s failed", filename);
2621 goto out;
2622 }
2623 if ((r = sshsig_armor(sigbuf, &abuf)) != 0) {
2624 error_fr(r, "sshsig_armor");
2625 goto out;
2626 }
2627 if ((asig = sshbuf_dup_string(abuf)) == NULL) {
2628 error_f("buffer error");
2629 r = SSH_ERR_ALLOC_FAIL;
2630 goto out;
2631 }
2632
2633 if (fd == STDIN_FILENO) {
2634 fputs(asig, stdout);
2635 fflush(stdout);
2636 } else {
2637 xasprintf(&wfile, "%s.sig", filename);
2638 if (confirm_overwrite(wfile)) {
2639 if ((wfd = open(wfile, O_WRONLY|O_CREAT|O_TRUNC,
2640 0666)) == -1) {
2641 oerrno = errno;
2642 error("Cannot open %s: %s",
2643 wfile, strerror(errno));
2644 errno = oerrno;
2645 r = SSH_ERR_SYSTEM_ERROR;
2646 goto out;
2647 }
2648 if (atomicio(vwrite, wfd, asig,
2649 strlen(asig)) != strlen(asig)) {
2650 oerrno = errno;
2651 error("Cannot write to %s: %s",
2652 wfile, strerror(errno));
2653 errno = oerrno;
2654 r = SSH_ERR_SYSTEM_ERROR;
2655 goto out;
2656 }
2657 if (!quiet) {
2658 fprintf(stderr, "Write signature to %s\n",
2659 wfile);
2660 }
2661 }
2662 }
2663 /* success */
2664 r = 0;
2665 out:
2666 free(wfile);
2667 free(prompt);
2668 free(asig);
2669 if (pin != NULL)
2670 freezero(pin, strlen(pin));
2671 sshbuf_free(abuf);
2672 sshbuf_free(sigbuf);
2673 if (wfd != -1)
2674 close(wfd);
2675 return r;
2676 }
2677
2678 static int
sig_process_opts(char * const * opts,size_t nopts,char ** hashalgp,uint64_t * verify_timep,int * print_pubkey)2679 sig_process_opts(char * const *opts, size_t nopts, char **hashalgp,
2680 uint64_t *verify_timep, int *print_pubkey)
2681 {
2682 size_t i;
2683 time_t now;
2684
2685 if (verify_timep != NULL)
2686 *verify_timep = 0;
2687 if (print_pubkey != NULL)
2688 *print_pubkey = 0;
2689 if (hashalgp != NULL)
2690 *hashalgp = NULL;
2691 for (i = 0; i < nopts; i++) {
2692 if (hashalgp != NULL &&
2693 strncasecmp(opts[i], "hashalg=", 8) == 0) {
2694 *hashalgp = xstrdup(opts[i] + 8);
2695 } else if (verify_timep &&
2696 strncasecmp(opts[i], "verify-time=", 12) == 0) {
2697 if (parse_absolute_time(opts[i] + 12,
2698 verify_timep) != 0 || *verify_timep == 0) {
2699 error("Invalid \"verify-time\" option");
2700 return SSH_ERR_INVALID_ARGUMENT;
2701 }
2702 } else if (print_pubkey &&
2703 strcasecmp(opts[i], "print-pubkey") == 0) {
2704 *print_pubkey = 1;
2705 } else {
2706 error("Invalid option \"%s\"", opts[i]);
2707 return SSH_ERR_INVALID_ARGUMENT;
2708 }
2709 }
2710 if (verify_timep && *verify_timep == 0) {
2711 if ((now = time(NULL)) < 0) {
2712 error("Time is before epoch");
2713 return SSH_ERR_INVALID_ARGUMENT;
2714 }
2715 *verify_timep = (uint64_t)now;
2716 }
2717 return 0;
2718 }
2719
2720
2721 static int
sig_sign(const char * keypath,const char * sig_namespace,int require_agent,int argc,char ** argv,char * const * opts,size_t nopts)2722 sig_sign(const char *keypath, const char *sig_namespace, int require_agent,
2723 int argc, char **argv, char * const *opts, size_t nopts)
2724 {
2725 int i, fd = -1, r, ret = -1;
2726 int agent_fd = -1;
2727 struct sshkey *pubkey = NULL, *privkey = NULL, *signkey = NULL;
2728 sshsig_signer *signer = NULL;
2729 char *hashalg = NULL;
2730
2731 /* Check file arguments. */
2732 for (i = 0; i < argc; i++) {
2733 if (strcmp(argv[i], "-") != 0)
2734 continue;
2735 if (i > 0 || argc > 1)
2736 fatal("Cannot sign mix of paths and standard input");
2737 }
2738
2739 if (sig_process_opts(opts, nopts, &hashalg, NULL, NULL) != 0)
2740 goto done; /* error already logged */
2741
2742 if ((r = sshkey_load_public(keypath, &pubkey, NULL)) != 0) {
2743 error_r(r, "Couldn't load public key %s", keypath);
2744 goto done;
2745 }
2746
2747 if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) {
2748 if (require_agent)
2749 fatal("Couldn't get agent socket");
2750 debug_r(r, "Couldn't get agent socket");
2751 } else {
2752 if ((r = ssh_agent_has_key(agent_fd, pubkey)) == 0)
2753 signer = agent_signer;
2754 else {
2755 if (require_agent)
2756 fatal("Couldn't find key in agent");
2757 debug_r(r, "Couldn't find key in agent");
2758 }
2759 }
2760
2761 if (signer == NULL) {
2762 /* Not using agent - try to load private key */
2763 if ((privkey = load_sign_key(keypath, pubkey)) == NULL)
2764 goto done;
2765 signkey = privkey;
2766 } else {
2767 /* Will use key in agent */
2768 signkey = pubkey;
2769 }
2770
2771 if (argc == 0) {
2772 if ((r = sign_one(signkey, "(stdin)", STDIN_FILENO,
2773 sig_namespace, hashalg, signer, &agent_fd)) != 0)
2774 goto done;
2775 } else {
2776 for (i = 0; i < argc; i++) {
2777 if (strcmp(argv[i], "-") == 0)
2778 fd = STDIN_FILENO;
2779 else if ((fd = open(argv[i], O_RDONLY)) == -1) {
2780 error("Cannot open %s for signing: %s",
2781 argv[i], strerror(errno));
2782 goto done;
2783 }
2784 if ((r = sign_one(signkey, argv[i], fd, sig_namespace,
2785 hashalg, signer, &agent_fd)) != 0)
2786 goto done;
2787 if (fd != STDIN_FILENO)
2788 close(fd);
2789 fd = -1;
2790 }
2791 }
2792
2793 ret = 0;
2794 done:
2795 if (fd != -1 && fd != STDIN_FILENO)
2796 close(fd);
2797 sshkey_free(pubkey);
2798 sshkey_free(privkey);
2799 free(hashalg);
2800 return ret;
2801 }
2802
2803 static int
sig_verify(const char * signature,const char * sig_namespace,const char * principal,const char * allowed_keys,const char * revoked_keys,char * const * opts,size_t nopts)2804 sig_verify(const char *signature, const char *sig_namespace,
2805 const char *principal, const char *allowed_keys, const char *revoked_keys,
2806 char * const *opts, size_t nopts)
2807 {
2808 int r, ret = -1;
2809 int print_pubkey = 0;
2810 struct sshbuf *sigbuf = NULL, *abuf = NULL;
2811 struct sshkey *sign_key = NULL;
2812 char *fp = NULL;
2813 struct sshkey_sig_details *sig_details = NULL;
2814 uint64_t verify_time = 0;
2815
2816 if (sig_process_opts(opts, nopts, NULL, &verify_time,
2817 &print_pubkey) != 0)
2818 goto done; /* error already logged */
2819
2820 memset(&sig_details, 0, sizeof(sig_details));
2821 if ((r = sshbuf_load_file(signature, &abuf)) != 0) {
2822 error_r(r, "Couldn't read signature file");
2823 goto done;
2824 }
2825
2826 if ((r = sshsig_dearmor(abuf, &sigbuf)) != 0) {
2827 error_fr(r, "sshsig_armor");
2828 goto done;
2829 }
2830 if ((r = sshsig_verify_fd(sigbuf, STDIN_FILENO, sig_namespace,
2831 &sign_key, &sig_details)) != 0)
2832 goto done; /* sshsig_verify() prints error */
2833
2834 if ((fp = sshkey_fingerprint(sign_key, fingerprint_hash,
2835 SSH_FP_DEFAULT)) == NULL)
2836 fatal_f("sshkey_fingerprint failed");
2837 debug("Valid (unverified) signature from key %s", fp);
2838 if (sig_details != NULL) {
2839 debug2_f("signature details: counter = %u, flags = 0x%02x",
2840 sig_details->sk_counter, sig_details->sk_flags);
2841 }
2842 free(fp);
2843 fp = NULL;
2844
2845 if (revoked_keys != NULL) {
2846 if ((r = sshkey_check_revoked(sign_key, revoked_keys)) != 0) {
2847 debug3_fr(r, "sshkey_check_revoked");
2848 goto done;
2849 }
2850 }
2851
2852 if (allowed_keys != NULL && (r = sshsig_check_allowed_keys(allowed_keys,
2853 sign_key, principal, sig_namespace, verify_time)) != 0) {
2854 debug3_fr(r, "sshsig_check_allowed_keys");
2855 goto done;
2856 }
2857 /* success */
2858 ret = 0;
2859 done:
2860 if (!quiet) {
2861 if (ret == 0) {
2862 if ((fp = sshkey_fingerprint(sign_key, fingerprint_hash,
2863 SSH_FP_DEFAULT)) == NULL)
2864 fatal_f("sshkey_fingerprint failed");
2865 if (principal == NULL) {
2866 printf("Good \"%s\" signature with %s key %s\n",
2867 sig_namespace, sshkey_type(sign_key), fp);
2868
2869 } else {
2870 printf("Good \"%s\" signature for %s with %s key %s\n",
2871 sig_namespace, principal,
2872 sshkey_type(sign_key), fp);
2873 }
2874 } else {
2875 printf("Could not verify signature.\n");
2876 }
2877 }
2878 /* Print the signature key if requested */
2879 if (ret == 0 && print_pubkey && sign_key != NULL) {
2880 if ((r = sshkey_write(sign_key, stdout)) == 0)
2881 fputc('\n', stdout);
2882 else {
2883 error_r(r, "Could not print public key.\n");
2884 ret = -1;
2885 }
2886 }
2887 sshbuf_free(sigbuf);
2888 sshbuf_free(abuf);
2889 sshkey_free(sign_key);
2890 sshkey_sig_details_free(sig_details);
2891 free(fp);
2892 return ret;
2893 }
2894
2895 static int
sig_find_principals(const char * signature,const char * allowed_keys,char * const * opts,size_t nopts)2896 sig_find_principals(const char *signature, const char *allowed_keys,
2897 char * const *opts, size_t nopts)
2898 {
2899 int r, ret = -1;
2900 struct sshbuf *sigbuf = NULL, *abuf = NULL;
2901 struct sshkey *sign_key = NULL;
2902 char *principals = NULL, *cp, *tmp;
2903 uint64_t verify_time = 0;
2904
2905 if (sig_process_opts(opts, nopts, NULL, &verify_time, NULL) != 0)
2906 goto done; /* error already logged */
2907
2908 if ((r = sshbuf_load_file(signature, &abuf)) != 0) {
2909 error_r(r, "Couldn't read signature file");
2910 goto done;
2911 }
2912 if ((r = sshsig_dearmor(abuf, &sigbuf)) != 0) {
2913 error_fr(r, "sshsig_armor");
2914 goto done;
2915 }
2916 if ((r = sshsig_get_pubkey(sigbuf, &sign_key)) != 0) {
2917 error_fr(r, "sshsig_get_pubkey");
2918 goto done;
2919 }
2920 if ((r = sshsig_find_principals(allowed_keys, sign_key,
2921 verify_time, &principals)) != 0) {
2922 if (r != SSH_ERR_KEY_NOT_FOUND)
2923 error_fr(r, "sshsig_find_principal");
2924 goto done;
2925 }
2926 ret = 0;
2927 done:
2928 if (ret == 0 ) {
2929 /* Emit matching principals one per line */
2930 tmp = principals;
2931 while ((cp = strsep(&tmp, ",")) != NULL && *cp != '\0')
2932 puts(cp);
2933 } else {
2934 fprintf(stderr, "No principal matched.\n");
2935 }
2936 sshbuf_free(sigbuf);
2937 sshbuf_free(abuf);
2938 sshkey_free(sign_key);
2939 free(principals);
2940 return ret;
2941 }
2942
2943 static int
sig_match_principals(const char * allowed_keys,char * principal,char * const * opts,size_t nopts)2944 sig_match_principals(const char *allowed_keys, char *principal,
2945 char * const *opts, size_t nopts)
2946 {
2947 int r;
2948 char **principals = NULL;
2949 size_t i, nprincipals = 0;
2950
2951 if ((r = sig_process_opts(opts, nopts, NULL, NULL, NULL)) != 0)
2952 return r; /* error already logged */
2953
2954 if ((r = sshsig_match_principals(allowed_keys, principal,
2955 &principals, &nprincipals)) != 0) {
2956 debug_f("match: %s", ssh_err(r));
2957 fprintf(stderr, "No principal matched.\n");
2958 return r;
2959 }
2960 for (i = 0; i < nprincipals; i++) {
2961 printf("%s\n", principals[i]);
2962 free(principals[i]);
2963 }
2964 free(principals);
2965
2966 return 0;
2967 }
2968
2969 static void
do_moduli_gen(const char * out_file,char ** opts,size_t nopts)2970 do_moduli_gen(const char *out_file, char **opts, size_t nopts)
2971 {
2972 #ifdef WITH_OPENSSL
2973 /* Moduli generation/screening */
2974 u_int32_t memory = 0;
2975 BIGNUM *start = NULL;
2976 int moduli_bits = 0;
2977 FILE *out;
2978 size_t i;
2979 const char *errstr;
2980
2981 /* Parse options */
2982 for (i = 0; i < nopts; i++) {
2983 if (strncmp(opts[i], "memory=", 7) == 0) {
2984 memory = (u_int32_t)strtonum(opts[i]+7, 1,
2985 UINT_MAX, &errstr);
2986 if (errstr) {
2987 fatal("Memory limit is %s: %s",
2988 errstr, opts[i]+7);
2989 }
2990 } else if (strncmp(opts[i], "start=", 6) == 0) {
2991 /* XXX - also compare length against bits */
2992 if (BN_hex2bn(&start, opts[i]+6) == 0)
2993 fatal("Invalid start point.");
2994 } else if (strncmp(opts[i], "bits=", 5) == 0) {
2995 moduli_bits = (int)strtonum(opts[i]+5, 1,
2996 INT_MAX, &errstr);
2997 if (errstr) {
2998 fatal("Invalid number: %s (%s)",
2999 opts[i]+12, errstr);
3000 }
3001 } else {
3002 fatal("Option \"%s\" is unsupported for moduli "
3003 "generation", opts[i]);
3004 }
3005 }
3006
3007 if ((out = fopen(out_file, "w")) == NULL) {
3008 fatal("Couldn't open modulus candidate file \"%s\": %s",
3009 out_file, strerror(errno));
3010 }
3011 setvbuf(out, NULL, _IOLBF, 0);
3012
3013 if (moduli_bits == 0)
3014 moduli_bits = DEFAULT_BITS;
3015 if (gen_candidates(out, memory, moduli_bits, start) != 0)
3016 fatal("modulus candidate generation failed");
3017 #else /* WITH_OPENSSL */
3018 fatal("Moduli generation is not supported");
3019 #endif /* WITH_OPENSSL */
3020 }
3021
3022 static void
do_moduli_screen(const char * out_file,char ** opts,size_t nopts)3023 do_moduli_screen(const char *out_file, char **opts, size_t nopts)
3024 {
3025 #ifdef WITH_OPENSSL
3026 /* Moduli generation/screening */
3027 char *checkpoint = NULL;
3028 u_int32_t generator_wanted = 0;
3029 unsigned long start_lineno = 0, lines_to_process = 0;
3030 int prime_tests = 0;
3031 FILE *out, *in = stdin;
3032 size_t i;
3033 const char *errstr;
3034
3035 /* Parse options */
3036 for (i = 0; i < nopts; i++) {
3037 if (strncmp(opts[i], "lines=", 6) == 0) {
3038 lines_to_process = strtoul(opts[i]+6, NULL, 10);
3039 } else if (strncmp(opts[i], "start-line=", 11) == 0) {
3040 start_lineno = strtoul(opts[i]+11, NULL, 10);
3041 } else if (strncmp(opts[i], "checkpoint=", 11) == 0) {
3042 free(checkpoint);
3043 checkpoint = xstrdup(opts[i]+11);
3044 } else if (strncmp(opts[i], "generator=", 10) == 0) {
3045 generator_wanted = (u_int32_t)strtonum(
3046 opts[i]+10, 1, UINT_MAX, &errstr);
3047 if (errstr != NULL) {
3048 fatal("Generator invalid: %s (%s)",
3049 opts[i]+10, errstr);
3050 }
3051 } else if (strncmp(opts[i], "prime-tests=", 12) == 0) {
3052 prime_tests = (int)strtonum(opts[i]+12, 1,
3053 INT_MAX, &errstr);
3054 if (errstr) {
3055 fatal("Invalid number: %s (%s)",
3056 opts[i]+12, errstr);
3057 }
3058 } else {
3059 fatal("Option \"%s\" is unsupported for moduli "
3060 "screening", opts[i]);
3061 }
3062 }
3063
3064 if (have_identity && strcmp(identity_file, "-") != 0) {
3065 if ((in = fopen(identity_file, "r")) == NULL) {
3066 fatal("Couldn't open modulus candidate "
3067 "file \"%s\": %s", identity_file,
3068 strerror(errno));
3069 }
3070 }
3071
3072 if ((out = fopen(out_file, "a")) == NULL) {
3073 fatal("Couldn't open moduli file \"%s\": %s",
3074 out_file, strerror(errno));
3075 }
3076 setvbuf(out, NULL, _IOLBF, 0);
3077 if (prime_test(in, out, prime_tests == 0 ? 100 : prime_tests,
3078 generator_wanted, checkpoint,
3079 start_lineno, lines_to_process) != 0)
3080 fatal("modulus screening failed");
3081 if (in != stdin)
3082 (void)fclose(in);
3083 free(checkpoint);
3084 #else /* WITH_OPENSSL */
3085 fatal("Moduli screening is not supported");
3086 #endif /* WITH_OPENSSL */
3087 }
3088
3089 /* Read and confirm a passphrase */
3090 static char *
read_check_passphrase(const char * prompt1,const char * prompt2,const char * retry_prompt)3091 read_check_passphrase(const char *prompt1, const char *prompt2,
3092 const char *retry_prompt)
3093 {
3094 char *passphrase1, *passphrase2;
3095
3096 for (;;) {
3097 passphrase1 = read_passphrase(prompt1, RP_ALLOW_STDIN);
3098 passphrase2 = read_passphrase(prompt2, RP_ALLOW_STDIN);
3099 if (strcmp(passphrase1, passphrase2) == 0) {
3100 freezero(passphrase2, strlen(passphrase2));
3101 return passphrase1;
3102 }
3103 /* The passphrases do not match. Clear them and retry. */
3104 freezero(passphrase1, strlen(passphrase1));
3105 freezero(passphrase2, strlen(passphrase2));
3106 fputs(retry_prompt, stdout);
3107 fputc('\n', stdout);
3108 fflush(stdout);
3109 }
3110 /* NOTREACHED */
3111 return NULL;
3112 }
3113
3114 static char *
private_key_passphrase(void)3115 private_key_passphrase(void)
3116 {
3117 if (identity_passphrase)
3118 return xstrdup(identity_passphrase);
3119 if (identity_new_passphrase)
3120 return xstrdup(identity_new_passphrase);
3121
3122 return read_check_passphrase(
3123 "Enter passphrase (empty for no passphrase): ",
3124 "Enter same passphrase again: ",
3125 "Passphrases do not match. Try again.");
3126 }
3127
3128 static char *
sk_suffix(const char * application,const uint8_t * user,size_t userlen)3129 sk_suffix(const char *application, const uint8_t *user, size_t userlen)
3130 {
3131 char *ret, *cp;
3132 size_t slen, i;
3133
3134 /* Trim off URL-like preamble */
3135 if (strncmp(application, "ssh://", 6) == 0)
3136 ret = xstrdup(application + 6);
3137 else if (strncmp(application, "ssh:", 4) == 0)
3138 ret = xstrdup(application + 4);
3139 else
3140 ret = xstrdup(application);
3141
3142 /* Count trailing zeros in user */
3143 for (i = 0; i < userlen; i++) {
3144 if (user[userlen - i - 1] != 0)
3145 break;
3146 }
3147 if (i >= userlen)
3148 return ret; /* user-id was default all-zeros */
3149
3150 /* Append user-id, escaping non-UTF-8 characters */
3151 slen = userlen - i;
3152 if (asmprintf(&cp, INT_MAX, NULL, "%.*s", (int)slen, user) == -1)
3153 fatal_f("asmprintf failed");
3154 /* Don't emit a user-id that contains path or control characters */
3155 if (strchr(cp, '/') != NULL || strstr(cp, "..") != NULL ||
3156 strchr(cp, '\\') != NULL) {
3157 free(cp);
3158 cp = tohex(user, slen);
3159 }
3160 xextendf(&ret, "_", "%s", cp);
3161 free(cp);
3162 return ret;
3163 }
3164
3165 static int
do_download_sk(const char * skprovider,const char * device)3166 do_download_sk(const char *skprovider, const char *device)
3167 {
3168 struct sshsk_resident_key **srks;
3169 size_t nsrks, i;
3170 int r, ret = -1;
3171 char *fp, *pin = NULL, *pass = NULL, *path, *pubpath;
3172 const char *ext;
3173 struct sshkey *key;
3174
3175 if (skprovider == NULL)
3176 fatal("Cannot download keys without provider");
3177
3178 pin = read_passphrase("Enter PIN for authenticator: ", RP_ALLOW_STDIN);
3179 if (!quiet) {
3180 printf("You may need to touch your authenticator "
3181 "to authorize key download.\n");
3182 }
3183 if ((r = sshsk_load_resident(skprovider, device, pin, 0,
3184 &srks, &nsrks)) != 0) {
3185 if (pin != NULL)
3186 freezero(pin, strlen(pin));
3187 error_r(r, "Unable to load resident keys");
3188 return -1;
3189 }
3190 if (nsrks == 0)
3191 logit("No keys to download");
3192 if (pin != NULL)
3193 freezero(pin, strlen(pin));
3194
3195 for (i = 0; i < nsrks; i++) {
3196 key = srks[i]->key;
3197 if (key->type != KEY_ECDSA_SK && key->type != KEY_ED25519_SK) {
3198 error("Unsupported key type %s (%d)",
3199 sshkey_type(key), key->type);
3200 continue;
3201 }
3202 if ((fp = sshkey_fingerprint(key, fingerprint_hash,
3203 SSH_FP_DEFAULT)) == NULL)
3204 fatal_f("sshkey_fingerprint failed");
3205 debug_f("key %zu: %s %s %s (flags 0x%02x)", i,
3206 sshkey_type(key), fp, key->sk_application, key->sk_flags);
3207 ext = sk_suffix(key->sk_application,
3208 srks[i]->user_id, srks[i]->user_id_len);
3209 xasprintf(&path, "id_%s_rk%s%s",
3210 key->type == KEY_ECDSA_SK ? "ecdsa_sk" : "ed25519_sk",
3211 *ext == '\0' ? "" : "_", ext);
3212
3213 /* If the file already exists, ask the user to confirm. */
3214 if (!confirm_overwrite(path)) {
3215 free(path);
3216 break;
3217 }
3218
3219 /* Save the key with the application string as the comment */
3220 if (pass == NULL)
3221 pass = private_key_passphrase();
3222 if ((r = sshkey_save_private(key, path, pass,
3223 key->sk_application, private_key_format,
3224 openssh_format_cipher, rounds)) != 0) {
3225 error_r(r, "Saving key \"%s\" failed", path);
3226 free(path);
3227 break;
3228 }
3229 if (!quiet) {
3230 printf("Saved %s key%s%s to %s\n", sshkey_type(key),
3231 *ext != '\0' ? " " : "",
3232 *ext != '\0' ? key->sk_application : "",
3233 path);
3234 }
3235
3236 /* Save public key too */
3237 xasprintf(&pubpath, "%s.pub", path);
3238 free(path);
3239 if ((r = sshkey_save_public(key, pubpath,
3240 key->sk_application)) != 0) {
3241 error_r(r, "Saving public key \"%s\" failed", pubpath);
3242 free(pubpath);
3243 break;
3244 }
3245 free(pubpath);
3246 }
3247
3248 if (i >= nsrks)
3249 ret = 0; /* success */
3250 if (pass != NULL)
3251 freezero(pass, strlen(pass));
3252 sshsk_free_resident_keys(srks, nsrks);
3253 return ret;
3254 }
3255
3256 static void
save_attestation(struct sshbuf * attest,const char * path)3257 save_attestation(struct sshbuf *attest, const char *path)
3258 {
3259 mode_t omask;
3260 int r;
3261
3262 if (path == NULL)
3263 return; /* nothing to do */
3264 if (attest == NULL || sshbuf_len(attest) == 0)
3265 fatal("Enrollment did not return attestation data");
3266 omask = umask(077);
3267 r = sshbuf_write_file(path, attest);
3268 umask(omask);
3269 if (r != 0)
3270 fatal_r(r, "Unable to write attestation data \"%s\"", path);
3271 if (!quiet)
3272 printf("Your FIDO attestation certificate has been saved in "
3273 "%s\n", path);
3274 }
3275
3276 static int
confirm_sk_overwrite(const char * application,const char * user)3277 confirm_sk_overwrite(const char *application, const char *user)
3278 {
3279 char yesno[3];
3280
3281 printf("A resident key scoped to '%s' with user id '%s' already "
3282 "exists.\n", application == NULL ? "ssh:" : application,
3283 user == NULL ? "null" : user);
3284 printf("Overwrite key in token (y/n)? ");
3285 fflush(stdout);
3286 if (fgets(yesno, sizeof(yesno), stdin) == NULL)
3287 return 0;
3288 if (yesno[0] != 'y' && yesno[0] != 'Y')
3289 return 0;
3290 return 1;
3291 }
3292
3293 static void
usage(void)3294 usage(void)
3295 {
3296 fprintf(stderr,
3297 "usage: ssh-keygen [-q] [-a rounds] [-b bits] [-C comment] [-f output_keyfile]\n"
3298 " [-m format] [-N new_passphrase] [-O option]\n"
3299 " [-t dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa]\n"
3300 " [-w provider] [-Z cipher]\n"
3301 " ssh-keygen -p [-a rounds] [-f keyfile] [-m format] [-N new_passphrase]\n"
3302 " [-P old_passphrase] [-Z cipher]\n"
3303 #ifdef WITH_OPENSSL
3304 " ssh-keygen -i [-f input_keyfile] [-m key_format]\n"
3305 " ssh-keygen -e [-f input_keyfile] [-m key_format]\n"
3306 #endif
3307 " ssh-keygen -y [-f input_keyfile]\n"
3308 " ssh-keygen -c [-a rounds] [-C comment] [-f keyfile] [-P passphrase]\n"
3309 " ssh-keygen -l [-v] [-E fingerprint_hash] [-f input_keyfile]\n"
3310 " ssh-keygen -B [-f input_keyfile]\n");
3311 #ifdef ENABLE_PKCS11
3312 fprintf(stderr,
3313 " ssh-keygen -D pkcs11\n");
3314 #endif
3315 fprintf(stderr,
3316 " ssh-keygen -F hostname [-lv] [-f known_hosts_file]\n"
3317 " ssh-keygen -H [-f known_hosts_file]\n"
3318 " ssh-keygen -K [-a rounds] [-w provider]\n"
3319 " ssh-keygen -R hostname [-f known_hosts_file]\n"
3320 " ssh-keygen -r hostname [-g] [-f input_keyfile]\n"
3321 #ifdef WITH_OPENSSL
3322 " ssh-keygen -M generate [-O option] output_file\n"
3323 " ssh-keygen -M screen [-f input_file] [-O option] output_file\n"
3324 #endif
3325 " ssh-keygen -I certificate_identity -s ca_key [-hU] [-D pkcs11_provider]\n"
3326 " [-n principals] [-O option] [-V validity_interval]\n"
3327 " [-z serial_number] file ...\n"
3328 " ssh-keygen -L [-f input_keyfile]\n"
3329 " ssh-keygen -A [-a rounds] [-f prefix_path]\n"
3330 " ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]\n"
3331 " file ...\n"
3332 " ssh-keygen -Q [-l] -f krl_file [file ...]\n"
3333 " ssh-keygen -Y find-principals -s signature_file -f allowed_signers_file\n"
3334 " ssh-keygen -Y match-principals -I signer_identity -f allowed_signers_file\n"
3335 " ssh-keygen -Y check-novalidate -n namespace -s signature_file\n"
3336 " ssh-keygen -Y sign -f key_file -n namespace file [-O option] ...\n"
3337 " ssh-keygen -Y verify -f allowed_signers_file -I signer_identity\n"
3338 " -n namespace -s signature_file [-r krl_file] [-O option]\n");
3339 exit(1);
3340 }
3341
3342 /*
3343 * Main program for key management.
3344 */
3345 int
main(int argc,char ** argv)3346 main(int argc, char **argv)
3347 {
3348 char comment[1024], *passphrase = NULL;
3349 char *rr_hostname = NULL, *ep, *fp, *ra;
3350 struct sshkey *private, *public;
3351 struct passwd *pw;
3352 int r, opt, type;
3353 int change_passphrase = 0, change_comment = 0, show_cert = 0;
3354 int find_host = 0, delete_host = 0, hash_hosts = 0;
3355 int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0;
3356 int prefer_agent = 0, convert_to = 0, convert_from = 0;
3357 int print_public = 0, print_generic = 0, cert_serial_autoinc = 0;
3358 int do_gen_candidates = 0, do_screen_candidates = 0, download_sk = 0;
3359 unsigned long long cert_serial = 0;
3360 char *identity_comment = NULL, *ca_key_path = NULL, **opts = NULL;
3361 char *sk_application = NULL, *sk_device = NULL, *sk_user = NULL;
3362 char *sk_attestation_path = NULL;
3363 struct sshbuf *challenge = NULL, *attest = NULL;
3364 size_t i, nopts = 0;
3365 u_int32_t bits = 0;
3366 uint8_t sk_flags = SSH_SK_USER_PRESENCE_REQD;
3367 const char *errstr;
3368 int log_level = SYSLOG_LEVEL_INFO;
3369 char *sign_op = NULL;
3370
3371 extern int optind;
3372 extern char *optarg;
3373
3374 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
3375 sanitise_stdfd();
3376
3377 __progname = ssh_get_progname(argv[0]);
3378
3379 seed_rng();
3380
3381 log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
3382
3383 msetlocale();
3384
3385 /* we need this for the home * directory. */
3386 pw = getpwuid(getuid());
3387 if (!pw)
3388 fatal("No user exists for uid %lu", (u_long)getuid());
3389 pw = pwcopy(pw);
3390 if (gethostname(hostname, sizeof(hostname)) == -1)
3391 fatal("gethostname: %s", strerror(errno));
3392
3393 sk_provider = getenv("SSH_SK_PROVIDER");
3394
3395 /* Remaining characters: dGjJSTWx */
3396 while ((opt = getopt(argc, argv, "ABHKLQUXceghiklopquvy"
3397 "C:D:E:F:I:M:N:O:P:R:V:Y:Z:"
3398 "a:b:f:g:m:n:r:s:t:w:z:")) != -1) {
3399 switch (opt) {
3400 case 'A':
3401 gen_all_hostkeys = 1;
3402 break;
3403 case 'b':
3404 bits = (u_int32_t)strtonum(optarg, 1, UINT32_MAX,
3405 &errstr);
3406 if (errstr)
3407 fatal("Bits has bad value %s (%s)",
3408 optarg, errstr);
3409 break;
3410 case 'E':
3411 fingerprint_hash = ssh_digest_alg_by_name(optarg);
3412 if (fingerprint_hash == -1)
3413 fatal("Invalid hash algorithm \"%s\"", optarg);
3414 break;
3415 case 'F':
3416 find_host = 1;
3417 rr_hostname = optarg;
3418 break;
3419 case 'H':
3420 hash_hosts = 1;
3421 break;
3422 case 'I':
3423 cert_key_id = optarg;
3424 break;
3425 case 'R':
3426 delete_host = 1;
3427 rr_hostname = optarg;
3428 break;
3429 case 'L':
3430 show_cert = 1;
3431 break;
3432 case 'l':
3433 print_fingerprint = 1;
3434 break;
3435 case 'B':
3436 print_bubblebabble = 1;
3437 break;
3438 case 'm':
3439 if (strcasecmp(optarg, "RFC4716") == 0 ||
3440 strcasecmp(optarg, "ssh2") == 0) {
3441 convert_format = FMT_RFC4716;
3442 break;
3443 }
3444 if (strcasecmp(optarg, "PKCS8") == 0) {
3445 convert_format = FMT_PKCS8;
3446 private_key_format = SSHKEY_PRIVATE_PKCS8;
3447 break;
3448 }
3449 if (strcasecmp(optarg, "PEM") == 0) {
3450 convert_format = FMT_PEM;
3451 private_key_format = SSHKEY_PRIVATE_PEM;
3452 break;
3453 }
3454 fatal("Unsupported conversion format \"%s\"", optarg);
3455 case 'n':
3456 cert_principals = optarg;
3457 break;
3458 case 'o':
3459 /* no-op; new format is already the default */
3460 break;
3461 case 'p':
3462 change_passphrase = 1;
3463 break;
3464 case 'c':
3465 change_comment = 1;
3466 break;
3467 case 'f':
3468 if (strlcpy(identity_file, optarg,
3469 sizeof(identity_file)) >= sizeof(identity_file))
3470 fatal("Identity filename too long");
3471 have_identity = 1;
3472 break;
3473 case 'g':
3474 print_generic = 1;
3475 break;
3476 case 'K':
3477 download_sk = 1;
3478 break;
3479 case 'P':
3480 identity_passphrase = optarg;
3481 break;
3482 case 'N':
3483 identity_new_passphrase = optarg;
3484 break;
3485 case 'Q':
3486 check_krl = 1;
3487 break;
3488 case 'O':
3489 opts = xrecallocarray(opts, nopts, nopts + 1,
3490 sizeof(*opts));
3491 opts[nopts++] = xstrdup(optarg);
3492 break;
3493 case 'Z':
3494 openssh_format_cipher = optarg;
3495 if (cipher_by_name(openssh_format_cipher) == NULL)
3496 fatal("Invalid OpenSSH-format cipher '%s'",
3497 openssh_format_cipher);
3498 break;
3499 case 'C':
3500 identity_comment = optarg;
3501 break;
3502 case 'q':
3503 quiet = 1;
3504 break;
3505 case 'e':
3506 /* export key */
3507 convert_to = 1;
3508 break;
3509 case 'h':
3510 cert_key_type = SSH2_CERT_TYPE_HOST;
3511 certflags_flags = 0;
3512 break;
3513 case 'k':
3514 gen_krl = 1;
3515 break;
3516 case 'i':
3517 case 'X':
3518 /* import key */
3519 convert_from = 1;
3520 break;
3521 case 'y':
3522 print_public = 1;
3523 break;
3524 case 's':
3525 ca_key_path = optarg;
3526 break;
3527 case 't':
3528 key_type_name = optarg;
3529 break;
3530 case 'D':
3531 pkcs11provider = optarg;
3532 break;
3533 case 'U':
3534 prefer_agent = 1;
3535 break;
3536 case 'u':
3537 update_krl = 1;
3538 break;
3539 case 'v':
3540 if (log_level == SYSLOG_LEVEL_INFO)
3541 log_level = SYSLOG_LEVEL_DEBUG1;
3542 else {
3543 if (log_level >= SYSLOG_LEVEL_DEBUG1 &&
3544 log_level < SYSLOG_LEVEL_DEBUG3)
3545 log_level++;
3546 }
3547 break;
3548 case 'r':
3549 rr_hostname = optarg;
3550 break;
3551 case 'a':
3552 rounds = (int)strtonum(optarg, 1, INT_MAX, &errstr);
3553 if (errstr)
3554 fatal("Invalid number: %s (%s)",
3555 optarg, errstr);
3556 break;
3557 case 'V':
3558 parse_cert_times(optarg);
3559 break;
3560 case 'Y':
3561 sign_op = optarg;
3562 break;
3563 case 'w':
3564 sk_provider = optarg;
3565 break;
3566 case 'z':
3567 errno = 0;
3568 if (*optarg == '+') {
3569 cert_serial_autoinc = 1;
3570 optarg++;
3571 }
3572 cert_serial = strtoull(optarg, &ep, 10);
3573 if (*optarg < '0' || *optarg > '9' || *ep != '\0' ||
3574 (errno == ERANGE && cert_serial == ULLONG_MAX))
3575 fatal("Invalid serial number \"%s\"", optarg);
3576 break;
3577 case 'M':
3578 if (strcmp(optarg, "generate") == 0)
3579 do_gen_candidates = 1;
3580 else if (strcmp(optarg, "screen") == 0)
3581 do_screen_candidates = 1;
3582 else
3583 fatal("Unsupported moduli option %s", optarg);
3584 break;
3585 default:
3586 usage();
3587 }
3588 }
3589
3590 #ifdef ENABLE_SK_INTERNAL
3591 if (sk_provider == NULL)
3592 sk_provider = "internal";
3593 #endif
3594
3595 /* reinit */
3596 log_init(argv[0], log_level, SYSLOG_FACILITY_USER, 1);
3597
3598 argv += optind;
3599 argc -= optind;
3600
3601 if (sign_op != NULL) {
3602 if (strncmp(sign_op, "find-principals", 15) == 0) {
3603 if (ca_key_path == NULL) {
3604 error("Too few arguments for find-principals:"
3605 "missing signature file");
3606 exit(1);
3607 }
3608 if (!have_identity) {
3609 error("Too few arguments for find-principals:"
3610 "missing allowed keys file");
3611 exit(1);
3612 }
3613 return sig_find_principals(ca_key_path, identity_file,
3614 opts, nopts);
3615 } else if (strncmp(sign_op, "match-principals", 16) == 0) {
3616 if (!have_identity) {
3617 error("Too few arguments for match-principals:"
3618 "missing allowed keys file");
3619 exit(1);
3620 }
3621 if (cert_key_id == NULL) {
3622 error("Too few arguments for match-principals: "
3623 "missing principal ID");
3624 exit(1);
3625 }
3626 return sig_match_principals(identity_file, cert_key_id,
3627 opts, nopts);
3628 } else if (strncmp(sign_op, "sign", 4) == 0) {
3629 /* NB. cert_principals is actually namespace, via -n */
3630 if (cert_principals == NULL ||
3631 *cert_principals == '\0') {
3632 error("Too few arguments for sign: "
3633 "missing namespace");
3634 exit(1);
3635 }
3636 if (!have_identity) {
3637 error("Too few arguments for sign: "
3638 "missing key");
3639 exit(1);
3640 }
3641 return sig_sign(identity_file, cert_principals,
3642 prefer_agent, argc, argv, opts, nopts);
3643 } else if (strncmp(sign_op, "check-novalidate", 16) == 0) {
3644 /* NB. cert_principals is actually namespace, via -n */
3645 if (cert_principals == NULL ||
3646 *cert_principals == '\0') {
3647 error("Too few arguments for check-novalidate: "
3648 "missing namespace");
3649 exit(1);
3650 }
3651 if (ca_key_path == NULL) {
3652 error("Too few arguments for check-novalidate: "
3653 "missing signature file");
3654 exit(1);
3655 }
3656 return sig_verify(ca_key_path, cert_principals,
3657 NULL, NULL, NULL, opts, nopts);
3658 } else if (strncmp(sign_op, "verify", 6) == 0) {
3659 /* NB. cert_principals is actually namespace, via -n */
3660 if (cert_principals == NULL ||
3661 *cert_principals == '\0') {
3662 error("Too few arguments for verify: "
3663 "missing namespace");
3664 exit(1);
3665 }
3666 if (ca_key_path == NULL) {
3667 error("Too few arguments for verify: "
3668 "missing signature file");
3669 exit(1);
3670 }
3671 if (!have_identity) {
3672 error("Too few arguments for sign: "
3673 "missing allowed keys file");
3674 exit(1);
3675 }
3676 if (cert_key_id == NULL) {
3677 error("Too few arguments for verify: "
3678 "missing principal identity");
3679 exit(1);
3680 }
3681 return sig_verify(ca_key_path, cert_principals,
3682 cert_key_id, identity_file, rr_hostname,
3683 opts, nopts);
3684 }
3685 error("Unsupported operation for -Y: \"%s\"", sign_op);
3686 usage();
3687 /* NOTREACHED */
3688 }
3689
3690 if (ca_key_path != NULL) {
3691 if (argc < 1 && !gen_krl) {
3692 error("Too few arguments.");
3693 usage();
3694 }
3695 } else if (argc > 0 && !gen_krl && !check_krl &&
3696 !do_gen_candidates && !do_screen_candidates) {
3697 error("Too many arguments.");
3698 usage();
3699 }
3700 if (change_passphrase && change_comment) {
3701 error("Can only have one of -p and -c.");
3702 usage();
3703 }
3704 if (print_fingerprint && (delete_host || hash_hosts)) {
3705 error("Cannot use -l with -H or -R.");
3706 usage();
3707 }
3708 if (gen_krl) {
3709 do_gen_krl(pw, update_krl, ca_key_path,
3710 cert_serial, identity_comment, argc, argv);
3711 return (0);
3712 }
3713 if (check_krl) {
3714 do_check_krl(pw, print_fingerprint, argc, argv);
3715 return (0);
3716 }
3717 if (ca_key_path != NULL) {
3718 if (cert_key_id == NULL)
3719 fatal("Must specify key id (-I) when certifying");
3720 for (i = 0; i < nopts; i++)
3721 add_cert_option(opts[i]);
3722 do_ca_sign(pw, ca_key_path, prefer_agent,
3723 cert_serial, cert_serial_autoinc, argc, argv);
3724 }
3725 if (show_cert)
3726 do_show_cert(pw);
3727 if (delete_host || hash_hosts || find_host) {
3728 do_known_hosts(pw, rr_hostname, find_host,
3729 delete_host, hash_hosts);
3730 }
3731 if (pkcs11provider != NULL)
3732 do_download(pw);
3733 if (download_sk) {
3734 for (i = 0; i < nopts; i++) {
3735 if (strncasecmp(opts[i], "device=", 7) == 0) {
3736 sk_device = xstrdup(opts[i] + 7);
3737 } else {
3738 fatal("Option \"%s\" is unsupported for "
3739 "FIDO authenticator download", opts[i]);
3740 }
3741 }
3742 return do_download_sk(sk_provider, sk_device);
3743 }
3744 if (print_fingerprint || print_bubblebabble)
3745 do_fingerprint(pw);
3746 if (change_passphrase)
3747 do_change_passphrase(pw);
3748 if (change_comment)
3749 do_change_comment(pw, identity_comment);
3750 #ifdef WITH_OPENSSL
3751 if (convert_to)
3752 do_convert_to(pw);
3753 if (convert_from)
3754 do_convert_from(pw);
3755 #else /* WITH_OPENSSL */
3756 if (convert_to || convert_from)
3757 fatal("key conversion disabled at compile time");
3758 #endif /* WITH_OPENSSL */
3759 if (print_public)
3760 do_print_public(pw);
3761 if (rr_hostname != NULL) {
3762 unsigned int n = 0;
3763
3764 if (have_identity) {
3765 n = do_print_resource_record(pw, identity_file,
3766 rr_hostname, print_generic, opts, nopts);
3767 if (n == 0)
3768 fatal("%s: %s", identity_file, strerror(errno));
3769 exit(0);
3770 } else {
3771
3772 n += do_print_resource_record(pw,
3773 _PATH_HOST_RSA_KEY_FILE, rr_hostname,
3774 print_generic, opts, nopts);
3775 #ifdef WITH_DSA
3776 n += do_print_resource_record(pw,
3777 _PATH_HOST_DSA_KEY_FILE, rr_hostname,
3778 print_generic, opts, nopts);
3779 #endif
3780 n += do_print_resource_record(pw,
3781 _PATH_HOST_ECDSA_KEY_FILE, rr_hostname,
3782 print_generic, opts, nopts);
3783 n += do_print_resource_record(pw,
3784 _PATH_HOST_ED25519_KEY_FILE, rr_hostname,
3785 print_generic, opts, nopts);
3786 n += do_print_resource_record(pw,
3787 _PATH_HOST_XMSS_KEY_FILE, rr_hostname,
3788 print_generic, opts, nopts);
3789 if (n == 0)
3790 fatal("no keys found.");
3791 exit(0);
3792 }
3793 }
3794
3795 if (do_gen_candidates || do_screen_candidates) {
3796 if (argc <= 0)
3797 fatal("No output file specified");
3798 else if (argc > 1)
3799 fatal("Too many output files specified");
3800 }
3801 if (do_gen_candidates) {
3802 do_moduli_gen(argv[0], opts, nopts);
3803 return 0;
3804 }
3805 if (do_screen_candidates) {
3806 do_moduli_screen(argv[0], opts, nopts);
3807 return 0;
3808 }
3809
3810 if (gen_all_hostkeys) {
3811 do_gen_all_hostkeys(pw);
3812 return (0);
3813 }
3814
3815 if (key_type_name == NULL)
3816 key_type_name = DEFAULT_KEY_TYPE_NAME;
3817
3818 type = sshkey_type_from_name(key_type_name);
3819 type_bits_valid(type, key_type_name, &bits);
3820
3821 if (!quiet)
3822 printf("Generating public/private %s key pair.\n",
3823 key_type_name);
3824 switch (type) {
3825 case KEY_ECDSA_SK:
3826 case KEY_ED25519_SK:
3827 for (i = 0; i < nopts; i++) {
3828 if (strcasecmp(opts[i], "no-touch-required") == 0) {
3829 sk_flags &= ~SSH_SK_USER_PRESENCE_REQD;
3830 } else if (strcasecmp(opts[i], "verify-required") == 0) {
3831 sk_flags |= SSH_SK_USER_VERIFICATION_REQD;
3832 } else if (strcasecmp(opts[i], "resident") == 0) {
3833 sk_flags |= SSH_SK_RESIDENT_KEY;
3834 } else if (strncasecmp(opts[i], "device=", 7) == 0) {
3835 sk_device = xstrdup(opts[i] + 7);
3836 } else if (strncasecmp(opts[i], "user=", 5) == 0) {
3837 sk_user = xstrdup(opts[i] + 5);
3838 } else if (strncasecmp(opts[i], "challenge=", 10) == 0) {
3839 if ((r = sshbuf_load_file(opts[i] + 10,
3840 &challenge)) != 0) {
3841 fatal_r(r, "Unable to load FIDO "
3842 "enrollment challenge \"%s\"",
3843 opts[i] + 10);
3844 }
3845 } else if (strncasecmp(opts[i],
3846 "write-attestation=", 18) == 0) {
3847 sk_attestation_path = opts[i] + 18;
3848 } else if (strncasecmp(opts[i],
3849 "application=", 12) == 0) {
3850 sk_application = xstrdup(opts[i] + 12);
3851 if (strncmp(sk_application, "ssh:", 4) != 0) {
3852 fatal("FIDO application string must "
3853 "begin with \"ssh:\"");
3854 }
3855 } else {
3856 fatal("Option \"%s\" is unsupported for "
3857 "FIDO authenticator enrollment", opts[i]);
3858 }
3859 }
3860 if ((attest = sshbuf_new()) == NULL)
3861 fatal("sshbuf_new failed");
3862 r = 0;
3863 for (i = 0 ;;) {
3864 if (!quiet) {
3865 printf("You may need to touch your "
3866 "authenticator%s to authorize key "
3867 "generation.\n",
3868 r == 0 ? "" : " again");
3869 }
3870 fflush(stdout);
3871 r = sshsk_enroll(type, sk_provider, sk_device,
3872 sk_application == NULL ? "ssh:" : sk_application,
3873 sk_user, sk_flags, passphrase, challenge,
3874 &private, attest);
3875 if (r == 0)
3876 break;
3877 if (r == SSH_ERR_KEY_BAD_PERMISSIONS &&
3878 (sk_flags & SSH_SK_RESIDENT_KEY) != 0 &&
3879 (sk_flags & SSH_SK_FORCE_OPERATION) == 0 &&
3880 confirm_sk_overwrite(sk_application, sk_user)) {
3881 sk_flags |= SSH_SK_FORCE_OPERATION;
3882 continue;
3883 }
3884 if (r != SSH_ERR_KEY_WRONG_PASSPHRASE)
3885 fatal_r(r, "Key enrollment failed");
3886 else if (passphrase != NULL) {
3887 error("PIN incorrect");
3888 freezero(passphrase, strlen(passphrase));
3889 passphrase = NULL;
3890 }
3891 if (++i >= 3)
3892 fatal("Too many incorrect PINs");
3893 passphrase = read_passphrase("Enter PIN for "
3894 "authenticator: ", RP_ALLOW_STDIN);
3895 }
3896 if (passphrase != NULL) {
3897 freezero(passphrase, strlen(passphrase));
3898 passphrase = NULL;
3899 }
3900 break;
3901 default:
3902 if ((r = sshkey_generate(type, bits, &private)) != 0)
3903 fatal("sshkey_generate failed");
3904 break;
3905 }
3906 if ((r = sshkey_from_private(private, &public)) != 0)
3907 fatal_r(r, "sshkey_from_private");
3908
3909 if (!have_identity)
3910 ask_filename(pw, "Enter file in which to save the key");
3911
3912 /* Create ~/.ssh directory if it doesn't already exist. */
3913 hostfile_create_user_ssh_dir(identity_file, !quiet);
3914
3915 /* If the file already exists, ask the user to confirm. */
3916 if (!confirm_overwrite(identity_file))
3917 exit(1);
3918
3919 /* Determine the passphrase for the private key */
3920 passphrase = private_key_passphrase();
3921 if (identity_comment) {
3922 strlcpy(comment, identity_comment, sizeof(comment));
3923 } else {
3924 /* Create default comment field for the passphrase. */
3925 snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname);
3926 }
3927
3928 /* Save the key with the given passphrase and comment. */
3929 if ((r = sshkey_save_private(private, identity_file, passphrase,
3930 comment, private_key_format, openssh_format_cipher, rounds)) != 0) {
3931 error_r(r, "Saving key \"%s\" failed", identity_file);
3932 freezero(passphrase, strlen(passphrase));
3933 exit(1);
3934 }
3935 freezero(passphrase, strlen(passphrase));
3936 sshkey_free(private);
3937
3938 if (!quiet) {
3939 printf("Your identification has been saved in %s\n",
3940 identity_file);
3941 }
3942
3943 strlcat(identity_file, ".pub", sizeof(identity_file));
3944 if ((r = sshkey_save_public(public, identity_file, comment)) != 0)
3945 fatal_r(r, "Unable to save public key to %s", identity_file);
3946
3947 if (!quiet) {
3948 fp = sshkey_fingerprint(public, fingerprint_hash,
3949 SSH_FP_DEFAULT);
3950 ra = sshkey_fingerprint(public, fingerprint_hash,
3951 SSH_FP_RANDOMART);
3952 if (fp == NULL || ra == NULL)
3953 fatal("sshkey_fingerprint failed");
3954 printf("Your public key has been saved in %s\n",
3955 identity_file);
3956 printf("The key fingerprint is:\n");
3957 printf("%s %s\n", fp, comment);
3958 printf("The key's randomart image is:\n");
3959 printf("%s\n", ra);
3960 free(ra);
3961 free(fp);
3962 }
3963
3964 if (sk_attestation_path != NULL)
3965 save_attestation(attest, sk_attestation_path);
3966
3967 sshbuf_free(attest);
3968 sshkey_free(public);
3969
3970 exit(0);
3971 }
3972