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