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