]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - crypto/openssh/ssh-keygen.c
This commit was generated by cvs2svn to compensate for changes in r79655,
[FreeBSD/FreeBSD.git] / crypto / openssh / ssh-keygen.c
1 /*
2  * Author: Tatu Ylonen <ylo@cs.hut.fi>
3  * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4  *                    All rights reserved
5  * Identity and host key generation and maintenance.
6  *
7  * As far as I am concerned, the code I have written for this software
8  * can be used freely for any purpose.  Any derived versions of this
9  * software must be clearly marked as such, and if the derived work is
10  * incompatible with the protocol description in the RFC file, it must be
11  * called by a name other than "ssh" or "Secure Shell".
12  */
13
14 #include "includes.h"
15 RCSID("$OpenBSD: ssh-keygen.c,v 1.60 2001/04/23 22:14:13 markus Exp $");
16
17 #include <openssl/evp.h>
18 #include <openssl/pem.h>
19
20 #include "xmalloc.h"
21 #include "key.h"
22 #include "rsa.h"
23 #include "authfile.h"
24 #include "uuencode.h"
25 #include "buffer.h"
26 #include "bufaux.h"
27 #include "pathnames.h"
28 #include "log.h"
29 #include "readpass.h"
30
31 /* Number of bits in the RSA/DSA key.  This value can be changed on the command line. */
32 int bits = 1024;
33
34 /*
35  * Flag indicating that we just want to change the passphrase.  This can be
36  * set on the command line.
37  */
38 int change_passphrase = 0;
39
40 /*
41  * Flag indicating that we just want to change the comment.  This can be set
42  * on the command line.
43  */
44 int change_comment = 0;
45
46 int quiet = 0;
47
48 /* Flag indicating that we just want to see the key fingerprint */
49 int print_fingerprint = 0;
50 int print_bubblebabble = 0;
51
52 /* The identity file name, given on the command line or entered by the user. */
53 char identity_file[1024];
54 int have_identity = 0;
55
56 /* This is set to the passphrase if given on the command line. */
57 char *identity_passphrase = NULL;
58
59 /* This is set to the new passphrase if given on the command line. */
60 char *identity_new_passphrase = NULL;
61
62 /* This is set to the new comment if given on the command line. */
63 char *identity_comment = NULL;
64
65 /* Dump public key file in format used by real and the original SSH 2 */
66 int convert_to_ssh2 = 0;
67 int convert_from_ssh2 = 0;
68 int print_public = 0;
69
70 /* default to RSA for SSH-1 */
71 char *key_type_name = "rsa1";
72
73 /* argv0 */
74 extern char *__progname;
75
76 char hostname[MAXHOSTNAMELEN];
77
78 void
79 ask_filename(struct passwd *pw, const char *prompt)
80 {
81         char buf[1024];
82         char *name = NULL;
83
84         switch (key_type_from_name(key_type_name)) {
85         case KEY_RSA1:
86                 name = _PATH_SSH_CLIENT_IDENTITY;
87                 break;
88         case KEY_DSA:
89                 name = _PATH_SSH_CLIENT_ID_DSA;
90                 break;
91         case KEY_RSA:
92                 name = _PATH_SSH_CLIENT_ID_RSA;
93                 break;
94         default:
95                 fprintf(stderr, "bad key type");
96                 exit(1);
97                 break;
98         }
99         snprintf(identity_file, sizeof(identity_file), "%s/%s", pw->pw_dir, name);
100         fprintf(stderr, "%s (%s): ", prompt, identity_file);
101         fflush(stderr);
102         if (fgets(buf, sizeof(buf), stdin) == NULL)
103                 exit(1);
104         if (strchr(buf, '\n'))
105                 *strchr(buf, '\n') = 0;
106         if (strcmp(buf, "") != 0)
107                 strlcpy(identity_file, buf, sizeof(identity_file));
108         have_identity = 1;
109 }
110
111 Key *
112 try_load_pem_key(char *filename)
113 {
114         char *pass;
115         Key *prv;
116
117         prv = key_load_private(filename, "", NULL);
118         if (prv == NULL) {
119                 pass = read_passphrase("Enter passphrase: ", 1);
120                 prv = key_load_private(filename, pass, NULL);
121                 memset(pass, 0, strlen(pass));
122                 xfree(pass);
123         }
124         return prv;
125 }
126
127 #define SSH_COM_PUBLIC_BEGIN            "---- BEGIN SSH2 PUBLIC KEY ----"
128 #define SSH_COM_PUBLIC_END              "---- END SSH2 PUBLIC KEY ----"
129 #define SSH_COM_PRIVATE_BEGIN           "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"
130 #define SSH_COM_PRIVATE_KEY_MAGIC       0x3f6ff9eb
131
132 void
133 do_convert_to_ssh2(struct passwd *pw)
134 {
135         Key *k;
136         int len;
137         u_char *blob;
138         struct stat st;
139
140         if (!have_identity)
141                 ask_filename(pw, "Enter file in which the key is");
142         if (stat(identity_file, &st) < 0) {
143                 perror(identity_file);
144                 exit(1);
145         }
146         if ((k = key_load_public(identity_file, NULL)) == NULL) {
147                 if ((k = try_load_pem_key(identity_file)) == NULL) {
148                         fprintf(stderr, "load failed\n");
149                         exit(1);
150                 }
151         }
152         key_to_blob(k, &blob, &len);
153         fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN);
154         fprintf(stdout,
155             "Comment: \"%d-bit %s, converted from OpenSSH by %s@%s\"\n",
156             key_size(k), key_type(k),
157             pw->pw_name, hostname);
158         dump_base64(stdout, blob, len);
159         fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END);
160         key_free(k);
161         xfree(blob);
162         exit(0);
163 }
164
165 void
166 buffer_get_bignum_bits(Buffer *b, BIGNUM *value)
167 {
168         int bits = buffer_get_int(b);
169         int bytes = (bits + 7) / 8;
170
171         if (buffer_len(b) < bytes)
172                 fatal("buffer_get_bignum_bits: input buffer too small: "
173                     "need %d have %d", bytes, buffer_len(b));
174         BN_bin2bn((u_char *)buffer_ptr(b), bytes, value);
175         buffer_consume(b, bytes);
176 }
177
178 Key *
179 do_convert_private_ssh2_from_blob(char *blob, int blen)
180 {
181         Buffer b;
182         Key *key = NULL;
183         int ignore, magic, rlen, ktype;
184         char *type, *cipher;
185
186         buffer_init(&b);
187         buffer_append(&b, blob, blen);
188
189         magic  = buffer_get_int(&b);
190         if (magic != SSH_COM_PRIVATE_KEY_MAGIC) {
191                 error("bad magic 0x%x != 0x%x", magic, SSH_COM_PRIVATE_KEY_MAGIC);
192                 buffer_free(&b);
193                 return NULL;
194         }
195         ignore = buffer_get_int(&b);
196         type   = buffer_get_string(&b, NULL);
197         cipher = buffer_get_string(&b, NULL);
198         ignore = buffer_get_int(&b);
199         ignore = buffer_get_int(&b);
200         ignore = buffer_get_int(&b);
201
202         if (strcmp(cipher, "none") != 0) {
203                 error("unsupported cipher %s", cipher);
204                 xfree(cipher);
205                 buffer_free(&b);
206                 xfree(type);
207                 return NULL;
208         }
209         xfree(cipher);
210
211         if (strstr(type, "dsa")) {
212                 ktype = KEY_DSA;
213         } else if (strstr(type, "rsa")) {
214                 ktype = KEY_RSA;
215         } else {
216                 xfree(type);
217                 return NULL;
218         }
219         key = key_new_private(ktype);
220         xfree(type);
221
222         switch (key->type) {
223         case KEY_DSA:
224                 buffer_get_bignum_bits(&b, key->dsa->p);
225                 buffer_get_bignum_bits(&b, key->dsa->g);
226                 buffer_get_bignum_bits(&b, key->dsa->q);
227                 buffer_get_bignum_bits(&b, key->dsa->pub_key);
228                 buffer_get_bignum_bits(&b, key->dsa->priv_key);
229                 break;
230         case KEY_RSA:
231                 if (!BN_set_word(key->rsa->e, (u_long) buffer_get_char(&b))) {
232                         buffer_free(&b);
233                         key_free(key);
234                         return NULL;
235                 }
236                 buffer_get_bignum_bits(&b, key->rsa->d);
237                 buffer_get_bignum_bits(&b, key->rsa->n);
238                 buffer_get_bignum_bits(&b, key->rsa->iqmp);
239                 buffer_get_bignum_bits(&b, key->rsa->q);
240                 buffer_get_bignum_bits(&b, key->rsa->p);
241                 generate_additional_parameters(key->rsa);
242                 break;
243         }
244         rlen = buffer_len(&b);
245         if(rlen != 0)
246                 error("do_convert_private_ssh2_from_blob: "
247                     "remaining bytes in key blob %d", rlen);
248         buffer_free(&b);
249 #ifdef DEBUG_PK
250         {
251                 u_int slen;
252                 u_char *sig, data[10] = "abcde12345";
253
254                 key_sign(key, &sig, &slen, data, sizeof data);
255                 key_verify(key, sig, slen, data, sizeof data);
256                 xfree(sig);
257         }
258 #endif
259         return key;
260 }
261
262 void
263 do_convert_from_ssh2(struct passwd *pw)
264 {
265         Key *k;
266         int blen;
267         char line[1024], *p;
268         char blob[8096];
269         char encoded[8096];
270         struct stat st;
271         int escaped = 0, private = 0, ok;
272         FILE *fp;
273
274         if (!have_identity)
275                 ask_filename(pw, "Enter file in which the key is");
276         if (stat(identity_file, &st) < 0) {
277                 perror(identity_file);
278                 exit(1);
279         }
280         fp = fopen(identity_file, "r");
281         if (fp == NULL) {
282                 perror(identity_file);
283                 exit(1);
284         }
285         encoded[0] = '\0';
286         while (fgets(line, sizeof(line), fp)) {
287                 if (!(p = strchr(line, '\n'))) {
288                         fprintf(stderr, "input line too long.\n");
289                         exit(1);
290                 }
291                 if (p > line && p[-1] == '\\')
292                         escaped++;
293                 if (strncmp(line, "----", 4) == 0 ||
294                     strstr(line, ": ") != NULL) {
295                         if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL)
296                                 private = 1;
297                         /* fprintf(stderr, "ignore: %s", line); */
298                         continue;
299                 }
300                 if (escaped) {
301                         escaped--;
302                         /* fprintf(stderr, "escaped: %s", line); */
303                         continue;
304                 }
305                 *p = '\0';
306                 strlcat(encoded, line, sizeof(encoded));
307         }
308         blen = uudecode(encoded, (u_char *)blob, sizeof(blob));
309         if (blen < 0) {
310                 fprintf(stderr, "uudecode failed.\n");
311                 exit(1);
312         }
313         k = private ?
314             do_convert_private_ssh2_from_blob(blob, blen) :
315             key_from_blob(blob, blen);
316         if (k == NULL) {
317                 fprintf(stderr, "decode blob failed.\n");
318                 exit(1);
319         }
320         ok = private ?
321             (k->type == KEY_DSA ?
322                  PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, NULL, 0, NULL, NULL) :
323                  PEM_write_RSAPrivateKey(stdout, k->rsa, NULL, NULL, 0, NULL, NULL)) :
324             key_write(k, stdout);
325         if (!ok) {
326                 fprintf(stderr, "key write failed");
327                 exit(1);
328         }
329         key_free(k);
330         fprintf(stdout, "\n");
331         fclose(fp);
332         exit(0);
333 }
334
335 void
336 do_print_public(struct passwd *pw)
337 {
338         Key *prv;
339         struct stat st;
340
341         if (!have_identity)
342                 ask_filename(pw, "Enter file in which the key is");
343         if (stat(identity_file, &st) < 0) {
344                 perror(identity_file);
345                 exit(1);
346         }
347         prv = try_load_pem_key(identity_file);
348         if (prv == NULL) {
349                 fprintf(stderr, "load failed\n");
350                 exit(1);
351         }
352         if (!key_write(prv, stdout))
353                 fprintf(stderr, "key_write failed");
354         key_free(prv);
355         fprintf(stdout, "\n");
356         exit(0);
357 }
358
359 void
360 do_fingerprint(struct passwd *pw)
361 {
362         FILE *f;
363         Key *public;
364         char *comment = NULL, *cp, *ep, line[16*1024], *fp;
365         int i, skip = 0, num = 1, invalid = 1, rep, fptype;
366         struct stat st;
367
368         fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
369         rep =    print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
370
371         if (!have_identity)
372                 ask_filename(pw, "Enter file in which the key is");
373         if (stat(identity_file, &st) < 0) {
374                 perror(identity_file);
375                 exit(1);
376         }
377         public = key_load_public(identity_file, &comment);
378         if (public != NULL) {
379                 fp = key_fingerprint(public, fptype, rep);
380                 printf("%d %s %s\n", key_size(public), fp, comment);
381                 key_free(public);
382                 xfree(comment);
383                 xfree(fp);
384                 exit(0);
385         }
386         if (comment)
387                 xfree(comment);
388
389         f = fopen(identity_file, "r");
390         if (f != NULL) {
391                 while (fgets(line, sizeof(line), f)) {
392                         i = strlen(line) - 1;
393                         if (line[i] != '\n') {
394                                 error("line %d too long: %.40s...", num, line);
395                                 skip = 1;
396                                 continue;
397                         }
398                         num++;
399                         if (skip) {
400                                 skip = 0;
401                                 continue;
402                         }
403                         line[i] = '\0';
404
405                         /* Skip leading whitespace, empty and comment lines. */
406                         for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
407                                 ;
408                         if (!*cp || *cp == '\n' || *cp == '#')
409                                 continue ;
410                         i = strtol(cp, &ep, 10);
411                         if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) {
412                                 int quoted = 0;
413                                 comment = cp;
414                                 for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
415                                         if (*cp == '\\' && cp[1] == '"')
416                                                 cp++;   /* Skip both */
417                                         else if (*cp == '"')
418                                                 quoted = !quoted;
419                                 }
420                                 if (!*cp)
421                                         continue;
422                                 *cp++ = '\0';
423                         }
424                         ep = cp;
425                         public = key_new(KEY_RSA1);
426                         if (key_read(public, &cp) != 1) {
427                                 cp = ep;
428                                 key_free(public);
429                                 public = key_new(KEY_UNSPEC);
430                                 if (key_read(public, &cp) != 1) {
431                                         key_free(public);
432                                         continue;
433                                 }
434                         }
435                         comment = *cp ? cp : comment;
436                         fp = key_fingerprint(public, fptype, rep);
437                         printf("%d %s %s\n", key_size(public), fp,
438                             comment ? comment : "no comment");
439                         xfree(fp);
440                         key_free(public);
441                         invalid = 0;
442                 }
443                 fclose(f);
444         }
445         if (invalid) {
446                 printf("%s is not a valid key file.\n", identity_file);
447                 exit(1);
448         }
449         exit(0);
450 }
451
452 /*
453  * Perform changing a passphrase.  The argument is the passwd structure
454  * for the current user.
455  */
456 void
457 do_change_passphrase(struct passwd *pw)
458 {
459         char *comment;
460         char *old_passphrase, *passphrase1, *passphrase2;
461         struct stat st;
462         Key *private;
463
464         if (!have_identity)
465                 ask_filename(pw, "Enter file in which the key is");
466         if (stat(identity_file, &st) < 0) {
467                 perror(identity_file);
468                 exit(1);
469         }
470         /* Try to load the file with empty passphrase. */
471         private = key_load_private(identity_file, "", &comment);
472         if (private == NULL) {
473                 if (identity_passphrase)
474                         old_passphrase = xstrdup(identity_passphrase);
475                 else
476                         old_passphrase = read_passphrase("Enter old passphrase: ", 1);
477                 private = key_load_private(identity_file, old_passphrase , &comment);
478                 memset(old_passphrase, 0, strlen(old_passphrase));
479                 xfree(old_passphrase);
480                 if (private == NULL) {
481                         printf("Bad passphrase.\n");
482                         exit(1);
483                 }
484         }
485         printf("Key has comment '%s'\n", comment);
486
487         /* Ask the new passphrase (twice). */
488         if (identity_new_passphrase) {
489                 passphrase1 = xstrdup(identity_new_passphrase);
490                 passphrase2 = NULL;
491         } else {
492                 passphrase1 =
493                         read_passphrase("Enter new passphrase (empty for no passphrase): ", 1);
494                 passphrase2 = read_passphrase("Enter same passphrase again: ", 1);
495
496                 /* Verify that they are the same. */
497                 if (strcmp(passphrase1, passphrase2) != 0) {
498                         memset(passphrase1, 0, strlen(passphrase1));
499                         memset(passphrase2, 0, strlen(passphrase2));
500                         xfree(passphrase1);
501                         xfree(passphrase2);
502                         printf("Pass phrases do not match.  Try again.\n");
503                         exit(1);
504                 }
505                 /* Destroy the other copy. */
506                 memset(passphrase2, 0, strlen(passphrase2));
507                 xfree(passphrase2);
508         }
509
510         /* Save the file using the new passphrase. */
511         if (!key_save_private(private, identity_file, passphrase1, comment)) {
512                 printf("Saving the key failed: %s.\n", identity_file);
513                 memset(passphrase1, 0, strlen(passphrase1));
514                 xfree(passphrase1);
515                 key_free(private);
516                 xfree(comment);
517                 exit(1);
518         }
519         /* Destroy the passphrase and the copy of the key in memory. */
520         memset(passphrase1, 0, strlen(passphrase1));
521         xfree(passphrase1);
522         key_free(private);               /* Destroys contents */
523         xfree(comment);
524
525         printf("Your identification has been saved with the new passphrase.\n");
526         exit(0);
527 }
528
529 /*
530  * Change the comment of a private key file.
531  */
532 void
533 do_change_comment(struct passwd *pw)
534 {
535         char new_comment[1024], *comment, *passphrase;
536         Key *private;
537         Key *public;
538         struct stat st;
539         FILE *f;
540         int fd;
541
542         if (!have_identity)
543                 ask_filename(pw, "Enter file in which the key is");
544         if (stat(identity_file, &st) < 0) {
545                 perror(identity_file);
546                 exit(1);
547         }
548         private = key_load_private(identity_file, "", &comment);
549         if (private == NULL) {
550                 if (identity_passphrase)
551                         passphrase = xstrdup(identity_passphrase);
552                 else if (identity_new_passphrase)
553                         passphrase = xstrdup(identity_new_passphrase);
554                 else
555                         passphrase = read_passphrase("Enter passphrase: ", 1);
556                 /* Try to load using the passphrase. */
557                 private = key_load_private(identity_file, passphrase, &comment);
558                 if (private == NULL) {
559                         memset(passphrase, 0, strlen(passphrase));
560                         xfree(passphrase);
561                         printf("Bad passphrase.\n");
562                         exit(1);
563                 }
564         } else {
565                 passphrase = xstrdup("");
566         }
567         if (private->type != KEY_RSA1) {
568                 fprintf(stderr, "Comments are only supported for RSA1 keys.\n");
569                 key_free(private);
570                 exit(1);
571         }       
572         printf("Key now has comment '%s'\n", comment);
573
574         if (identity_comment) {
575                 strlcpy(new_comment, identity_comment, sizeof(new_comment));
576         } else {
577                 printf("Enter new comment: ");
578                 fflush(stdout);
579                 if (!fgets(new_comment, sizeof(new_comment), stdin)) {
580                         memset(passphrase, 0, strlen(passphrase));
581                         key_free(private);
582                         exit(1);
583                 }
584                 if (strchr(new_comment, '\n'))
585                         *strchr(new_comment, '\n') = 0;
586         }
587
588         /* Save the file using the new passphrase. */
589         if (!key_save_private(private, identity_file, passphrase, new_comment)) {
590                 printf("Saving the key failed: %s.\n", identity_file);
591                 memset(passphrase, 0, strlen(passphrase));
592                 xfree(passphrase);
593                 key_free(private);
594                 xfree(comment);
595                 exit(1);
596         }
597         memset(passphrase, 0, strlen(passphrase));
598         xfree(passphrase);
599         public = key_from_private(private);
600         key_free(private);
601
602         strlcat(identity_file, ".pub", sizeof(identity_file));
603         fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
604         if (fd == -1) {
605                 printf("Could not save your public key in %s\n", identity_file);
606                 exit(1);
607         }
608         f = fdopen(fd, "w");
609         if (f == NULL) {
610                 printf("fdopen %s failed", identity_file);
611                 exit(1);
612         }
613         if (!key_write(public, f))
614                 fprintf(stderr, "write key failed");
615         key_free(public);
616         fprintf(f, " %s\n", new_comment);
617         fclose(f);
618
619         xfree(comment);
620
621         printf("The comment in your key file has been changed.\n");
622         exit(0);
623 }
624
625 void
626 usage(void)
627 {
628         printf("Usage: %s [-ceilpqyB] [-t type] [-b bits] [-f file] [-C comment] "
629             "[-N new-pass] [-P pass]\n", __progname);
630         exit(1);
631 }
632
633 /*
634  * Main program for key management.
635  */
636 int
637 main(int ac, char **av)
638 {
639         char dotsshdir[16 * 1024], comment[1024], *passphrase1, *passphrase2;
640         Key *private, *public;
641         struct passwd *pw;
642         int opt, type, fd;
643         struct stat st;
644         FILE *f;
645
646         extern int optind;
647         extern char *optarg;
648
649         SSLeay_add_all_algorithms();
650
651         /* we need this for the home * directory.  */
652         pw = getpwuid(getuid());
653         if (!pw) {
654                 printf("You don't exist, go away!\n");
655                 exit(1);
656         }
657         if (gethostname(hostname, sizeof(hostname)) < 0) {
658                 perror("gethostname");
659                 exit(1);
660         }
661
662         while ((opt = getopt(ac, av, "deiqpclBRxXyb:f:t:P:N:C:")) != -1) {
663                 switch (opt) {
664                 case 'b':
665                         bits = atoi(optarg);
666                         if (bits < 512 || bits > 32768) {
667                                 printf("Bits has bad value.\n");
668                                 exit(1);
669                         }
670                         break;
671
672                 case 'l':
673                         print_fingerprint = 1;
674                         break;
675
676                 case 'B':
677                         print_bubblebabble = 1;
678                         break;
679
680                 case 'p':
681                         change_passphrase = 1;
682                         break;
683
684                 case 'c':
685                         change_comment = 1;
686                         break;
687
688                 case 'f':
689                         strlcpy(identity_file, optarg, sizeof(identity_file));
690                         have_identity = 1;
691                         break;
692
693                 case 'P':
694                         identity_passphrase = optarg;
695                         break;
696
697                 case 'N':
698                         identity_new_passphrase = optarg;
699                         break;
700
701                 case 'C':
702                         identity_comment = optarg;
703                         break;
704
705                 case 'q':
706                         quiet = 1;
707                         break;
708
709                 case 'R':
710                         /* unused */
711                         exit(0);
712                         break;
713
714                 case 'e':
715                 case 'x':
716                         /* export key */
717                         convert_to_ssh2 = 1;
718                         break;
719
720                 case 'i':
721                 case 'X':
722                         /* import key */
723                         convert_from_ssh2 = 1;
724                         break;
725
726                 case 'y':
727                         print_public = 1;
728                         break;
729
730                 case 'd':
731                         key_type_name = "dsa";
732                         break;
733
734                 case 't':
735                         key_type_name = optarg;
736                         break;
737
738                 case '?':
739                 default:
740                         usage();
741                 }
742         }
743         if (optind < ac) {
744                 printf("Too many arguments.\n");
745                 usage();
746         }
747         if (change_passphrase && change_comment) {
748                 printf("Can only have one of -p and -c.\n");
749                 usage();
750         }
751         if (print_fingerprint || print_bubblebabble)
752                 do_fingerprint(pw);
753         if (change_passphrase)
754                 do_change_passphrase(pw);
755         if (change_comment)
756                 do_change_comment(pw);
757         if (convert_to_ssh2)
758                 do_convert_to_ssh2(pw);
759         if (convert_from_ssh2)
760                 do_convert_from_ssh2(pw);
761         if (print_public)
762                 do_print_public(pw);
763
764         arc4random_stir();
765
766         type = key_type_from_name(key_type_name);
767         if (type == KEY_UNSPEC) {
768                 fprintf(stderr, "unknown key type %s\n", key_type_name);
769                 exit(1);
770         }
771         if (!quiet)
772                 printf("Generating public/private %s key pair.\n", key_type_name);
773         private = key_generate(type, bits);
774         if (private == NULL) {
775                 fprintf(stderr, "key_generate failed");
776                 exit(1);
777         }
778         public  = key_from_private(private);
779
780         if (!have_identity)
781                 ask_filename(pw, "Enter file in which to save the key");
782
783         /* Create ~/.ssh directory if it doesn\'t already exist. */
784         snprintf(dotsshdir, sizeof dotsshdir, "%s/%s", pw->pw_dir, _PATH_SSH_USER_DIR);
785         if (strstr(identity_file, dotsshdir) != NULL &&
786             stat(dotsshdir, &st) < 0) {
787                 if (mkdir(dotsshdir, 0700) < 0)
788                         error("Could not create directory '%s'.", dotsshdir);
789                 else if (!quiet)
790                         printf("Created directory '%s'.\n", dotsshdir);
791         }
792         /* If the file already exists, ask the user to confirm. */
793         if (stat(identity_file, &st) >= 0) {
794                 char yesno[3];
795                 printf("%s already exists.\n", identity_file);
796                 printf("Overwrite (y/n)? ");
797                 fflush(stdout);
798                 if (fgets(yesno, sizeof(yesno), stdin) == NULL)
799                         exit(1);
800                 if (yesno[0] != 'y' && yesno[0] != 'Y')
801                         exit(1);
802         }
803         /* Ask for a passphrase (twice). */
804         if (identity_passphrase)
805                 passphrase1 = xstrdup(identity_passphrase);
806         else if (identity_new_passphrase)
807                 passphrase1 = xstrdup(identity_new_passphrase);
808         else {
809 passphrase_again:
810                 passphrase1 =
811                         read_passphrase("Enter passphrase (empty for no passphrase): ", 1);
812                 passphrase2 = read_passphrase("Enter same passphrase again: ", 1);
813                 if (strcmp(passphrase1, passphrase2) != 0) {
814                         /* The passphrases do not match.  Clear them and retry. */
815                         memset(passphrase1, 0, strlen(passphrase1));
816                         memset(passphrase2, 0, strlen(passphrase2));
817                         xfree(passphrase1);
818                         xfree(passphrase2);
819                         printf("Passphrases do not match.  Try again.\n");
820                         goto passphrase_again;
821                 }
822                 /* Clear the other copy of the passphrase. */
823                 memset(passphrase2, 0, strlen(passphrase2));
824                 xfree(passphrase2);
825         }
826
827         if (identity_comment) {
828                 strlcpy(comment, identity_comment, sizeof(comment));
829         } else {
830                 /* Create default commend field for the passphrase. */
831                 snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname);
832         }
833
834         /* Save the key with the given passphrase and comment. */
835         if (!key_save_private(private, identity_file, passphrase1, comment)) {
836                 printf("Saving the key failed: %s.\n", identity_file);
837                 memset(passphrase1, 0, strlen(passphrase1));
838                 xfree(passphrase1);
839                 exit(1);
840         }
841         /* Clear the passphrase. */
842         memset(passphrase1, 0, strlen(passphrase1));
843         xfree(passphrase1);
844
845         /* Clear the private key and the random number generator. */
846         key_free(private);
847         arc4random_stir();
848
849         if (!quiet)
850                 printf("Your identification has been saved in %s.\n", identity_file);
851
852         strlcat(identity_file, ".pub", sizeof(identity_file));
853         fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
854         if (fd == -1) {
855                 printf("Could not save your public key in %s\n", identity_file);
856                 exit(1);
857         }
858         f = fdopen(fd, "w");
859         if (f == NULL) {
860                 printf("fdopen %s failed", identity_file);
861                 exit(1);
862         }
863         if (!key_write(public, f))
864                 fprintf(stderr, "write key failed");
865         fprintf(f, " %s\n", comment);
866         fclose(f);
867
868         if (!quiet) {
869                 char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX);
870                 printf("Your public key has been saved in %s.\n",
871                     identity_file);
872                 printf("The key fingerprint is:\n");
873                 printf("%s %s\n", fp, comment);
874                 xfree(fp);
875         }
876
877         key_free(public);
878         exit(0);
879 }