Annotation of src/usr.bin/ssh/ssh-keygen.c, Revision 1.60.2.1
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.1! jason 15: RCSID("$OpenBSD: ssh-keygen.c,v 1.81 2001/09/17 20:50:22 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.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:
! 494: if (prv)
! 495: key_free(prv);
! 496: for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++)
! 497: if (elements[i])
! 498: xfree(elements[i]);
! 499: if (fd != -1)
! 500: sectok_close(fd);
! 501: exit(status);
! 502: }
! 503:
! 504: static void
! 505: do_download(struct passwd *pw, const char *sc_reader_id)
! 506: {
! 507: Key *pub = NULL;
! 508:
! 509: pub = sc_get_key(sc_reader_id);
! 510: if (pub == NULL)
! 511: fatal("cannot read public key from smartcard");
! 512: key_write(pub, stdout);
! 513: key_free(pub);
! 514: fprintf(stdout, "\n");
! 515: exit(0);
! 516: }
! 517: #endif /* SMARTCARD */
! 518:
! 519: static void
1.8 markus 520: do_fingerprint(struct passwd *pw)
521: {
1.15 markus 522: FILE *f;
1.19 markus 523: Key *public;
1.49 markus 524: char *comment = NULL, *cp, *ep, line[16*1024], *fp;
1.52 markus 525: int i, skip = 0, num = 1, invalid = 1, rep, fptype;
1.12 markus 526: struct stat st;
527:
1.52 markus 528: fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
529: rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
1.49 markus 530:
1.12 markus 531: if (!have_identity)
532: ask_filename(pw, "Enter file in which the key is");
533: if (stat(identity_file, &st) < 0) {
534: perror(identity_file);
535: exit(1);
536: }
1.52 markus 537: public = key_load_public(identity_file, &comment);
538: if (public != NULL) {
539: fp = key_fingerprint(public, fptype, rep);
540: printf("%d %s %s\n", key_size(public), fp, comment);
1.33 markus 541: key_free(public);
542: xfree(comment);
1.49 markus 543: xfree(fp);
1.15 markus 544: exit(0);
545: }
1.52 markus 546: if (comment)
547: xfree(comment);
1.15 markus 548:
549: f = fopen(identity_file, "r");
550: if (f != NULL) {
551: while (fgets(line, sizeof(line), f)) {
552: i = strlen(line) - 1;
553: if (line[i] != '\n') {
554: error("line %d too long: %.40s...", num, line);
555: skip = 1;
556: continue;
557: }
558: num++;
559: if (skip) {
560: skip = 0;
561: continue;
562: }
563: line[i] = '\0';
564:
565: /* Skip leading whitespace, empty and comment lines. */
566: for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
567: ;
568: if (!*cp || *cp == '\n' || *cp == '#')
569: continue ;
570: i = strtol(cp, &ep, 10);
571: if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) {
572: int quoted = 0;
573: comment = cp;
574: for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
575: if (*cp == '\\' && cp[1] == '"')
576: cp++; /* Skip both */
577: else if (*cp == '"')
578: quoted = !quoted;
579: }
580: if (!*cp)
581: continue;
582: *cp++ = '\0';
583: }
584: ep = cp;
1.38 markus 585: public = key_new(KEY_RSA1);
586: if (key_read(public, &cp) != 1) {
587: cp = ep;
588: key_free(public);
589: public = key_new(KEY_UNSPEC);
590: if (key_read(public, &cp) != 1) {
591: key_free(public);
592: continue;
593: }
1.12 markus 594: }
1.38 markus 595: comment = *cp ? cp : comment;
1.52 markus 596: fp = key_fingerprint(public, fptype, rep);
1.49 markus 597: printf("%d %s %s\n", key_size(public), fp,
1.38 markus 598: comment ? comment : "no comment");
1.49 markus 599: xfree(fp);
1.52 markus 600: key_free(public);
1.38 markus 601: invalid = 0;
1.12 markus 602: }
1.15 markus 603: fclose(f);
604: }
605: if (invalid) {
606: printf("%s is not a valid key file.\n", identity_file);
607: exit(1);
1.12 markus 608: }
609: exit(0);
1.8 markus 610: }
611:
1.13 deraadt 612: /*
613: * Perform changing a passphrase. The argument is the passwd structure
614: * for the current user.
615: */
1.60.2.1! jason 616: static void
1.7 markus 617: do_change_passphrase(struct passwd *pw)
618: {
1.12 markus 619: char *comment;
620: char *old_passphrase, *passphrase1, *passphrase2;
621: struct stat st;
1.19 markus 622: Key *private;
1.12 markus 623:
624: if (!have_identity)
625: ask_filename(pw, "Enter file in which the key is");
626: if (stat(identity_file, &st) < 0) {
627: perror(identity_file);
628: exit(1);
629: }
630: /* Try to load the file with empty passphrase. */
1.52 markus 631: private = key_load_private(identity_file, "", &comment);
632: if (private == NULL) {
1.12 markus 633: if (identity_passphrase)
634: old_passphrase = xstrdup(identity_passphrase);
635: else
1.60.2.1! jason 636: old_passphrase =
! 637: read_passphrase("Enter old passphrase: ",
! 638: RP_ALLOW_STDIN);
! 639: private = key_load_private(identity_file, old_passphrase,
! 640: &comment);
1.52 markus 641: memset(old_passphrase, 0, strlen(old_passphrase));
642: xfree(old_passphrase);
643: if (private == NULL) {
1.12 markus 644: printf("Bad passphrase.\n");
645: exit(1);
646: }
647: }
648: printf("Key has comment '%s'\n", comment);
649:
650: /* Ask the new passphrase (twice). */
651: if (identity_new_passphrase) {
652: passphrase1 = xstrdup(identity_new_passphrase);
653: passphrase2 = NULL;
654: } else {
655: passphrase1 =
1.60.2.1! jason 656: read_passphrase("Enter new passphrase (empty for no "
! 657: "passphrase): ", RP_ALLOW_STDIN);
! 658: passphrase2 = read_passphrase("Enter same passphrase again: ",
! 659: RP_ALLOW_STDIN);
1.12 markus 660:
661: /* Verify that they are the same. */
662: if (strcmp(passphrase1, passphrase2) != 0) {
663: memset(passphrase1, 0, strlen(passphrase1));
664: memset(passphrase2, 0, strlen(passphrase2));
665: xfree(passphrase1);
666: xfree(passphrase2);
667: printf("Pass phrases do not match. Try again.\n");
668: exit(1);
669: }
670: /* Destroy the other copy. */
671: memset(passphrase2, 0, strlen(passphrase2));
672: xfree(passphrase2);
673: }
674:
675: /* Save the file using the new passphrase. */
1.52 markus 676: if (!key_save_private(private, identity_file, passphrase1, comment)) {
1.56 markus 677: printf("Saving the key failed: %s.\n", identity_file);
1.12 markus 678: memset(passphrase1, 0, strlen(passphrase1));
679: xfree(passphrase1);
1.19 markus 680: key_free(private);
1.12 markus 681: xfree(comment);
682: exit(1);
683: }
684: /* Destroy the passphrase and the copy of the key in memory. */
685: memset(passphrase1, 0, strlen(passphrase1));
686: xfree(passphrase1);
1.19 markus 687: key_free(private); /* Destroys contents */
1.12 markus 688: xfree(comment);
1.1 deraadt 689:
1.12 markus 690: printf("Your identification has been saved with the new passphrase.\n");
691: exit(0);
1.1 deraadt 692: }
693:
1.13 deraadt 694: /*
695: * Change the comment of a private key file.
696: */
1.60.2.1! jason 697: static void
1.2 provos 698: do_change_comment(struct passwd *pw)
1.1 deraadt 699: {
1.46 deraadt 700: char new_comment[1024], *comment, *passphrase;
1.52 markus 701: Key *private;
702: Key *public;
1.12 markus 703: struct stat st;
704: FILE *f;
1.46 deraadt 705: int fd;
1.12 markus 706:
707: if (!have_identity)
708: ask_filename(pw, "Enter file in which the key is");
709: if (stat(identity_file, &st) < 0) {
710: perror(identity_file);
711: exit(1);
712: }
1.52 markus 713: private = key_load_private(identity_file, "", &comment);
714: if (private == NULL) {
1.12 markus 715: if (identity_passphrase)
716: passphrase = xstrdup(identity_passphrase);
717: else if (identity_new_passphrase)
718: passphrase = xstrdup(identity_new_passphrase);
719: else
1.60.2.1! jason 720: passphrase = read_passphrase("Enter passphrase: ",
! 721: RP_ALLOW_STDIN);
1.12 markus 722: /* Try to load using the passphrase. */
1.52 markus 723: private = key_load_private(identity_file, passphrase, &comment);
724: if (private == NULL) {
1.12 markus 725: memset(passphrase, 0, strlen(passphrase));
726: xfree(passphrase);
727: printf("Bad passphrase.\n");
728: exit(1);
729: }
1.52 markus 730: } else {
731: passphrase = xstrdup("");
1.12 markus 732: }
1.52 markus 733: if (private->type != KEY_RSA1) {
734: fprintf(stderr, "Comments are only supported for RSA1 keys.\n");
735: key_free(private);
736: exit(1);
737: }
1.12 markus 738: printf("Key now has comment '%s'\n", comment);
739:
740: if (identity_comment) {
741: strlcpy(new_comment, identity_comment, sizeof(new_comment));
742: } else {
743: printf("Enter new comment: ");
744: fflush(stdout);
745: if (!fgets(new_comment, sizeof(new_comment), stdin)) {
746: memset(passphrase, 0, strlen(passphrase));
1.19 markus 747: key_free(private);
1.12 markus 748: exit(1);
749: }
750: if (strchr(new_comment, '\n'))
751: *strchr(new_comment, '\n') = 0;
752: }
753:
754: /* Save the file using the new passphrase. */
1.52 markus 755: if (!key_save_private(private, identity_file, passphrase, new_comment)) {
1.56 markus 756: printf("Saving the key failed: %s.\n", identity_file);
1.12 markus 757: memset(passphrase, 0, strlen(passphrase));
758: xfree(passphrase);
1.19 markus 759: key_free(private);
1.12 markus 760: xfree(comment);
761: exit(1);
762: }
763: memset(passphrase, 0, strlen(passphrase));
764: xfree(passphrase);
1.52 markus 765: public = key_from_private(private);
1.19 markus 766: key_free(private);
1.12 markus 767:
768: strlcat(identity_file, ".pub", sizeof(identity_file));
1.46 deraadt 769: fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
770: if (fd == -1) {
1.12 markus 771: printf("Could not save your public key in %s\n", identity_file);
772: exit(1);
773: }
1.46 deraadt 774: f = fdopen(fd, "w");
775: if (f == NULL) {
776: printf("fdopen %s failed", identity_file);
777: exit(1);
778: }
1.19 markus 779: if (!key_write(public, f))
780: fprintf(stderr, "write key failed");
781: key_free(public);
782: fprintf(f, " %s\n", new_comment);
1.12 markus 783: fclose(f);
1.1 deraadt 784:
1.12 markus 785: xfree(comment);
1.1 deraadt 786:
1.12 markus 787: printf("The comment in your key file has been changed.\n");
788: exit(0);
1.1 deraadt 789: }
790:
1.60.2.1! jason 791: static void
1.10 markus 792: usage(void)
793: {
1.60.2.1! jason 794: fprintf(stderr, "Usage: %s [options]\n", __progname);
! 795: fprintf(stderr, "Options:\n");
! 796: fprintf(stderr, " -b bits Number of bits in the key to create.\n");
! 797: fprintf(stderr, " -c Change comment in private and public key files.\n");
! 798: fprintf(stderr, " -e Convert OpenSSH to IETF SECSH key file.\n");
! 799: fprintf(stderr, " -f filename Filename of the key file.\n");
! 800: fprintf(stderr, " -i Convert IETF SECSH to OpenSSH key file.\n");
! 801: fprintf(stderr, " -l Show fingerprint of key file.\n");
! 802: fprintf(stderr, " -p Change passphrase of private key file.\n");
! 803: fprintf(stderr, " -q Quiet.\n");
! 804: fprintf(stderr, " -y Read private key file and print public key.\n");
! 805: fprintf(stderr, " -t type Specify type of key to create.\n");
! 806: fprintf(stderr, " -B Show bubblebabble digest of key file.\n");
! 807: fprintf(stderr, " -C comment Provide new comment.\n");
! 808: fprintf(stderr, " -N phrase Provide new passphrase.\n");
! 809: fprintf(stderr, " -P phrase Provide old passphrase.\n");
! 810: #ifdef SMARTCARD
! 811: fprintf(stderr, " -D reader Download public key from smartcard.\n");
! 812: fprintf(stderr, " -U reader Upload private key to smartcard.\n");
! 813: #endif /* SMARTCARD */
! 814:
1.12 markus 815: exit(1);
1.10 markus 816: }
817:
1.13 deraadt 818: /*
819: * Main program for key management.
820: */
1.2 provos 821: int
822: main(int ac, char **av)
1.1 deraadt 823: {
1.12 markus 824: char dotsshdir[16 * 1024], comment[1024], *passphrase1, *passphrase2;
1.60.2.1! jason 825: char *reader_id = NULL;
1.46 deraadt 826: Key *private, *public;
1.12 markus 827: struct passwd *pw;
828: struct stat st;
1.60.2.1! jason 829: int opt, type, fd, download = 0;
1.12 markus 830: FILE *f;
1.33 markus 831:
1.12 markus 832: extern int optind;
833: extern char *optarg;
834:
1.26 markus 835: SSLeay_add_all_algorithms();
1.19 markus 836:
1.14 markus 837: /* we need this for the home * directory. */
1.12 markus 838: pw = getpwuid(getuid());
839: if (!pw) {
840: printf("You don't exist, go away!\n");
841: exit(1);
842: }
1.19 markus 843: if (gethostname(hostname, sizeof(hostname)) < 0) {
844: perror("gethostname");
845: exit(1);
846: }
1.14 markus 847:
1.60.2.1! jason 848: while ((opt = getopt(ac, av, "deiqpclBRxXyb:f:t:U:D:P:N:C:")) != -1) {
1.12 markus 849: switch (opt) {
850: case 'b':
851: bits = atoi(optarg);
852: if (bits < 512 || bits > 32768) {
853: printf("Bits has bad value.\n");
854: exit(1);
855: }
856: break;
857: case 'l':
858: print_fingerprint = 1;
859: break;
1.49 markus 860: case 'B':
861: print_bubblebabble = 1;
862: break;
1.12 markus 863: case 'p':
864: change_passphrase = 1;
865: break;
866: case 'c':
867: change_comment = 1;
868: break;
869: case 'f':
870: strlcpy(identity_file, optarg, sizeof(identity_file));
871: have_identity = 1;
872: break;
873: case 'P':
874: identity_passphrase = optarg;
875: break;
876: case 'N':
877: identity_new_passphrase = optarg;
878: break;
879: case 'C':
880: identity_comment = optarg;
881: break;
882: case 'q':
883: quiet = 1;
1.20 deraadt 884: break;
885: case 'R':
1.33 markus 886: /* unused */
887: exit(0);
1.12 markus 888: break;
1.57 markus 889: case 'e':
1.19 markus 890: case 'x':
1.57 markus 891: /* export key */
1.19 markus 892: convert_to_ssh2 = 1;
893: break;
1.57 markus 894: case 'i':
1.19 markus 895: case 'X':
1.57 markus 896: /* import key */
1.19 markus 897: convert_from_ssh2 = 1;
898: break;
899: case 'y':
900: print_public = 1;
1.47 jakob 901: break;
1.19 markus 902: case 'd':
1.33 markus 903: key_type_name = "dsa";
1.19 markus 904: break;
1.33 markus 905: case 't':
906: key_type_name = optarg;
907: break;
1.60.2.1! jason 908: case 'D':
! 909: download = 1;
! 910: case 'U':
! 911: reader_id = optarg;
! 912: break;
1.12 markus 913: case '?':
914: default:
915: usage();
916: }
917: }
918: if (optind < ac) {
919: printf("Too many arguments.\n");
920: usage();
921: }
922: if (change_passphrase && change_comment) {
923: printf("Can only have one of -p and -c.\n");
924: usage();
925: }
1.49 markus 926: if (print_fingerprint || print_bubblebabble)
1.12 markus 927: do_fingerprint(pw);
928: if (change_passphrase)
929: do_change_passphrase(pw);
930: if (change_comment)
931: do_change_comment(pw);
1.19 markus 932: if (convert_to_ssh2)
933: do_convert_to_ssh2(pw);
934: if (convert_from_ssh2)
935: do_convert_from_ssh2(pw);
936: if (print_public)
937: do_print_public(pw);
1.60.2.1! jason 938: if (reader_id != NULL) {
! 939: #ifdef SMARTCARD
! 940: if (download)
! 941: do_download(pw, reader_id);
! 942: else
! 943: do_upload(pw, reader_id);
! 944: #else /* SMARTCARD */
! 945: fatal("no support for smartcards.");
! 946: #endif /* SMARTCARD */
! 947: }
1.12 markus 948:
949: arc4random_stir();
950:
1.35 markus 951: type = key_type_from_name(key_type_name);
952: if (type == KEY_UNSPEC) {
953: fprintf(stderr, "unknown key type %s\n", key_type_name);
954: exit(1);
1.19 markus 955: }
1.33 markus 956: if (!quiet)
1.35 markus 957: printf("Generating public/private %s key pair.\n", key_type_name);
1.33 markus 958: private = key_generate(type, bits);
959: if (private == NULL) {
960: fprintf(stderr, "key_generate failed");
961: exit(1);
962: }
963: public = key_from_private(private);
1.12 markus 964:
965: if (!have_identity)
966: ask_filename(pw, "Enter file in which to save the key");
967:
968: /* Create ~/.ssh directory if it doesn\'t already exist. */
1.40 markus 969: snprintf(dotsshdir, sizeof dotsshdir, "%s/%s", pw->pw_dir, _PATH_SSH_USER_DIR);
1.12 markus 970: if (strstr(identity_file, dotsshdir) != NULL &&
971: stat(dotsshdir, &st) < 0) {
1.29 djm 972: if (mkdir(dotsshdir, 0700) < 0)
1.12 markus 973: error("Could not create directory '%s'.", dotsshdir);
974: else if (!quiet)
975: printf("Created directory '%s'.\n", dotsshdir);
976: }
977: /* If the file already exists, ask the user to confirm. */
978: if (stat(identity_file, &st) >= 0) {
979: char yesno[3];
980: printf("%s already exists.\n", identity_file);
981: printf("Overwrite (y/n)? ");
982: fflush(stdout);
983: if (fgets(yesno, sizeof(yesno), stdin) == NULL)
984: exit(1);
985: if (yesno[0] != 'y' && yesno[0] != 'Y')
986: exit(1);
987: }
988: /* Ask for a passphrase (twice). */
989: if (identity_passphrase)
990: passphrase1 = xstrdup(identity_passphrase);
991: else if (identity_new_passphrase)
992: passphrase1 = xstrdup(identity_new_passphrase);
993: else {
994: passphrase_again:
995: passphrase1 =
1.60.2.1! jason 996: read_passphrase("Enter passphrase (empty for no "
! 997: "passphrase): ", RP_ALLOW_STDIN);
! 998: passphrase2 = read_passphrase("Enter same passphrase again: ",
! 999: RP_ALLOW_STDIN);
1.12 markus 1000: if (strcmp(passphrase1, passphrase2) != 0) {
1.60.2.1! jason 1001: /*
! 1002: * The passphrases do not match. Clear them and
! 1003: * retry.
! 1004: */
1.12 markus 1005: memset(passphrase1, 0, strlen(passphrase1));
1006: memset(passphrase2, 0, strlen(passphrase2));
1007: xfree(passphrase1);
1008: xfree(passphrase2);
1009: printf("Passphrases do not match. Try again.\n");
1010: goto passphrase_again;
1011: }
1012: /* Clear the other copy of the passphrase. */
1013: memset(passphrase2, 0, strlen(passphrase2));
1014: xfree(passphrase2);
1015: }
1016:
1017: if (identity_comment) {
1018: strlcpy(comment, identity_comment, sizeof(comment));
1019: } else {
1.18 markus 1020: /* Create default commend field for the passphrase. */
1.12 markus 1021: snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname);
1022: }
1023:
1024: /* Save the key with the given passphrase and comment. */
1.52 markus 1025: if (!key_save_private(private, identity_file, passphrase1, comment)) {
1.56 markus 1026: printf("Saving the key failed: %s.\n", identity_file);
1.12 markus 1027: memset(passphrase1, 0, strlen(passphrase1));
1028: xfree(passphrase1);
1029: exit(1);
1030: }
1031: /* Clear the passphrase. */
1032: memset(passphrase1, 0, strlen(passphrase1));
1033: xfree(passphrase1);
1034:
1035: /* Clear the private key and the random number generator. */
1.33 markus 1036: key_free(private);
1.12 markus 1037: arc4random_stir();
1038:
1039: if (!quiet)
1040: printf("Your identification has been saved in %s.\n", identity_file);
1041:
1042: strlcat(identity_file, ".pub", sizeof(identity_file));
1.46 deraadt 1043: fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
1044: if (fd == -1) {
1.12 markus 1045: printf("Could not save your public key in %s\n", identity_file);
1.46 deraadt 1046: exit(1);
1047: }
1048: f = fdopen(fd, "w");
1049: if (f == NULL) {
1050: printf("fdopen %s failed", identity_file);
1.12 markus 1051: exit(1);
1052: }
1.19 markus 1053: if (!key_write(public, f))
1054: fprintf(stderr, "write key failed");
1055: fprintf(f, " %s\n", comment);
1.12 markus 1056: fclose(f);
1057:
1058: if (!quiet) {
1.50 markus 1059: char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX);
1.19 markus 1060: printf("Your public key has been saved in %s.\n",
1061: identity_file);
1.12 markus 1062: printf("The key fingerprint is:\n");
1.50 markus 1063: printf("%s %s\n", fp, comment);
1064: xfree(fp);
1.12 markus 1065: }
1.19 markus 1066:
1067: key_free(public);
1.12 markus 1068: exit(0);
1.1 deraadt 1069: }