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