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