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