1 /* $OpenBSD: ssh-keygen.c,v 1.175 2009/08/27 17:33:49 djm Exp $ */
2 /*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, 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 <sys/param.h>
16 #include <sys/socket.h>
17 #include <sys/stat.h>
18
19 #include <openssl/evp.h>
20 #include <openssl/pem.h>
21 #include <openssl/err.h>
22
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <pwd.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30
31 #include "xmalloc.h"
32 #include "key.h"
33 #include "rsa.h"
34 #include "authfile.h"
35 #include "uuencode.h"
36 #include "buffer.h"
37 #include "pathnames.h"
38 #include "log.h"
39 #include "misc.h"
40 #include "match.h"
41 #include "hostfile.h"
42 #include "dns.h"
43
44 #ifdef SMARTCARD
45 #include "scard.h"
46 #endif
47
48 __RCSID("$MirOS: src/usr.bin/ssh/ssh-keygen.c,v 1.24 2014/03/12 23:19:37 tg Exp $");
49
50 /* Number of bits in the RSA/DSA key. This value can be set on the command line. */
51 #define DEFAULT_BITS 2048
52 #define DEFAULT_BITS_DSA 1024
53 u_int32_t bits = 0;
54
55 /*
56 * Flag indicating that we just want to change the passphrase. This can be
57 * set on the command line.
58 */
59 int change_passphrase = 0;
60
61 /*
62 * Flag indicating that we just want to change the comment. This can be set
63 * on the command line.
64 */
65 int change_comment = 0;
66
67 int quiet = 0;
68
69 int log_level = SYSLOG_LEVEL_INFO;
70
71 /* Flag indicating that we want to hash a known_hosts file */
72 int hash_hosts = 0;
73 /* Flag indicating that we want lookup a host in known_hosts file */
74 int find_host = 0;
75 /* Flag indicating that we want to delete a host from a known_hosts file */
76 int delete_host = 0;
77
78 /* Flag indicating that we just want to see the key fingerprint */
79 int print_fingerprint = 0;
80 int print_bubblebabble = 0;
81
82 /* The identity file name, given on the command line or entered by the user. */
83 char identity_file[1024];
84 int have_identity = 0;
85
86 /* This is set to the passphrase if given on the command line. */
87 char *identity_passphrase = NULL;
88
89 /* This is set to the new passphrase if given on the command line. */
90 char *identity_new_passphrase = NULL;
91
92 /* This is set to the new comment if given on the command line. */
93 char *identity_comment = NULL;
94
95 /* Dump public key file in format used by real and the original SSH 2 */
96 int convert_to_ssh2 = 0;
97 int convert_from_ssh2 = 0;
98 int print_public = 0;
99 int print_generic = 0;
100
101 /* Dump public key file in format used by the OpenSSL tool */
102 int convert_to_ossl = 0;
103 int convert_from_ossl = 0;
104
105 const char *key_type_name = NULL;
106
107 /* argv0 */
108 extern char *__progname;
109
110 char hostname[MAXHOSTNAMELEN];
111
112 /* moduli.c */
113 int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *);
114 int prime_test(FILE *, FILE *, u_int32_t, u_int32_t);
115
116 static void
ask_filename(struct passwd * pw,const char * prompt)117 ask_filename(struct passwd *pw, const char *prompt)
118 {
119 char buf[1024];
120 const char *name = NULL;
121
122 if (key_type_name == NULL)
123 name = _PATH_SSH_CLIENT_ID_RSA;
124 else {
125 switch (key_type_from_name((char *)key_type_name)) {
126 case KEY_RSA1:
127 name = _PATH_SSH_CLIENT_IDENTITY;
128 break;
129 case KEY_DSA:
130 name = _PATH_SSH_CLIENT_ID_DSA;
131 break;
132 case KEY_RSA:
133 name = _PATH_SSH_CLIENT_ID_RSA;
134 break;
135 default:
136 fprintf(stderr, "bad key type\n");
137 exit(1);
138 break;
139 }
140 }
141 snprintf(identity_file, sizeof(identity_file), "%s/%s", pw->pw_dir, name);
142 fprintf(stderr, "%s (%s): ", prompt, identity_file);
143 if (fgets(buf, sizeof(buf), stdin) == NULL)
144 exit(1);
145 buf[strcspn(buf, "\n")] = '\0';
146 if (strcmp(buf, "") != 0)
147 strlcpy(identity_file, buf, sizeof(identity_file));
148 have_identity = 1;
149 }
150
151 static Key *
load_identity(char * filename)152 load_identity(char *filename)
153 {
154 char *pass;
155 Key *prv;
156
157 prv = key_load_private(filename, "", NULL);
158 if (prv == NULL) {
159 if (identity_passphrase)
160 pass = xstrdup(identity_passphrase);
161 else
162 pass = read_passphrase("Enter passphrase: ",
163 RP_ALLOW_STDIN);
164 prv = key_load_private(filename, pass, NULL);
165 memset(pass, 0, strlen(pass));
166 xfree(pass);
167 }
168 return prv;
169 }
170
171 #define SSH_COM_PUBLIC_BEGIN "---- BEGIN SSH2 PUBLIC KEY ----"
172 #define SSH_COM_PUBLIC_END "---- END SSH2 PUBLIC KEY ----"
173 #define SSH_COM_PRIVATE_BEGIN "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"
174 #define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb
175
176 static void
do_convert_to_ssh2(struct passwd * pw)177 do_convert_to_ssh2(struct passwd *pw)
178 {
179 Key *k;
180 u_int len;
181 u_char *blob;
182 struct stat st;
183
184 if (!have_identity)
185 ask_filename(pw, "Enter file in which the key is");
186 if (stat(identity_file, &st) < 0) {
187 perror(identity_file);
188 exit(1);
189 }
190 if ((k = key_load_public(identity_file, NULL)) == NULL) {
191 if ((k = load_identity(identity_file)) == NULL) {
192 fprintf(stderr, "load failed\n");
193 exit(1);
194 }
195 }
196 if (k->type == KEY_RSA1) {
197 fprintf(stderr, "version 1 keys are not supported\n");
198 exit(1);
199 }
200 if (key_to_blob(k, &blob, &len) <= 0) {
201 fprintf(stderr, "key_to_blob failed\n");
202 exit(1);
203 }
204 fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN);
205 fprintf(stdout,
206 "Comment: \"%u-bit %s, converted from OpenSSH by %s@%s\"\n",
207 key_size(k), key_type(k),
208 pw->pw_name, hostname);
209 dump_base64(stdout, blob, len);
210 fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END);
211 key_free(k);
212 xfree(blob);
213 exit(0);
214 }
215
216 static void
do_convert_to_ossl(struct passwd * pw)217 do_convert_to_ossl(struct passwd *pw)
218 {
219 Key *k;
220 struct stat st;
221 int rv;
222
223 if (!have_identity)
224 ask_filename(pw, "Enter file in which the key is");
225 if (stat(identity_file, &st) < 0) {
226 perror(identity_file);
227 exit(1);
228 }
229 if ((k = key_load_public(identity_file, NULL)) == NULL) {
230 if ((k = load_identity(identity_file)) == NULL) {
231 fprintf(stderr, "load failed\n");
232 exit(1);
233 }
234 }
235 if (k->type == KEY_RSA1) {
236 fprintf(stderr, "version 1 keys are not supported\n");
237 exit(1);
238 }
239 if ((rv = !PEM_write_RSA_PUBKEY(stdout, k->rsa)))
240 fprintf(stderr, "error during key conversion\n");
241 key_free(k);
242 exit(rv);
243 }
244
245 static void
buffer_get_bignum_bits(Buffer * b,BIGNUM * value)246 buffer_get_bignum_bits(Buffer *b, BIGNUM *value)
247 {
248 u_int bignum_bits = buffer_get_int(b);
249 u_int bytes = (bignum_bits + 7) / 8;
250
251 if (buffer_len(b) < bytes)
252 fatal("buffer_get_bignum_bits: input buffer too small: "
253 "need %d have %d", bytes, buffer_len(b));
254 if (BN_bin2bn(buffer_ptr(b), bytes, value) == NULL)
255 fatal("buffer_get_bignum_bits: BN_bin2bn failed");
256 buffer_consume(b, bytes);
257 }
258
259 static Key *
do_convert_private_ssh2_from_blob(u_char * blob,u_int blen)260 do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
261 {
262 Buffer b;
263 Key *key = NULL;
264 char *type, *cipher;
265 u_char *sig, data[] = "abcde12345";
266 int magic, rlen, ktype, i1, i2, i3, i4;
267 u_int slen;
268 u_long e;
269
270 buffer_init(&b);
271 buffer_append(&b, blob, blen);
272
273 magic = buffer_get_int(&b);
274 if (magic != SSH_COM_PRIVATE_KEY_MAGIC) {
275 error("bad magic 0x%x != 0x%x", magic, SSH_COM_PRIVATE_KEY_MAGIC);
276 buffer_free(&b);
277 return NULL;
278 }
279 i1 = buffer_get_int(&b);
280 type = buffer_get_string(&b, NULL);
281 cipher = buffer_get_string(&b, NULL);
282 i2 = buffer_get_int(&b);
283 i3 = buffer_get_int(&b);
284 i4 = buffer_get_int(&b);
285 debug("ignore (%d %d %d %d)", i1, i2, i3, i4);
286 if (strcmp(cipher, "none") != 0) {
287 error("unsupported cipher %s", cipher);
288 xfree(cipher);
289 buffer_free(&b);
290 xfree(type);
291 return NULL;
292 }
293 xfree(cipher);
294
295 if (strstr(type, "dsa")) {
296 ktype = KEY_DSA;
297 } else if (strstr(type, "rsa")) {
298 ktype = KEY_RSA;
299 } else {
300 buffer_free(&b);
301 xfree(type);
302 return NULL;
303 }
304 key = key_new_private(ktype);
305 xfree(type);
306
307 switch (key->type) {
308 case KEY_DSA:
309 buffer_get_bignum_bits(&b, key->dsa->p);
310 buffer_get_bignum_bits(&b, key->dsa->g);
311 buffer_get_bignum_bits(&b, key->dsa->q);
312 buffer_get_bignum_bits(&b, key->dsa->pub_key);
313 buffer_get_bignum_bits(&b, key->dsa->priv_key);
314 break;
315 case KEY_RSA:
316 e = buffer_get_char(&b);
317 debug("e %lx", e);
318 if (e < 30) {
319 e <<= 8;
320 e += buffer_get_char(&b);
321 debug("e %lx", e);
322 e <<= 8;
323 e += buffer_get_char(&b);
324 debug("e %lx", e);
325 }
326 if (!BN_set_word(key->rsa->e, e)) {
327 buffer_free(&b);
328 key_free(key);
329 return NULL;
330 }
331 buffer_get_bignum_bits(&b, key->rsa->d);
332 buffer_get_bignum_bits(&b, key->rsa->n);
333 buffer_get_bignum_bits(&b, key->rsa->iqmp);
334 buffer_get_bignum_bits(&b, key->rsa->q);
335 buffer_get_bignum_bits(&b, key->rsa->p);
336 rsa_generate_additional_parameters(key->rsa);
337 break;
338 }
339 rlen = buffer_len(&b);
340 if (rlen != 0)
341 error("do_convert_private_ssh2_from_blob: "
342 "remaining bytes in key blob %d", rlen);
343 buffer_free(&b);
344
345 /* try the key */
346 key_sign(key, &sig, &slen, data, sizeof(data));
347 key_verify(key, sig, slen, data, sizeof(data));
348 xfree(sig);
349 return key;
350 }
351
352 static int
get_line(FILE * fp,char * line,size_t len)353 get_line(FILE *fp, char *line, size_t len)
354 {
355 int c;
356 size_t pos = 0;
357
358 line[0] = '\0';
359 while ((c = fgetc(fp)) != EOF) {
360 if (pos >= len - 1) {
361 fprintf(stderr, "input line too long.\n");
362 exit(1);
363 }
364 switch (c) {
365 case '\r':
366 c = fgetc(fp);
367 if (c != EOF && c != '\n' && ungetc(c, fp) == EOF) {
368 fprintf(stderr, "unget: %s\n", strerror(errno));
369 exit(1);
370 }
371 return pos;
372 case '\n':
373 return pos;
374 }
375 line[pos++] = c;
376 line[pos] = '\0';
377 }
378 /* We reached EOF */
379 return -1;
380 }
381
382 static void
do_convert_from_ssh2(struct passwd * pw)383 do_convert_from_ssh2(struct passwd *pw)
384 {
385 Key *k;
386 int blen;
387 u_int len;
388 char line[1024];
389 u_char blob[8096];
390 char encoded[8096];
391 struct stat st;
392 int escaped = 0, private = 0, ok;
393 FILE *fp;
394
395 if (!have_identity)
396 ask_filename(pw, "Enter file in which the key is");
397 if (stat(identity_file, &st) < 0) {
398 perror(identity_file);
399 exit(1);
400 }
401 fp = fopen(identity_file, "r");
402 if (fp == NULL) {
403 perror(identity_file);
404 exit(1);
405 }
406 encoded[0] = '\0';
407 while ((blen = get_line(fp, line, sizeof(line))) != -1) {
408 if (line[blen - 1] == '\\')
409 escaped++;
410 if (strncmp(line, "----", 4) == 0 ||
411 strstr(line, ": ") != NULL) {
412 if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL)
413 private = 1;
414 if (strstr(line, " END ") != NULL) {
415 break;
416 }
417 /* fprintf(stderr, "ignore: %s", line); */
418 continue;
419 }
420 if (escaped) {
421 escaped--;
422 /* fprintf(stderr, "escaped: %s", line); */
423 continue;
424 }
425 strlcat(encoded, line, sizeof(encoded));
426 }
427 len = strlen(encoded);
428 if (((len % 4) == 3) &&
429 (encoded[len-1] == '=') &&
430 (encoded[len-2] == '=') &&
431 (encoded[len-3] == '='))
432 encoded[len-3] = '\0';
433 blen = uudecode(encoded, blob, sizeof(blob));
434 if (blen < 0) {
435 fprintf(stderr, "uudecode failed.\n");
436 exit(1);
437 }
438 k = private ?
439 do_convert_private_ssh2_from_blob(blob, blen) :
440 key_from_blob(blob, blen);
441 if (k == NULL) {
442 fprintf(stderr, "decode blob failed.\n");
443 exit(1);
444 }
445 ok = private ?
446 (k->type == KEY_DSA ?
447 PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, NULL, 0, NULL, NULL) :
448 PEM_write_RSAPrivateKey(stdout, k->rsa, NULL, NULL, 0, NULL, NULL)) :
449 key_write(k, stdout);
450 if (!ok) {
451 fprintf(stderr, "key write failed\n");
452 exit(1);
453 }
454 key_free(k);
455 if (!private)
456 fprintf(stdout, "\n");
457 fclose(fp);
458 exit(0);
459 }
460
461 static __dead void
do_convert_from_ossl(struct passwd * pw)462 do_convert_from_ossl(struct passwd *pw)
463 {
464 Key *k;
465 struct stat st;
466 FILE *fp;
467 X509 *x;
468
469 if (!have_identity)
470 ask_filename(pw, "Enter file in which the key is");
471 if (stat(identity_file, &st) < 0) {
472 perror(identity_file);
473 exit(1);
474 }
475 fp = fopen(identity_file, "r");
476 if (fp == NULL) {
477 perror(identity_file);
478 exit(1);
479 }
480 k = key_new_private(KEY_RSA);
481 if (k != NULL) {
482 RSA_free(k->rsa);
483 k->rsa = NULL;
484 x = PEM_read_X509(fp, NULL, NULL, NULL);
485 if (x != NULL) {
486 EVP_PKEY *pkey;
487 if ((pkey = X509_get_pubkey(x)) != NULL)
488 k->rsa = pkey->pkey.rsa;
489 }
490 if (k->rsa == NULL) {
491 rewind(fp);
492 k->rsa = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
493 }
494 }
495 if (k == NULL || k->rsa == NULL) {
496 unsigned long e;
497 ERR_load_crypto_strings();
498 while ((e = ERR_get_error()))
499 fprintf(stderr, "%s\n", ERR_error_string(e, NULL));
500 fprintf(stderr, "decode blob failed.\n");
501 exit(1);
502 }
503 if (!key_write(k, stdout)) {
504 fprintf(stderr, "key write failed");
505 exit(1);
506 }
507 key_free(k);
508 fprintf(stdout, "\n");
509 fclose(fp);
510 exit(0);
511 }
512
513 static void
do_print_public(struct passwd * pw)514 do_print_public(struct passwd *pw)
515 {
516 Key *prv;
517 struct stat st;
518
519 if (!have_identity)
520 ask_filename(pw, "Enter file in which the key is");
521 if (stat(identity_file, &st) < 0) {
522 perror(identity_file);
523 exit(1);
524 }
525 prv = load_identity(identity_file);
526 if (prv == NULL) {
527 fprintf(stderr, "load failed\n");
528 exit(1);
529 }
530 if (!key_write(prv, stdout))
531 fprintf(stderr, "key_write failed");
532 key_free(prv);
533 fprintf(stdout, "\n");
534 exit(0);
535 }
536
537 #ifdef SMARTCARD
538 static void
do_upload(struct passwd * pw,const char * sc_reader_id)539 do_upload(struct passwd *pw, const char *sc_reader_id)
540 {
541 Key *prv = NULL;
542 struct stat st;
543 int ret;
544
545 if (!have_identity)
546 ask_filename(pw, "Enter file in which the key is");
547 if (stat(identity_file, &st) < 0) {
548 perror(identity_file);
549 exit(1);
550 }
551 prv = load_identity(identity_file);
552 if (prv == NULL) {
553 error("load failed");
554 exit(1);
555 }
556 ret = sc_put_key(prv, sc_reader_id);
557 key_free(prv);
558 if (ret < 0)
559 exit(1);
560 logit("loading key done");
561 exit(0);
562 }
563
564 static void
do_download(struct passwd * pw,const char * sc_reader_id)565 do_download(struct passwd *pw, const char *sc_reader_id)
566 {
567 Key **keys = NULL;
568 int i;
569
570 keys = sc_get_keys(sc_reader_id, NULL);
571 if (keys == NULL)
572 fatal("cannot read public key from smartcard");
573 for (i = 0; keys[i]; i++) {
574 key_write(keys[i], stdout);
575 key_free(keys[i]);
576 fprintf(stdout, "\n");
577 }
578 xfree(keys);
579 exit(0);
580 }
581 #endif /* SMARTCARD */
582
583 static __dead void
do_fingerprint(struct passwd * pw)584 do_fingerprint(struct passwd *pw)
585 {
586 FILE *f;
587 Key *public;
588 char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra;
589 int i, skip = 0, num = 0, invalid = 1;
590 enum fp_rep rep;
591 enum fp_type fptype;
592 struct stat st;
593
594 fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
595 rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
596
597 if (!have_identity)
598 ask_filename(pw, "Enter file in which the key is");
599 if (stat(identity_file, &st) < 0) {
600 perror(identity_file);
601 exit(1);
602 }
603 public = key_load_public(identity_file, &comment);
604 if (public != NULL) {
605 fp = key_fingerprint(public, fptype, rep);
606 ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
607 printf("%u %s %s (%s)\n", key_size(public), fp, comment,
608 key_type(public));
609 if (log_level >= SYSLOG_LEVEL_VERBOSE)
610 printf("%s\n", ra);
611 key_free(public);
612 xfree(comment);
613 xfree(ra);
614 xfree(fp);
615 exit(0);
616 }
617 if (comment) {
618 xfree(comment);
619 comment = NULL;
620 }
621
622 f = fopen(identity_file, "r");
623 if (f != NULL) {
624 while (fgets(line, sizeof(line), f)) {
625 if ((cp = strchr(line, '\n')) == NULL) {
626 error("line %d too long: %.40s...",
627 num + 1, line);
628 skip = 1;
629 continue;
630 }
631 num++;
632 if (skip) {
633 skip = 0;
634 continue;
635 }
636 *cp = '\0';
637
638 /* Skip leading whitespace, empty and comment lines. */
639 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
640 ;
641 if (!*cp || *cp == '\n' || *cp == '#')
642 continue;
643 i = strtol(cp, &ep, 10);
644 if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) {
645 int quoted = 0;
646 comment = cp;
647 for (; *cp && (quoted || (*cp != ' ' &&
648 *cp != '\t')); cp++) {
649 if (*cp == '\\' && cp[1] == '"')
650 cp++; /* Skip both */
651 else if (*cp == '"')
652 quoted = !quoted;
653 }
654 if (!*cp)
655 continue;
656 *cp++ = '\0';
657 }
658 ep = cp;
659 public = key_new(KEY_RSA1);
660 if (key_read(public, &cp) != 1) {
661 cp = ep;
662 key_free(public);
663 public = key_new(KEY_UNSPEC);
664 if (key_read(public, &cp) != 1) {
665 key_free(public);
666 continue;
667 }
668 }
669 comment = *cp ? cp : comment;
670 fp = key_fingerprint(public, fptype, rep);
671 ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
672 printf("%u %s %s (%s)\n", key_size(public), fp,
673 comment ? comment : "no comment", key_type(public));
674 if (log_level >= SYSLOG_LEVEL_VERBOSE)
675 printf("%s\n", ra);
676 xfree(ra);
677 xfree(fp);
678 key_free(public);
679 invalid = 0;
680 }
681 fclose(f);
682 }
683 if (invalid) {
684 printf("%s is not a public key file.\n", identity_file);
685 exit(1);
686 }
687 exit(0);
688 }
689
690 static void
print_host(FILE * f,const char * name,Key * public,int hash)691 print_host(FILE *f, const char *name, Key *public, int hash)
692 {
693 if (print_fingerprint) {
694 enum fp_rep rep;
695 enum fp_type fptype;
696 char *fp, *ra;
697
698 fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
699 rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
700 fp = key_fingerprint(public, fptype, rep);
701 ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
702 printf("%u %s %s (%s)\n", key_size(public), fp, name,
703 key_type(public));
704 if (log_level >= SYSLOG_LEVEL_VERBOSE)
705 printf("%s\n", ra);
706 xfree(ra);
707 xfree(fp);
708 } else {
709 if (hash && (name = host_hash(name, NULL, 0)) == NULL)
710 fatal("hash_host failed");
711 fprintf(f, "%s ", name);
712 if (!key_write(public, f))
713 fatal("key_write failed");
714 fprintf(f, "\n");
715 }
716 }
717
718 static __dead void
do_known_hosts(struct passwd * pw,const char * name)719 do_known_hosts(struct passwd *pw, const char *name)
720 {
721 FILE *in, *out = stdout;
722 Key *public;
723 char *cp, *cp2, *kp, *kp2;
724 char line[16*1024], tmp[MAXPATHLEN], old[MAXPATHLEN];
725 int c, skip = 0, inplace = 0, num = 0, invalid = 0, has_unhashed = 0;
726
727 if (!have_identity) {
728 cp = tilde_expand_filename(
729 #ifdef _PATH_SSH_ROOT_HOSTFILE
730 (!pw->pw_dir || !pw->pw_dir[0] || (pw->pw_dir[0] == '/' &&
731 !pw->pw_dir[1])) ? _PATH_SSH_ROOT_HOSTFILE :
732 #endif
733 _PATH_SSH_USER_HOSTFILE, pw->pw_uid);
734 if (strlcpy(identity_file, cp, sizeof(identity_file)) >=
735 sizeof(identity_file))
736 fatal("Specified known hosts path too long");
737 xfree(cp);
738 have_identity = 1;
739 }
740 if ((in = fopen(identity_file, "r")) == NULL)
741 fatal("fopen: %s", strerror(errno));
742
743 /*
744 * Find hosts goes to stdout, hash and deletions happen in-place
745 * A corner case is ssh-keygen -HF foo, which should go to stdout
746 */
747 if (!find_host && (hash_hosts || delete_host)) {
748 if (strlcpy(tmp, identity_file, sizeof(tmp)) >= sizeof(tmp) ||
749 strlcat(tmp, ".XXXXXXXXXX", sizeof(tmp)) >= sizeof(tmp) ||
750 strlcpy(old, identity_file, sizeof(old)) >= sizeof(old) ||
751 strlcat(old, ".old", sizeof(old)) >= sizeof(old))
752 fatal("known_hosts path too long");
753 umask(077);
754 if ((c = mkstemp(tmp)) == -1)
755 fatal("mkstemp: %s", strerror(errno));
756 if ((out = fdopen(c, "w")) == NULL) {
757 c = errno;
758 unlink(tmp);
759 fatal("fdopen: %s", strerror(c));
760 }
761 inplace = 1;
762 }
763
764 while (fgets(line, sizeof(line), in)) {
765 if ((cp = strchr(line, '\n')) == NULL) {
766 error("line %d too long: %.40s...", num + 1, line);
767 skip = 1;
768 invalid = 1;
769 continue;
770 }
771 num++;
772 if (skip) {
773 skip = 0;
774 continue;
775 }
776 *cp = '\0';
777
778 /* Skip leading whitespace, empty and comment lines. */
779 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
780 ;
781 if (!*cp || *cp == '\n' || *cp == '#') {
782 if (inplace)
783 fprintf(out, "%s\n", cp);
784 continue;
785 }
786 /* Find the end of the host name portion. */
787 for (kp = cp; *kp && *kp != ' ' && *kp != '\t'; kp++)
788 ;
789 if (*kp == '\0' || *(kp + 1) == '\0') {
790 error("line %d missing key: %.40s...",
791 num, line);
792 invalid = 1;
793 continue;
794 }
795 *kp++ = '\0';
796 kp2 = kp;
797
798 public = key_new(KEY_RSA1);
799 if (key_read(public, &kp) != 1) {
800 kp = kp2;
801 key_free(public);
802 public = key_new(KEY_UNSPEC);
803 if (key_read(public, &kp) != 1) {
804 error("line %d invalid key: %.40s...",
805 num, line);
806 key_free(public);
807 invalid = 1;
808 continue;
809 }
810 }
811
812 if (*cp == HASH_DELIM) {
813 if (find_host || delete_host) {
814 cp2 = host_hash(name, cp, strlen(cp));
815 if (cp2 == NULL) {
816 error("line %d: invalid hashed "
817 "name: %.64s...", num, line);
818 invalid = 1;
819 continue;
820 }
821 c = (strcmp(cp2, cp) == 0);
822 if (find_host && c) {
823 printf("# Host %s found: "
824 "line %d type %s\n", name,
825 num, key_type(public));
826 print_host(out, cp, public, 0);
827 }
828 if (delete_host && !c)
829 print_host(out, cp, public, 0);
830 } else if (hash_hosts)
831 print_host(out, cp, public, 0);
832 } else {
833 if (find_host || delete_host) {
834 c = (match_hostname(name, cp,
835 strlen(cp)) == 1);
836 if (find_host && c) {
837 printf("# Host %s found: "
838 "line %d type %s\n", name,
839 num, key_type(public));
840 print_host(out, name, public,
841 hash_hosts);
842 }
843 if (delete_host && !c)
844 print_host(out, cp, public, 0);
845 } else if (hash_hosts) {
846 for (cp2 = strsep(&cp, ",");
847 cp2 != NULL && *cp2 != '\0';
848 cp2 = strsep(&cp, ",")) {
849 if (strcspn(cp2, "*?!") != strlen(cp2))
850 fprintf(stderr, "Warning: "
851 "ignoring host name with "
852 "metacharacters: %.64s\n",
853 cp2);
854 else
855 print_host(out, cp2, public, 1);
856 }
857 has_unhashed = 1;
858 }
859 }
860 key_free(public);
861 }
862 fclose(in);
863
864 if (invalid) {
865 fprintf(stderr, "%s is not a valid known_hosts file.\n",
866 identity_file);
867 if (inplace) {
868 fprintf(stderr, "Not replacing existing known_hosts "
869 "file because of errors\n");
870 fclose(out);
871 unlink(tmp);
872 }
873 exit(1);
874 }
875
876 if (inplace) {
877 fclose(out);
878
879 /* Backup existing file */
880 if (unlink(old) == -1 && errno != ENOENT)
881 fatal("unlink %.100s: %s", old, strerror(errno));
882 if (link(identity_file, old) == -1)
883 fatal("link %.100s to %.100s: %s", identity_file, old,
884 strerror(errno));
885 /* Move new one into place */
886 if (rename(tmp, identity_file) == -1) {
887 error("rename\"%s\" to \"%s\": %s", tmp, identity_file,
888 strerror(errno));
889 unlink(tmp);
890 unlink(old);
891 exit(1);
892 }
893
894 fprintf(stderr, "%s updated.\n", identity_file);
895 fprintf(stderr, "Original contents retained as %s\n", old);
896 if (has_unhashed) {
897 fprintf(stderr, "WARNING: %s contains unhashed "
898 "entries\n", old);
899 fprintf(stderr, "Delete this file to ensure privacy "
900 "of hostnames\n");
901 }
902 }
903
904 exit(0);
905 }
906
907 /*
908 * Perform changing a passphrase. The argument is the passwd structure
909 * for the current user.
910 */
911 static __dead void
do_change_passphrase(struct passwd * pw)912 do_change_passphrase(struct passwd *pw)
913 {
914 char *comment;
915 char *old_passphrase, *passphrase1, *passphrase2;
916 struct stat st;
917 Key *private;
918
919 if (!have_identity)
920 ask_filename(pw, "Enter file in which the key is");
921 if (stat(identity_file, &st) < 0) {
922 perror(identity_file);
923 exit(1);
924 }
925 /* Try to load the file with empty passphrase. */
926 private = key_load_private(identity_file, "", &comment);
927 if (private == NULL) {
928 if (identity_passphrase)
929 old_passphrase = xstrdup(identity_passphrase);
930 else
931 old_passphrase =
932 read_passphrase("Enter old passphrase: ",
933 RP_ALLOW_STDIN);
934 private = key_load_private(identity_file, old_passphrase,
935 &comment);
936 memset(old_passphrase, 0, strlen(old_passphrase));
937 xfree(old_passphrase);
938 if (private == NULL) {
939 printf("Bad passphrase.\n");
940 exit(1);
941 }
942 }
943 printf("Key has comment '%s'\n", comment);
944
945 /* Ask the new passphrase (twice). */
946 if (identity_new_passphrase) {
947 passphrase1 = xstrdup(identity_new_passphrase);
948 passphrase2 = NULL;
949 } else {
950 passphrase1 =
951 read_passphrase("Enter new passphrase (empty for no "
952 "passphrase): ", RP_ALLOW_STDIN);
953 passphrase2 = read_passphrase("Enter same passphrase again: ",
954 RP_ALLOW_STDIN);
955
956 /* Verify that they are the same. */
957 if (strcmp(passphrase1, passphrase2) != 0) {
958 memset(passphrase1, 0, strlen(passphrase1));
959 memset(passphrase2, 0, strlen(passphrase2));
960 xfree(passphrase1);
961 xfree(passphrase2);
962 printf("Pass phrases do not match. Try again.\n");
963 exit(1);
964 }
965 /* Destroy the other copy. */
966 memset(passphrase2, 0, strlen(passphrase2));
967 xfree(passphrase2);
968 }
969
970 /* Save the file using the new passphrase. */
971 if (!key_save_private(private, identity_file, passphrase1, comment)) {
972 printf("Saving the key failed: %s.\n", identity_file);
973 memset(passphrase1, 0, strlen(passphrase1));
974 xfree(passphrase1);
975 key_free(private);
976 xfree(comment);
977 exit(1);
978 }
979 /* Destroy the passphrase and the copy of the key in memory. */
980 memset(passphrase1, 0, strlen(passphrase1));
981 xfree(passphrase1);
982 key_free(private); /* Destroys contents */
983 xfree(comment);
984
985 printf("Your identification has been saved with the new passphrase.\n");
986 exit(0);
987 }
988
989 /*
990 * Print the SSHFP RR.
991 */
992 static int
do_print_resource_record(struct passwd * pw,const char * fname,const char * hname)993 do_print_resource_record(struct passwd *pw, const char *fname,
994 const char *hname)
995 {
996 Key *public;
997 char *comment = NULL;
998 struct stat st;
999
1000 if (fname == NULL)
1001 ask_filename(pw, "Enter file in which the key is");
1002 if (stat(fname, &st) < 0) {
1003 if (errno == ENOENT)
1004 return 0;
1005 perror(fname);
1006 exit(1);
1007 }
1008 public = key_load_public(fname, &comment);
1009 if (public != NULL) {
1010 export_dns_rr(hname, public, stdout, print_generic);
1011 key_free(public);
1012 xfree(comment);
1013 return 1;
1014 }
1015 if (comment)
1016 xfree(comment);
1017
1018 printf("failed to read v2 public key from %s.\n", fname);
1019 exit(1);
1020 }
1021
1022 /*
1023 * Change the comment of a private key file.
1024 */
1025 static __dead void
do_change_comment(struct passwd * pw)1026 do_change_comment(struct passwd *pw)
1027 {
1028 char new_comment[1024], *comment, *passphrase;
1029 Key *private;
1030 Key *public;
1031 struct stat st;
1032 FILE *f;
1033 int fd;
1034
1035 if (!have_identity)
1036 ask_filename(pw, "Enter file in which the key is");
1037 if (stat(identity_file, &st) < 0) {
1038 perror(identity_file);
1039 exit(1);
1040 }
1041 private = key_load_private(identity_file, "", &comment);
1042 if (private == NULL) {
1043 if (identity_passphrase)
1044 passphrase = xstrdup(identity_passphrase);
1045 else if (identity_new_passphrase)
1046 passphrase = xstrdup(identity_new_passphrase);
1047 else
1048 passphrase = read_passphrase("Enter passphrase: ",
1049 RP_ALLOW_STDIN);
1050 /* Try to load using the passphrase. */
1051 private = key_load_private(identity_file, passphrase, &comment);
1052 if (private == NULL) {
1053 memset(passphrase, 0, strlen(passphrase));
1054 xfree(passphrase);
1055 printf("Bad passphrase.\n");
1056 exit(1);
1057 }
1058 } else {
1059 passphrase = xstrdup("");
1060 }
1061 if (private->type != KEY_RSA1) {
1062 fprintf(stderr, "Comments are only supported for RSA1 keys.\n");
1063 key_free(private);
1064 exit(1);
1065 }
1066 printf("Key now has comment '%s'\n", comment);
1067
1068 if (identity_comment) {
1069 strlcpy(new_comment, identity_comment, sizeof(new_comment));
1070 } else {
1071 printf("Enter new comment: ");
1072 fflush(stdout);
1073 if (!fgets(new_comment, sizeof(new_comment), stdin)) {
1074 memset(passphrase, 0, strlen(passphrase));
1075 key_free(private);
1076 exit(1);
1077 }
1078 new_comment[strcspn(new_comment, "\n")] = '\0';
1079 }
1080
1081 /* Save the file using the new passphrase. */
1082 if (!key_save_private(private, identity_file, passphrase, new_comment)) {
1083 printf("Saving the key failed: %s.\n", identity_file);
1084 memset(passphrase, 0, strlen(passphrase));
1085 xfree(passphrase);
1086 key_free(private);
1087 xfree(comment);
1088 exit(1);
1089 }
1090 memset(passphrase, 0, strlen(passphrase));
1091 xfree(passphrase);
1092 public = key_from_private(private);
1093 key_free(private);
1094
1095 strlcat(identity_file, ".pub", sizeof(identity_file));
1096 fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
1097 if (fd == -1) {
1098 printf("Could not save your public key in %s\n", identity_file);
1099 exit(1);
1100 }
1101 f = fdopen(fd, "w");
1102 if (f == NULL) {
1103 printf("fdopen %s failed\n", identity_file);
1104 exit(1);
1105 }
1106 if (!key_write(public, f))
1107 fprintf(stderr, "write key failed\n");
1108 key_free(public);
1109 fprintf(f, " %s\n", new_comment);
1110 fclose(f);
1111
1112 xfree(comment);
1113
1114 printf("The comment in your key file has been changed.\n");
1115 exit(0);
1116 }
1117
1118 static __dead void
usage(void)1119 usage(void)
1120 {
1121 fprintf(stderr, "usage: %s [options]\n", __progname);
1122 fprintf(stderr, "Options:\n");
1123 fprintf(stderr, " -a trials Number of trials for screening DH-GEX moduli.\n");
1124 fprintf(stderr, " -B Show bubblebabble digest of key file.\n");
1125 fprintf(stderr, " -b bits Number of bits in the key to create.\n");
1126 fprintf(stderr, " -C comment Provide new comment.\n");
1127 fprintf(stderr, " -c Change comment in private and public key files.\n");
1128 #ifdef SMARTCARD
1129 fprintf(stderr, " -D reader Download public key from smartcard.\n");
1130 #endif /* SMARTCARD */
1131 fprintf(stderr, " -E Convert OpenSSH to OpenSSL public key file.\n");
1132 fprintf(stderr, " -e Convert OpenSSH to RFC 4716 key file.\n");
1133 fprintf(stderr, " -F hostname Find hostname in known hosts file.\n");
1134 fprintf(stderr, " -f filename Filename of the key file.\n");
1135 fprintf(stderr, " -G file Generate candidates for DH-GEX moduli.\n");
1136 fprintf(stderr, " -g Use generic DNS resource record format.\n");
1137 fprintf(stderr, " -H Hash names in known_hosts file.\n");
1138 fprintf(stderr, " -I Convert OpenSSL to OpenSSH public key file.\n");
1139 fprintf(stderr, " -i Convert RFC 4716 to OpenSSH key file.\n");
1140 fprintf(stderr, " -l Show fingerprint of key file.\n");
1141 fprintf(stderr, " -M memory Amount of memory (MB) to use for generating DH-GEX moduli.\n");
1142 fprintf(stderr, " -N phrase Provide new passphrase.\n");
1143 fprintf(stderr, " -P phrase Provide old passphrase.\n");
1144 fprintf(stderr, " -p Change passphrase of private key file.\n");
1145 fprintf(stderr, " -q Quiet.\n");
1146 fprintf(stderr, " -R hostname Remove host from known_hosts file.\n");
1147 fprintf(stderr, " -r hostname Print DNS resource record.\n");
1148 fprintf(stderr, " -S start Start point (hex) for generating DH-GEX moduli.\n");
1149 fprintf(stderr, " -T file Screen candidates for DH-GEX moduli.\n");
1150 fprintf(stderr, " -t type Specify type of key to create.\n");
1151 #ifdef SMARTCARD
1152 fprintf(stderr, " -U reader Upload private key to smartcard.\n");
1153 #endif /* SMARTCARD */
1154 fprintf(stderr, " -v Verbose.\n");
1155 fprintf(stderr, " -W gen Generator to use for generating DH-GEX moduli.\n");
1156 fprintf(stderr, " -y Read private key file and print public key.\n");
1157
1158 exit(1);
1159 }
1160
1161 /*
1162 * Main program for key management.
1163 */
1164 int
main(int argc,char ** argv)1165 main(int argc, char **argv)
1166 {
1167 char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2;
1168 char out_file[MAXPATHLEN], *reader_id = NULL;
1169 char *rr_hostname = NULL;
1170 Key *private, *public;
1171 struct passwd *pw;
1172 struct stat st;
1173 int opt, type, fd, download = 0;
1174 u_int32_t memory = 0, generator_wanted = 0, trials = 100;
1175 int do_gen_candidates = 0, do_screen_candidates = 0;
1176 BIGNUM *start = NULL;
1177 FILE *f;
1178 const char *errstr;
1179
1180 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
1181 sanitise_stdfd();
1182
1183 SSLeay_add_all_algorithms();
1184 log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
1185
1186 /* we need this for the home * directory. */
1187 pw = getpwuid(getuid());
1188 if (!pw) {
1189 printf("You don't exist, go away!\n");
1190 exit(1);
1191 }
1192 if (gethostname(hostname, sizeof(hostname)) < 0) {
1193 perror("gethostname");
1194 exit(1);
1195 }
1196
1197 while ((opt = getopt(argc, argv,
1198 "a:Bb:cC:dD:EeF:f:G:gHIilM:N:pP:qR:r:S:T:t:U:vW:Xxy")) != -1) {
1199 switch (opt) {
1200 case 'b':
1201 bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr);
1202 if (errstr)
1203 fatal("Bits has bad value %s (%s)",
1204 optarg, errstr);
1205 break;
1206 case 'F':
1207 find_host = 1;
1208 rr_hostname = optarg;
1209 break;
1210 case 'H':
1211 hash_hosts = 1;
1212 break;
1213 case 'R':
1214 delete_host = 1;
1215 rr_hostname = optarg;
1216 break;
1217 case 'l':
1218 print_fingerprint = 1;
1219 break;
1220 case 'B':
1221 print_bubblebabble = 1;
1222 break;
1223 case 'p':
1224 change_passphrase = 1;
1225 break;
1226 case 'c':
1227 change_comment = 1;
1228 break;
1229 case 'f':
1230 if (strlcpy(identity_file, optarg, sizeof(identity_file)) >=
1231 sizeof(identity_file))
1232 fatal("Identity filename too long");
1233 have_identity = 1;
1234 break;
1235 case 'g':
1236 print_generic = 1;
1237 break;
1238 case 'P':
1239 identity_passphrase = optarg;
1240 break;
1241 case 'N':
1242 identity_new_passphrase = optarg;
1243 break;
1244 case 'C':
1245 identity_comment = optarg;
1246 break;
1247 case 'q':
1248 quiet = 1;
1249 break;
1250 case 'e':
1251 case 'x':
1252 /* export key */
1253 convert_to_ssh2 = 1;
1254 break;
1255 case 'i':
1256 case 'X':
1257 /* import key */
1258 convert_from_ssh2 = 1;
1259 break;
1260 case 'E':
1261 convert_to_ossl = 1;
1262 break;
1263 case 'I':
1264 convert_from_ossl = 1;
1265 break;
1266 case 'y':
1267 print_public = 1;
1268 break;
1269 case 'd':
1270 key_type_name = "dsa";
1271 break;
1272 case 't':
1273 key_type_name = optarg;
1274 break;
1275 case 'D':
1276 download = 1;
1277 /*FALLTHROUGH*/
1278 case 'U':
1279 reader_id = optarg;
1280 break;
1281 case 'v':
1282 if (log_level == SYSLOG_LEVEL_INFO)
1283 log_level = SYSLOG_LEVEL_DEBUG1;
1284 else {
1285 if (log_level >= SYSLOG_LEVEL_DEBUG1 &&
1286 log_level < SYSLOG_LEVEL_DEBUG3)
1287 log_level++;
1288 }
1289 break;
1290 case 'r':
1291 rr_hostname = optarg;
1292 break;
1293 case 'W':
1294 generator_wanted = (u_int32_t)strtonum(optarg, 1,
1295 UINT_MAX, &errstr);
1296 if (errstr)
1297 fatal("Desired generator has bad value: %s (%s)",
1298 optarg, errstr);
1299 break;
1300 case 'a':
1301 trials = (u_int32_t)strtonum(optarg, 1, UINT_MAX, &errstr);
1302 if (errstr)
1303 fatal("Invalid number of trials: %s (%s)",
1304 optarg, errstr);
1305 break;
1306 case 'M':
1307 memory = (u_int32_t)strtonum(optarg, 1, UINT_MAX, &errstr);
1308 if (errstr) {
1309 fatal("Memory limit is %s: %s", errstr, optarg);
1310 }
1311 break;
1312 case 'G':
1313 do_gen_candidates = 1;
1314 if (strlcpy(out_file, optarg, sizeof(out_file)) >=
1315 sizeof(out_file))
1316 fatal("Output filename too long");
1317 break;
1318 case 'T':
1319 do_screen_candidates = 1;
1320 if (strlcpy(out_file, optarg, sizeof(out_file)) >=
1321 sizeof(out_file))
1322 fatal("Output filename too long");
1323 break;
1324 case 'S':
1325 /* XXX - also compare length against bits */
1326 if (BN_hex2bn(&start, optarg) == 0)
1327 fatal("Invalid start point.");
1328 break;
1329 case '?':
1330 default:
1331 usage();
1332 }
1333 }
1334
1335 /* reinit */
1336 log_init(argv[0], log_level, SYSLOG_FACILITY_USER, 1);
1337
1338 if (optind < argc) {
1339 printf("Too many arguments.\n");
1340 usage();
1341 }
1342 if (change_passphrase && change_comment) {
1343 printf("Can only have one of -p and -c.\n");
1344 usage();
1345 }
1346 if (print_fingerprint && (delete_host || hash_hosts)) {
1347 printf("Cannot use -l with -D or -R.\n");
1348 usage();
1349 }
1350 if (delete_host || hash_hosts || find_host)
1351 do_known_hosts(pw, rr_hostname);
1352 if (print_fingerprint || print_bubblebabble)
1353 do_fingerprint(pw);
1354 if (change_passphrase)
1355 do_change_passphrase(pw);
1356 if (change_comment)
1357 do_change_comment(pw);
1358 if (convert_to_ssh2)
1359 do_convert_to_ssh2(pw);
1360 if (convert_from_ssh2)
1361 do_convert_from_ssh2(pw);
1362 if (convert_to_ossl)
1363 do_convert_to_ossl(pw);
1364 if (convert_from_ossl)
1365 do_convert_from_ossl(pw);
1366 if (print_public)
1367 do_print_public(pw);
1368 if (rr_hostname != NULL) {
1369 unsigned int n = 0;
1370
1371 if (have_identity) {
1372 n = do_print_resource_record(pw,
1373 identity_file, rr_hostname);
1374 if (n == 0) {
1375 perror(identity_file);
1376 exit(1);
1377 }
1378 exit(0);
1379 } else {
1380
1381 n += do_print_resource_record(pw,
1382 _PATH_HOST_RSA_KEY_FILE, rr_hostname);
1383 n += do_print_resource_record(pw,
1384 _PATH_HOST_DSA_KEY_FILE, rr_hostname);
1385
1386 if (n == 0)
1387 fatal("no keys found.");
1388 exit(0);
1389 }
1390 }
1391 if (reader_id != NULL) {
1392 #ifdef SMARTCARD
1393 if (download)
1394 do_download(pw, reader_id);
1395 else
1396 do_upload(pw, reader_id);
1397 #else /* SMARTCARD */
1398 fatal("no support for smartcards.");
1399 #endif /* SMARTCARD */
1400 }
1401
1402 if (do_gen_candidates) {
1403 FILE *out = fopen(out_file, "w");
1404
1405 if (out == NULL) {
1406 error("Couldn't open modulus candidate file \"%s\": %s",
1407 out_file, strerror(errno));
1408 return (1);
1409 }
1410 if (bits == 0)
1411 bits = DEFAULT_BITS;
1412 if (gen_candidates(out, memory, bits, start) != 0)
1413 fatal("modulus candidate generation failed");
1414
1415 return (0);
1416 }
1417
1418 if (do_screen_candidates) {
1419 FILE *in;
1420 FILE *out = fopen(out_file, "w");
1421
1422 if (have_identity && strcmp(identity_file, "-") != 0) {
1423 if ((in = fopen(identity_file, "r")) == NULL) {
1424 fatal("Couldn't open modulus candidate "
1425 "file \"%s\": %s", identity_file,
1426 strerror(errno));
1427 }
1428 } else
1429 in = stdin;
1430
1431 if (out == NULL) {
1432 fatal("Couldn't open moduli file \"%s\": %s",
1433 out_file, strerror(errno));
1434 }
1435 if (prime_test(in, out, trials, generator_wanted) != 0)
1436 fatal("modulus screening failed");
1437 return (0);
1438 }
1439
1440 (void)arc4random();
1441
1442 if (key_type_name == NULL)
1443 key_type_name = "rsa";
1444
1445 type = key_type_from_name((char *)key_type_name);
1446 if (type == KEY_UNSPEC) {
1447 fprintf(stderr, "unknown key type %s\n", key_type_name);
1448 exit(1);
1449 }
1450 if (bits == 0)
1451 bits = (type == KEY_DSA) ? DEFAULT_BITS_DSA : DEFAULT_BITS;
1452 if (type == KEY_DSA && bits != 1024)
1453 fatal("DSA keys must be 1024 bits");
1454 if (!quiet)
1455 printf("Generating public/private %s key pair.\n", key_type_name);
1456 private = key_generate(type, bits);
1457 if (private == NULL) {
1458 fprintf(stderr, "key_generate failed\n");
1459 exit(1);
1460 }
1461 public = key_from_private(private);
1462
1463 if (!have_identity)
1464 ask_filename(pw, "Enter file in which to save the key");
1465
1466 /* Create ~/.etc/ssh directory if it doesn't already exist. */
1467 snprintf(dotsshdir, sizeof dotsshdir, "%s/%s", pw->pw_dir, _PATH_SSH_USER_DIR);
1468 if (strstr(identity_file, dotsshdir) != NULL &&
1469 stat(dotsshdir, &st) < 0) {
1470 if (mkdir(dotsshdir, 0700) < 0)
1471 error("Could not create directory '%s'.", dotsshdir);
1472 else if (!quiet)
1473 printf("Created directory '%s'.\n", dotsshdir);
1474 }
1475 /* If the file already exists, ask the user to confirm. */
1476 if (stat(identity_file, &st) >= 0) {
1477 char yesno[3];
1478 printf("%s already exists.\n", identity_file);
1479 printf("Overwrite (y/n)? ");
1480 fflush(stdout);
1481 if (fgets(yesno, sizeof(yesno), stdin) == NULL)
1482 exit(1);
1483 if (yesno[0] != 'y' && yesno[0] != 'Y')
1484 exit(1);
1485 }
1486 /* Ask for a passphrase (twice). */
1487 if (identity_passphrase)
1488 passphrase1 = xstrdup(identity_passphrase);
1489 else if (identity_new_passphrase)
1490 passphrase1 = xstrdup(identity_new_passphrase);
1491 else {
1492 passphrase_again:
1493 passphrase1 =
1494 read_passphrase("Enter passphrase (empty for no "
1495 "passphrase): ", RP_ALLOW_STDIN);
1496 passphrase2 = read_passphrase("Enter same passphrase again: ",
1497 RP_ALLOW_STDIN);
1498 if (strcmp(passphrase1, passphrase2) != 0) {
1499 /*
1500 * The passphrases do not match. Clear them and
1501 * retry.
1502 */
1503 memset(passphrase1, 0, strlen(passphrase1));
1504 memset(passphrase2, 0, strlen(passphrase2));
1505 xfree(passphrase1);
1506 xfree(passphrase2);
1507 printf("Passphrases do not match. Try again.\n");
1508 goto passphrase_again;
1509 }
1510 /* Clear the other copy of the passphrase. */
1511 memset(passphrase2, 0, strlen(passphrase2));
1512 xfree(passphrase2);
1513 }
1514
1515 if (identity_comment) {
1516 strlcpy(comment, identity_comment, sizeof(comment));
1517 } else {
1518 /* Create default comment field for the passphrase. */
1519 snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname);
1520 }
1521
1522 /* Save the key with the given passphrase and comment. */
1523 if (!key_save_private(private, identity_file, passphrase1, comment)) {
1524 printf("Saving the key failed: %s.\n", identity_file);
1525 memset(passphrase1, 0, strlen(passphrase1));
1526 xfree(passphrase1);
1527 exit(1);
1528 }
1529 /* Clear the passphrase. */
1530 memset(passphrase1, 0, strlen(passphrase1));
1531 xfree(passphrase1);
1532
1533 /* Clear the private key and the random number generator. */
1534 key_free(private);
1535 (void)arc4random();
1536
1537 if (!quiet)
1538 printf("Your identification has been saved in %s.\n", identity_file);
1539
1540 strlcat(identity_file, ".pub", sizeof(identity_file));
1541 fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
1542 if (fd == -1) {
1543 printf("Could not save your public key in %s\n", identity_file);
1544 exit(1);
1545 }
1546 f = fdopen(fd, "w");
1547 if (f == NULL) {
1548 printf("fdopen %s failed\n", identity_file);
1549 exit(1);
1550 }
1551 if (!key_write(public, f))
1552 fprintf(stderr, "write key failed\n");
1553 fprintf(f, " %s\n", comment);
1554 fclose(f);
1555
1556 if (!quiet) {
1557 char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX);
1558 char *ra = key_fingerprint(public, SSH_FP_MD5,
1559 SSH_FP_RANDOMART);
1560 printf("Your public key has been saved in %s.\n",
1561 identity_file);
1562 printf("The key fingerprint is:\n");
1563 printf("%s %s\n", fp, comment);
1564 printf("The key's randomart image is:\n");
1565 printf("%s\n", ra);
1566 xfree(ra);
1567 xfree(fp);
1568 }
1569
1570 key_free(public);
1571 exit(0);
1572 }
1573