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