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