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