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