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