ssh-keygen.c revision 149749
153943Sache/*
231022Sache * Author: Tatu Ylonen <ylo@cs.hut.fi>
3174990Sache * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
431022Sache *                    All rights reserved
5135535Spjd * Identity and host key generation and maintenance.
6135535Spjd *
7135535Spjd * As far as I am concerned, the code I have written for this software
8135535Spjd * can be used freely for any purpose.  Any derived versions of this
9135535Spjd * software must be clearly marked as such, and if the derived work is
10135535Spjd * incompatible with the protocol description in the RFC file, it must be
11135535Spjd * called by a name other than "ssh" or "Secure Shell".
12135535Spjd */
13135535Spjd
14135535Spjd#include "includes.h"
15135535SpjdRCSID("$OpenBSD: ssh-keygen.c,v 1.128 2005/07/17 07:17:55 djm Exp $");
16135535Spjd
1731022Sache#include <openssl/evp.h>
18174990Sache#include <openssl/pem.h>
1931022Sache
20135535Spjd#include "xmalloc.h"
21135535Spjd#include "key.h"
22135535Spjd#include "rsa.h"
23135535Spjd#include "authfile.h"
24135535Spjd#include "uuencode.h"
25135535Spjd#include "buffer.h"
26135535Spjd#include "bufaux.h"
27135535Spjd#include "pathnames.h"
28135535Spjd#include "log.h"
29135535Spjd#include "misc.h"
30135535Spjd#include "match.h"
31135535Spjd#include "hostfile.h"
3231022Sache
3331022Sache#ifdef SMARTCARD
3431022Sache#include "scard.h"
35219091Sversus#endif
36135535Spjd#include "dns.h"
37135535Spjd
38135535Spjd/* Number of bits in the RSA/DSA key.  This value can be changed on the command line. */
39135535Spjdu_int32_t bits = 2048;
40219091Sversus
41135535Spjd/*
4231022Sache * Flag indicating that we just want to change the passphrase.  This can be
4331022Sache * set on the command line.
4431022Sache */
45135535Spjdint change_passphrase = 0;
46135535Spjd
47135535Spjd/*
48135535Spjd * Flag indicating that we just want to change the comment.  This can be set
49135535Spjd * on the command line.
50135535Spjd */
51135535Spjdint change_comment = 0;
5231022Sache
5331022Sacheint quiet = 0;
5431022Sache
5531022Sache/* Flag indicating that we want to hash a known_hosts file */
5631022Sacheint hash_hosts = 0;
5731022Sache/* Flag indicating that we want lookup a host in known_hosts file */
5831022Sacheint find_host = 0;
5974570Sache/* Flag indicating that we want to delete a host from a known_hosts file */
6031022Sacheint delete_host = 0;
6131022Sache
6231022Sache/* Flag indicating that we just want to see the key fingerprint */
6354090Sacheint print_fingerprint = 0;
6431022Sacheint print_bubblebabble = 0;
6531022Sache
6631022Sache/* The identity file name, given on the command line or entered by the user. */
6731022Sachechar identity_file[1024];
6831022Sacheint have_identity = 0;
6931022Sache
7031022Sache/* This is set to the passphrase if given on the command line. */
7131022Sachechar *identity_passphrase = NULL;
7231022Sache
7331022Sache/* This is set to the new passphrase if given on the command line. */
7431022Sachechar *identity_new_passphrase = NULL;
75193958Sedwin
7653943Sache/* This is set to the new comment if given on the command line. */
77174990Sachechar *identity_comment = NULL;
7853943Sache
79135535Spjd/* Dump public key file in format used by real and the original SSH 2 */
80135535Spjdint convert_to_ssh2 = 0;
81135535Spjdint convert_from_ssh2 = 0;
82135535Spjdint print_public = 0;
83135535Spjdint print_generic = 0;
84135535Spjd
85135535Spjdchar *key_type_name = NULL;
86135535Spjd
87135535Spjd/* argv0 */
88135535Spjdextern char *__progname;
89135535Spjd
90135535Spjdchar hostname[MAXHOSTNAMELEN];
9153943Sache
9274413Sache/* moduli.c */
9353943Sacheint gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *);
9474413Sacheint prime_test(FILE *, FILE *, u_int32_t, u_int32_t);
9553961Sache
9673361Sachestatic void
9773361Sacheask_filename(struct passwd *pw, const char *prompt)
9873361Sache{
9973361Sache	char buf[1024];
100	char *name = NULL;
101
102	if (key_type_name == NULL)
103		name = _PATH_SSH_CLIENT_ID_RSA;
104	else
105		switch (key_type_from_name(key_type_name)) {
106		case KEY_RSA1:
107			name = _PATH_SSH_CLIENT_IDENTITY;
108			break;
109		case KEY_DSA:
110			name = _PATH_SSH_CLIENT_ID_DSA;
111			break;
112		case KEY_RSA:
113			name = _PATH_SSH_CLIENT_ID_RSA;
114			break;
115		default:
116			fprintf(stderr, "bad key type");
117			exit(1);
118			break;
119		}
120
121	snprintf(identity_file, sizeof(identity_file), "%s/%s", pw->pw_dir, name);
122	fprintf(stderr, "%s (%s): ", prompt, identity_file);
123	if (fgets(buf, sizeof(buf), stdin) == NULL)
124		exit(1);
125	if (strchr(buf, '\n'))
126		*strchr(buf, '\n') = 0;
127	if (strcmp(buf, "") != 0)
128		strlcpy(identity_file, buf, sizeof(identity_file));
129	have_identity = 1;
130}
131
132static Key *
133load_identity(char *filename)
134{
135	char *pass;
136	Key *prv;
137
138	prv = key_load_private(filename, "", NULL);
139	if (prv == NULL) {
140		if (identity_passphrase)
141			pass = xstrdup(identity_passphrase);
142		else
143			pass = read_passphrase("Enter passphrase: ",
144			    RP_ALLOW_STDIN);
145		prv = key_load_private(filename, pass, NULL);
146		memset(pass, 0, strlen(pass));
147		xfree(pass);
148	}
149	return prv;
150}
151
152#define SSH_COM_PUBLIC_BEGIN		"---- BEGIN SSH2 PUBLIC KEY ----"
153#define SSH_COM_PUBLIC_END		"---- END SSH2 PUBLIC KEY ----"
154#define SSH_COM_PRIVATE_BEGIN		"---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"
155#define	SSH_COM_PRIVATE_KEY_MAGIC	0x3f6ff9eb
156
157static void
158do_convert_to_ssh2(struct passwd *pw)
159{
160	Key *k;
161	u_int len;
162	u_char *blob;
163	struct stat st;
164
165	if (!have_identity)
166		ask_filename(pw, "Enter file in which the key is");
167	if (stat(identity_file, &st) < 0) {
168		perror(identity_file);
169		exit(1);
170	}
171	if ((k = key_load_public(identity_file, NULL)) == NULL) {
172		if ((k = load_identity(identity_file)) == NULL) {
173			fprintf(stderr, "load failed\n");
174			exit(1);
175		}
176	}
177	if (k->type == KEY_RSA1) {
178		fprintf(stderr, "version 1 keys are not supported\n");
179		exit(1);
180	}
181	if (key_to_blob(k, &blob, &len) <= 0) {
182		fprintf(stderr, "key_to_blob failed\n");
183		exit(1);
184	}
185	fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN);
186	fprintf(stdout,
187	    "Comment: \"%u-bit %s, converted from OpenSSH by %s@%s\"\n",
188	    key_size(k), key_type(k),
189	    pw->pw_name, hostname);
190	dump_base64(stdout, blob, len);
191	fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END);
192	key_free(k);
193	xfree(blob);
194	exit(0);
195}
196
197static void
198buffer_get_bignum_bits(Buffer *b, BIGNUM *value)
199{
200	u_int bignum_bits = buffer_get_int(b);
201	u_int bytes = (bignum_bits + 7) / 8;
202
203	if (buffer_len(b) < bytes)
204		fatal("buffer_get_bignum_bits: input buffer too small: "
205		    "need %d have %d", bytes, buffer_len(b));
206	BN_bin2bn(buffer_ptr(b), bytes, value);
207	buffer_consume(b, bytes);
208}
209
210static Key *
211do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
212{
213	Buffer b;
214	Key *key = NULL;
215	char *type, *cipher;
216	u_char *sig, data[] = "abcde12345";
217	int magic, rlen, ktype, i1, i2, i3, i4;
218	u_int slen;
219	u_long e;
220
221	buffer_init(&b);
222	buffer_append(&b, blob, blen);
223
224	magic  = buffer_get_int(&b);
225	if (magic != SSH_COM_PRIVATE_KEY_MAGIC) {
226		error("bad magic 0x%x != 0x%x", magic, SSH_COM_PRIVATE_KEY_MAGIC);
227		buffer_free(&b);
228		return NULL;
229	}
230	i1 = buffer_get_int(&b);
231	type   = buffer_get_string(&b, NULL);
232	cipher = buffer_get_string(&b, NULL);
233	i2 = buffer_get_int(&b);
234	i3 = buffer_get_int(&b);
235	i4 = buffer_get_int(&b);
236	debug("ignore (%d %d %d %d)", i1,i2,i3,i4);
237	if (strcmp(cipher, "none") != 0) {
238		error("unsupported cipher %s", cipher);
239		xfree(cipher);
240		buffer_free(&b);
241		xfree(type);
242		return NULL;
243	}
244	xfree(cipher);
245
246	if (strstr(type, "dsa")) {
247		ktype = KEY_DSA;
248	} else if (strstr(type, "rsa")) {
249		ktype = KEY_RSA;
250	} else {
251		buffer_free(&b);
252		xfree(type);
253		return NULL;
254	}
255	key = key_new_private(ktype);
256	xfree(type);
257
258	switch (key->type) {
259	case KEY_DSA:
260		buffer_get_bignum_bits(&b, key->dsa->p);
261		buffer_get_bignum_bits(&b, key->dsa->g);
262		buffer_get_bignum_bits(&b, key->dsa->q);
263		buffer_get_bignum_bits(&b, key->dsa->pub_key);
264		buffer_get_bignum_bits(&b, key->dsa->priv_key);
265		break;
266	case KEY_RSA:
267		e  = buffer_get_char(&b);
268		debug("e %lx", e);
269		if (e < 30) {
270			e <<= 8;
271			e += buffer_get_char(&b);
272			debug("e %lx", e);
273			e <<= 8;
274			e += buffer_get_char(&b);
275			debug("e %lx", e);
276		}
277		if (!BN_set_word(key->rsa->e, e)) {
278			buffer_free(&b);
279			key_free(key);
280			return NULL;
281		}
282		buffer_get_bignum_bits(&b, key->rsa->d);
283		buffer_get_bignum_bits(&b, key->rsa->n);
284		buffer_get_bignum_bits(&b, key->rsa->iqmp);
285		buffer_get_bignum_bits(&b, key->rsa->q);
286		buffer_get_bignum_bits(&b, key->rsa->p);
287		rsa_generate_additional_parameters(key->rsa);
288		break;
289	}
290	rlen = buffer_len(&b);
291	if (rlen != 0)
292		error("do_convert_private_ssh2_from_blob: "
293		    "remaining bytes in key blob %d", rlen);
294	buffer_free(&b);
295
296	/* try the key */
297	key_sign(key, &sig, &slen, data, sizeof(data));
298	key_verify(key, sig, slen, data, sizeof(data));
299	xfree(sig);
300	return key;
301}
302
303static void
304do_convert_from_ssh2(struct passwd *pw)
305{
306	Key *k;
307	int blen;
308	u_int len;
309	char line[1024], *p;
310	u_char blob[8096];
311	char encoded[8096];
312	struct stat st;
313	int escaped = 0, private = 0, ok;
314	FILE *fp;
315
316	if (!have_identity)
317		ask_filename(pw, "Enter file in which the key is");
318	if (stat(identity_file, &st) < 0) {
319		perror(identity_file);
320		exit(1);
321	}
322	fp = fopen(identity_file, "r");
323	if (fp == NULL) {
324		perror(identity_file);
325		exit(1);
326	}
327	encoded[0] = '\0';
328	while (fgets(line, sizeof(line), fp)) {
329		if (!(p = strchr(line, '\n'))) {
330			fprintf(stderr, "input line too long.\n");
331			exit(1);
332		}
333		if (p > line && p[-1] == '\\')
334			escaped++;
335		if (strncmp(line, "----", 4) == 0 ||
336		    strstr(line, ": ") != NULL) {
337			if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL)
338				private = 1;
339			if (strstr(line, " END ") != NULL) {
340				break;
341			}
342			/* fprintf(stderr, "ignore: %s", line); */
343			continue;
344		}
345		if (escaped) {
346			escaped--;
347			/* fprintf(stderr, "escaped: %s", line); */
348			continue;
349		}
350		*p = '\0';
351		strlcat(encoded, line, sizeof(encoded));
352	}
353	len = strlen(encoded);
354	if (((len % 4) == 3) &&
355	    (encoded[len-1] == '=') &&
356	    (encoded[len-2] == '=') &&
357	    (encoded[len-3] == '='))
358		encoded[len-3] = '\0';
359	blen = uudecode(encoded, blob, sizeof(blob));
360	if (blen < 0) {
361		fprintf(stderr, "uudecode failed.\n");
362		exit(1);
363	}
364	k = private ?
365	    do_convert_private_ssh2_from_blob(blob, blen) :
366	    key_from_blob(blob, blen);
367	if (k == NULL) {
368		fprintf(stderr, "decode blob failed.\n");
369		exit(1);
370	}
371	ok = private ?
372	    (k->type == KEY_DSA ?
373		 PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, NULL, 0, NULL, NULL) :
374		 PEM_write_RSAPrivateKey(stdout, k->rsa, NULL, NULL, 0, NULL, NULL)) :
375	    key_write(k, stdout);
376	if (!ok) {
377		fprintf(stderr, "key write failed");
378		exit(1);
379	}
380	key_free(k);
381	if (!private)
382		fprintf(stdout, "\n");
383	fclose(fp);
384	exit(0);
385}
386
387static void
388do_print_public(struct passwd *pw)
389{
390	Key *prv;
391	struct stat st;
392
393	if (!have_identity)
394		ask_filename(pw, "Enter file in which the key is");
395	if (stat(identity_file, &st) < 0) {
396		perror(identity_file);
397		exit(1);
398	}
399	prv = load_identity(identity_file);
400	if (prv == NULL) {
401		fprintf(stderr, "load failed\n");
402		exit(1);
403	}
404	if (!key_write(prv, stdout))
405		fprintf(stderr, "key_write failed");
406	key_free(prv);
407	fprintf(stdout, "\n");
408	exit(0);
409}
410
411#ifdef SMARTCARD
412static void
413do_upload(struct passwd *pw, const char *sc_reader_id)
414{
415	Key *prv = NULL;
416	struct stat st;
417	int ret;
418
419	if (!have_identity)
420		ask_filename(pw, "Enter file in which the key is");
421	if (stat(identity_file, &st) < 0) {
422		perror(identity_file);
423		exit(1);
424	}
425	prv = load_identity(identity_file);
426	if (prv == NULL) {
427		error("load failed");
428		exit(1);
429	}
430	ret = sc_put_key(prv, sc_reader_id);
431	key_free(prv);
432	if (ret < 0)
433		exit(1);
434	logit("loading key done");
435	exit(0);
436}
437
438static void
439do_download(struct passwd *pw, const char *sc_reader_id)
440{
441	Key **keys = NULL;
442	int i;
443
444	keys = sc_get_keys(sc_reader_id, NULL);
445	if (keys == NULL)
446		fatal("cannot read public key from smartcard");
447	for (i = 0; keys[i]; i++) {
448		key_write(keys[i], stdout);
449		key_free(keys[i]);
450		fprintf(stdout, "\n");
451	}
452	xfree(keys);
453	exit(0);
454}
455#endif /* SMARTCARD */
456
457static void
458do_fingerprint(struct passwd *pw)
459{
460	FILE *f;
461	Key *public;
462	char *comment = NULL, *cp, *ep, line[16*1024], *fp;
463	int i, skip = 0, num = 1, invalid = 1;
464	enum fp_rep rep;
465	enum fp_type fptype;
466	struct stat st;
467
468	fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
469	rep =    print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
470
471	if (!have_identity)
472		ask_filename(pw, "Enter file in which the key is");
473	if (stat(identity_file, &st) < 0) {
474		perror(identity_file);
475		exit(1);
476	}
477	public = key_load_public(identity_file, &comment);
478	if (public != NULL) {
479		fp = key_fingerprint(public, fptype, rep);
480		printf("%u %s %s\n", key_size(public), fp, comment);
481		key_free(public);
482		xfree(comment);
483		xfree(fp);
484		exit(0);
485	}
486	if (comment)
487		xfree(comment);
488
489	f = fopen(identity_file, "r");
490	if (f != NULL) {
491		while (fgets(line, sizeof(line), f)) {
492			i = strlen(line) - 1;
493			if (line[i] != '\n') {
494				error("line %d too long: %.40s...", num, line);
495				skip = 1;
496				continue;
497			}
498			num++;
499			if (skip) {
500				skip = 0;
501				continue;
502			}
503			line[i] = '\0';
504
505			/* Skip leading whitespace, empty and comment lines. */
506			for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
507				;
508			if (!*cp || *cp == '\n' || *cp == '#')
509				continue ;
510			i = strtol(cp, &ep, 10);
511			if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) {
512				int quoted = 0;
513				comment = cp;
514				for (; *cp && (quoted || (*cp != ' ' &&
515				    *cp != '\t')); cp++) {
516					if (*cp == '\\' && cp[1] == '"')
517						cp++;	/* Skip both */
518					else if (*cp == '"')
519						quoted = !quoted;
520				}
521				if (!*cp)
522					continue;
523				*cp++ = '\0';
524			}
525			ep = cp;
526			public = key_new(KEY_RSA1);
527			if (key_read(public, &cp) != 1) {
528				cp = ep;
529				key_free(public);
530				public = key_new(KEY_UNSPEC);
531				if (key_read(public, &cp) != 1) {
532					key_free(public);
533					continue;
534				}
535			}
536			comment = *cp ? cp : comment;
537			fp = key_fingerprint(public, fptype, rep);
538			printf("%u %s %s\n", key_size(public), fp,
539			    comment ? comment : "no comment");
540			xfree(fp);
541			key_free(public);
542			invalid = 0;
543		}
544		fclose(f);
545	}
546	if (invalid) {
547		printf("%s is not a public key file.\n", identity_file);
548		exit(1);
549	}
550	exit(0);
551}
552
553static void
554print_host(FILE *f, char *name, Key *public, int hash)
555{
556	if (hash && (name = host_hash(name, NULL, 0)) == NULL)
557		fatal("hash_host failed");
558	fprintf(f, "%s ", name);
559	if (!key_write(public, f))
560		fatal("key_write failed");
561	fprintf(f, "\n");
562}
563
564static void
565do_known_hosts(struct passwd *pw, const char *name)
566{
567	FILE *in, *out = stdout;
568	Key *public;
569	char *cp, *cp2, *kp, *kp2;
570	char line[16*1024], tmp[MAXPATHLEN], old[MAXPATHLEN];
571	int c, i, skip = 0, inplace = 0, num = 0, invalid = 0, has_unhashed = 0;
572
573	if (!have_identity) {
574		cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid);
575		if (strlcpy(identity_file, cp, sizeof(identity_file)) >=
576		    sizeof(identity_file))
577			fatal("Specified known hosts path too long");
578		xfree(cp);
579		have_identity = 1;
580	}
581	if ((in = fopen(identity_file, "r")) == NULL)
582		fatal("fopen: %s", strerror(errno));
583
584	/*
585	 * Find hosts goes to stdout, hash and deletions happen in-place
586	 * A corner case is ssh-keygen -HF foo, which should go to stdout
587	 */
588	if (!find_host && (hash_hosts || delete_host)) {
589		if (strlcpy(tmp, identity_file, sizeof(tmp)) >= sizeof(tmp) ||
590		    strlcat(tmp, ".XXXXXXXXXX", sizeof(tmp)) >= sizeof(tmp) ||
591		    strlcpy(old, identity_file, sizeof(old)) >= sizeof(old) ||
592		    strlcat(old, ".old", sizeof(old)) >= sizeof(old))
593			fatal("known_hosts path too long");
594		umask(077);
595		if ((c = mkstemp(tmp)) == -1)
596			fatal("mkstemp: %s", strerror(errno));
597		if ((out = fdopen(c, "w")) == NULL) {
598			c = errno;
599			unlink(tmp);
600			fatal("fdopen: %s", strerror(c));
601		}
602		inplace = 1;
603	}
604
605	while (fgets(line, sizeof(line), in)) {
606		num++;
607		i = strlen(line) - 1;
608		if (line[i] != '\n') {
609			error("line %d too long: %.40s...", num, line);
610			skip = 1;
611			invalid = 1;
612			continue;
613		}
614		if (skip) {
615			skip = 0;
616			continue;
617		}
618		line[i] = '\0';
619
620		/* Skip leading whitespace, empty and comment lines. */
621		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
622			;
623		if (!*cp || *cp == '\n' || *cp == '#') {
624			if (inplace)
625				fprintf(out, "%s\n", cp);
626			continue;
627		}
628		/* Find the end of the host name portion. */
629		for (kp = cp; *kp && *kp != ' ' && *kp != '\t'; kp++)
630			;
631		if (*kp == '\0' || *(kp + 1) == '\0') {
632			error("line %d missing key: %.40s...",
633			    num, line);
634			invalid = 1;
635			continue;
636		}
637		*kp++ = '\0';
638		kp2 = kp;
639
640		public = key_new(KEY_RSA1);
641		if (key_read(public, &kp) != 1) {
642			kp = kp2;
643			key_free(public);
644			public = key_new(KEY_UNSPEC);
645			if (key_read(public, &kp) != 1) {
646				error("line %d invalid key: %.40s...",
647				    num, line);
648				key_free(public);
649				invalid = 1;
650				continue;
651			}
652		}
653
654		if (*cp == HASH_DELIM) {
655			if (find_host || delete_host) {
656				cp2 = host_hash(name, cp, strlen(cp));
657				if (cp2 == NULL) {
658					error("line %d: invalid hashed "
659					    "name: %.64s...", num, line);
660					invalid = 1;
661					continue;
662				}
663				c = (strcmp(cp2, cp) == 0);
664				if (find_host && c) {
665					printf("# Host %s found: "
666					    "line %d type %s\n", name,
667					    num, key_type(public));
668					print_host(out, cp, public, 0);
669				}
670				if (delete_host && !c)
671					print_host(out, cp, public, 0);
672			} else if (hash_hosts)
673				print_host(out, cp, public, 0);
674		} else {
675			if (find_host || delete_host) {
676				c = (match_hostname(name, cp,
677				    strlen(cp)) == 1);
678				if (find_host && c) {
679					printf("# Host %s found: "
680					    "line %d type %s\n", name,
681					    num, key_type(public));
682					print_host(out, cp, public, hash_hosts);
683				}
684				if (delete_host && !c)
685					print_host(out, cp, public, 0);
686			} else if (hash_hosts) {
687				for (cp2 = strsep(&cp, ",");
688				    cp2 != NULL && *cp2 != '\0';
689				    cp2 = strsep(&cp, ",")) {
690					if (strcspn(cp2, "*?!") != strlen(cp2))
691						fprintf(stderr, "Warning: "
692						    "ignoring host name with "
693						    "metacharacters: %.64s\n",
694						    cp2);
695					else
696						print_host(out, cp2, public, 1);
697				}
698				has_unhashed = 1;
699			}
700		}
701		key_free(public);
702	}
703	fclose(in);
704
705	if (invalid) {
706		fprintf(stderr, "%s is not a valid known_host file.\n",
707		    identity_file);
708		if (inplace) {
709			fprintf(stderr, "Not replacing existing known_hosts "
710			    "file because of errors\n");
711			fclose(out);
712			unlink(tmp);
713		}
714		exit(1);
715	}
716
717	if (inplace) {
718		fclose(out);
719
720		/* Backup existing file */
721		if (unlink(old) == -1 && errno != ENOENT)
722			fatal("unlink %.100s: %s", old, strerror(errno));
723		if (link(identity_file, old) == -1)
724			fatal("link %.100s to %.100s: %s", identity_file, old,
725			    strerror(errno));
726		/* Move new one into place */
727		if (rename(tmp, identity_file) == -1) {
728			error("rename\"%s\" to \"%s\": %s", tmp, identity_file,
729			    strerror(errno));
730			unlink(tmp);
731			unlink(old);
732			exit(1);
733		}
734
735		fprintf(stderr, "%s updated.\n", identity_file);
736		fprintf(stderr, "Original contents retained as %s\n", old);
737		if (has_unhashed) {
738			fprintf(stderr, "WARNING: %s contains unhashed "
739			    "entries\n", old);
740			fprintf(stderr, "Delete this file to ensure privacy "
741			    "of hostnames\n");
742		}
743	}
744
745	exit(0);
746}
747
748/*
749 * Perform changing a passphrase.  The argument is the passwd structure
750 * for the current user.
751 */
752static void
753do_change_passphrase(struct passwd *pw)
754{
755	char *comment;
756	char *old_passphrase, *passphrase1, *passphrase2;
757	struct stat st;
758	Key *private;
759
760	if (!have_identity)
761		ask_filename(pw, "Enter file in which the key is");
762	if (stat(identity_file, &st) < 0) {
763		perror(identity_file);
764		exit(1);
765	}
766	/* Try to load the file with empty passphrase. */
767	private = key_load_private(identity_file, "", &comment);
768	if (private == NULL) {
769		if (identity_passphrase)
770			old_passphrase = xstrdup(identity_passphrase);
771		else
772			old_passphrase =
773			    read_passphrase("Enter old passphrase: ",
774			    RP_ALLOW_STDIN);
775		private = key_load_private(identity_file, old_passphrase,
776		    &comment);
777		memset(old_passphrase, 0, strlen(old_passphrase));
778		xfree(old_passphrase);
779		if (private == NULL) {
780			printf("Bad passphrase.\n");
781			exit(1);
782		}
783	}
784	printf("Key has comment '%s'\n", comment);
785
786	/* Ask the new passphrase (twice). */
787	if (identity_new_passphrase) {
788		passphrase1 = xstrdup(identity_new_passphrase);
789		passphrase2 = NULL;
790	} else {
791		passphrase1 =
792			read_passphrase("Enter new passphrase (empty for no "
793			    "passphrase): ", RP_ALLOW_STDIN);
794		passphrase2 = read_passphrase("Enter same passphrase again: ",
795		    RP_ALLOW_STDIN);
796
797		/* Verify that they are the same. */
798		if (strcmp(passphrase1, passphrase2) != 0) {
799			memset(passphrase1, 0, strlen(passphrase1));
800			memset(passphrase2, 0, strlen(passphrase2));
801			xfree(passphrase1);
802			xfree(passphrase2);
803			printf("Pass phrases do not match.  Try again.\n");
804			exit(1);
805		}
806		/* Destroy the other copy. */
807		memset(passphrase2, 0, strlen(passphrase2));
808		xfree(passphrase2);
809	}
810
811	/* Save the file using the new passphrase. */
812	if (!key_save_private(private, identity_file, passphrase1, comment)) {
813		printf("Saving the key failed: %s.\n", identity_file);
814		memset(passphrase1, 0, strlen(passphrase1));
815		xfree(passphrase1);
816		key_free(private);
817		xfree(comment);
818		exit(1);
819	}
820	/* Destroy the passphrase and the copy of the key in memory. */
821	memset(passphrase1, 0, strlen(passphrase1));
822	xfree(passphrase1);
823	key_free(private);		 /* Destroys contents */
824	xfree(comment);
825
826	printf("Your identification has been saved with the new passphrase.\n");
827	exit(0);
828}
829
830/*
831 * Print the SSHFP RR.
832 */
833static void
834do_print_resource_record(struct passwd *pw, char *hname)
835{
836	Key *public;
837	char *comment = NULL;
838	struct stat st;
839
840	if (!have_identity)
841		ask_filename(pw, "Enter file in which the key is");
842	if (stat(identity_file, &st) < 0) {
843		perror(identity_file);
844		exit(1);
845	}
846	public = key_load_public(identity_file, &comment);
847	if (public != NULL) {
848		export_dns_rr(hname, public, stdout, print_generic);
849		key_free(public);
850		xfree(comment);
851		exit(0);
852	}
853	if (comment)
854		xfree(comment);
855
856	printf("failed to read v2 public key from %s.\n", identity_file);
857	exit(1);
858}
859
860/*
861 * Change the comment of a private key file.
862 */
863static void
864do_change_comment(struct passwd *pw)
865{
866	char new_comment[1024], *comment, *passphrase;
867	Key *private;
868	Key *public;
869	struct stat st;
870	FILE *f;
871	int fd;
872
873	if (!have_identity)
874		ask_filename(pw, "Enter file in which the key is");
875	if (stat(identity_file, &st) < 0) {
876		perror(identity_file);
877		exit(1);
878	}
879	private = key_load_private(identity_file, "", &comment);
880	if (private == NULL) {
881		if (identity_passphrase)
882			passphrase = xstrdup(identity_passphrase);
883		else if (identity_new_passphrase)
884			passphrase = xstrdup(identity_new_passphrase);
885		else
886			passphrase = read_passphrase("Enter passphrase: ",
887			    RP_ALLOW_STDIN);
888		/* Try to load using the passphrase. */
889		private = key_load_private(identity_file, passphrase, &comment);
890		if (private == NULL) {
891			memset(passphrase, 0, strlen(passphrase));
892			xfree(passphrase);
893			printf("Bad passphrase.\n");
894			exit(1);
895		}
896	} else {
897		passphrase = xstrdup("");
898	}
899	if (private->type != KEY_RSA1) {
900		fprintf(stderr, "Comments are only supported for RSA1 keys.\n");
901		key_free(private);
902		exit(1);
903	}
904	printf("Key now has comment '%s'\n", comment);
905
906	if (identity_comment) {
907		strlcpy(new_comment, identity_comment, sizeof(new_comment));
908	} else {
909		printf("Enter new comment: ");
910		fflush(stdout);
911		if (!fgets(new_comment, sizeof(new_comment), stdin)) {
912			memset(passphrase, 0, strlen(passphrase));
913			key_free(private);
914			exit(1);
915		}
916		if (strchr(new_comment, '\n'))
917			*strchr(new_comment, '\n') = 0;
918	}
919
920	/* Save the file using the new passphrase. */
921	if (!key_save_private(private, identity_file, passphrase, new_comment)) {
922		printf("Saving the key failed: %s.\n", identity_file);
923		memset(passphrase, 0, strlen(passphrase));
924		xfree(passphrase);
925		key_free(private);
926		xfree(comment);
927		exit(1);
928	}
929	memset(passphrase, 0, strlen(passphrase));
930	xfree(passphrase);
931	public = key_from_private(private);
932	key_free(private);
933
934	strlcat(identity_file, ".pub", sizeof(identity_file));
935	fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
936	if (fd == -1) {
937		printf("Could not save your public key in %s\n", identity_file);
938		exit(1);
939	}
940	f = fdopen(fd, "w");
941	if (f == NULL) {
942		printf("fdopen %s failed", identity_file);
943		exit(1);
944	}
945	if (!key_write(public, f))
946		fprintf(stderr, "write key failed");
947	key_free(public);
948	fprintf(f, " %s\n", new_comment);
949	fclose(f);
950
951	xfree(comment);
952
953	printf("The comment in your key file has been changed.\n");
954	exit(0);
955}
956
957static void
958usage(void)
959{
960	fprintf(stderr, "Usage: %s [options]\n", __progname);
961	fprintf(stderr, "Options:\n");
962	fprintf(stderr, "  -a trials   Number of trials for screening DH-GEX moduli.\n");
963	fprintf(stderr, "  -B          Show bubblebabble digest of key file.\n");
964	fprintf(stderr, "  -b bits     Number of bits in the key to create.\n");
965	fprintf(stderr, "  -C comment  Provide new comment.\n");
966	fprintf(stderr, "  -c          Change comment in private and public key files.\n");
967#ifdef SMARTCARD
968	fprintf(stderr, "  -D reader   Download public key from smartcard.\n");
969#endif /* SMARTCARD */
970	fprintf(stderr, "  -e          Convert OpenSSH to IETF SECSH key file.\n");
971	fprintf(stderr, "  -F hostname Find hostname in known hosts file.\n");
972	fprintf(stderr, "  -f filename Filename of the key file.\n");
973	fprintf(stderr, "  -G file     Generate candidates for DH-GEX moduli.\n");
974	fprintf(stderr, "  -g          Use generic DNS resource record format.\n");
975	fprintf(stderr, "  -H          Hash names in known_hosts file.\n");
976	fprintf(stderr, "  -i          Convert IETF SECSH to OpenSSH key file.\n");
977	fprintf(stderr, "  -l          Show fingerprint of key file.\n");
978	fprintf(stderr, "  -M memory   Amount of memory (MB) to use for generating DH-GEX moduli.\n");
979	fprintf(stderr, "  -N phrase   Provide new passphrase.\n");
980	fprintf(stderr, "  -P phrase   Provide old passphrase.\n");
981	fprintf(stderr, "  -p          Change passphrase of private key file.\n");
982	fprintf(stderr, "  -q          Quiet.\n");
983	fprintf(stderr, "  -R hostname Remove host from known_hosts file.\n");
984	fprintf(stderr, "  -r hostname Print DNS resource record.\n");
985	fprintf(stderr, "  -S start    Start point (hex) for generating DH-GEX moduli.\n");
986	fprintf(stderr, "  -T file     Screen candidates for DH-GEX moduli.\n");
987	fprintf(stderr, "  -t type     Specify type of key to create.\n");
988#ifdef SMARTCARD
989	fprintf(stderr, "  -U reader   Upload private key to smartcard.\n");
990#endif /* SMARTCARD */
991	fprintf(stderr, "  -v          Verbose.\n");
992	fprintf(stderr, "  -W gen      Generator to use for generating DH-GEX moduli.\n");
993	fprintf(stderr, "  -y          Read private key file and print public key.\n");
994
995	exit(1);
996}
997
998/*
999 * Main program for key management.
1000 */
1001int
1002main(int ac, char **av)
1003{
1004	char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2;
1005	char out_file[MAXPATHLEN], *reader_id = NULL;
1006	char *rr_hostname = NULL;
1007	Key *private, *public;
1008	struct passwd *pw;
1009	struct stat st;
1010	int opt, type, fd, download = 0;
1011	u_int32_t memory = 0, generator_wanted = 0, trials = 100;
1012	int do_gen_candidates = 0, do_screen_candidates = 0;
1013	int log_level = SYSLOG_LEVEL_INFO;
1014	BIGNUM *start = NULL;
1015	FILE *f;
1016	const char *errstr;
1017
1018	extern int optind;
1019	extern char *optarg;
1020
1021	__progname = ssh_get_progname(av[0]);
1022
1023	SSLeay_add_all_algorithms();
1024	log_init(av[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
1025
1026	init_rng();
1027	seed_rng();
1028
1029	/* we need this for the home * directory.  */
1030	pw = getpwuid(getuid());
1031	if (!pw) {
1032		printf("You don't exist, go away!\n");
1033		exit(1);
1034	}
1035	if (gethostname(hostname, sizeof(hostname)) < 0) {
1036		perror("gethostname");
1037		exit(1);
1038	}
1039
1040	while ((opt = getopt(ac, av,
1041	    "degiqpclBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) {
1042		switch (opt) {
1043		case 'b':
1044			bits = strtonum(optarg, 512, 32768, &errstr);
1045			if (errstr)
1046				fatal("Bits has bad value %s (%s)",
1047					optarg, errstr);
1048			break;
1049		case 'F':
1050			find_host = 1;
1051			rr_hostname = optarg;
1052			break;
1053		case 'H':
1054			hash_hosts = 1;
1055			break;
1056		case 'R':
1057			delete_host = 1;
1058			rr_hostname = optarg;
1059			break;
1060		case 'l':
1061			print_fingerprint = 1;
1062			break;
1063		case 'B':
1064			print_bubblebabble = 1;
1065			break;
1066		case 'p':
1067			change_passphrase = 1;
1068			break;
1069		case 'c':
1070			change_comment = 1;
1071			break;
1072		case 'f':
1073			if (strlcpy(identity_file, optarg, sizeof(identity_file)) >=
1074			    sizeof(identity_file))
1075				fatal("Identity filename too long");
1076			have_identity = 1;
1077			break;
1078		case 'g':
1079			print_generic = 1;
1080			break;
1081		case 'P':
1082			identity_passphrase = optarg;
1083			break;
1084		case 'N':
1085			identity_new_passphrase = optarg;
1086			break;
1087		case 'C':
1088			identity_comment = optarg;
1089			break;
1090		case 'q':
1091			quiet = 1;
1092			break;
1093		case 'e':
1094		case 'x':
1095			/* export key */
1096			convert_to_ssh2 = 1;
1097			break;
1098		case 'i':
1099		case 'X':
1100			/* import key */
1101			convert_from_ssh2 = 1;
1102			break;
1103		case 'y':
1104			print_public = 1;
1105			break;
1106		case 'd':
1107			key_type_name = "dsa";
1108			break;
1109		case 't':
1110			key_type_name = optarg;
1111			break;
1112		case 'D':
1113			download = 1;
1114		case 'U':
1115			reader_id = optarg;
1116			break;
1117		case 'v':
1118			if (log_level == SYSLOG_LEVEL_INFO)
1119				log_level = SYSLOG_LEVEL_DEBUG1;
1120			else {
1121				if (log_level >= SYSLOG_LEVEL_DEBUG1 &&
1122				    log_level < SYSLOG_LEVEL_DEBUG3)
1123					log_level++;
1124			}
1125			break;
1126		case 'r':
1127			rr_hostname = optarg;
1128			break;
1129		case 'W':
1130			generator_wanted = strtonum(optarg, 1, UINT_MAX, &errstr);
1131			if (errstr)
1132				fatal("Desired generator has bad value: %s (%s)",
1133					optarg, errstr);
1134			break;
1135		case 'a':
1136			trials = strtonum(optarg, 1, UINT_MAX, &errstr);
1137			if (errstr)
1138				fatal("Invalid number of trials: %s (%s)",
1139					optarg, errstr);
1140			break;
1141		case 'M':
1142			memory = strtonum(optarg, 1, UINT_MAX, &errstr);
1143			if (errstr) {
1144				fatal("Memory limit is %s: %s", errstr, optarg);
1145			}
1146			break;
1147		case 'G':
1148			do_gen_candidates = 1;
1149			if (strlcpy(out_file, optarg, sizeof(out_file)) >=
1150			    sizeof(out_file))
1151				fatal("Output filename too long");
1152			break;
1153		case 'T':
1154			do_screen_candidates = 1;
1155			if (strlcpy(out_file, optarg, sizeof(out_file)) >=
1156			    sizeof(out_file))
1157				fatal("Output filename too long");
1158			break;
1159		case 'S':
1160			/* XXX - also compare length against bits */
1161			if (BN_hex2bn(&start, optarg) == 0)
1162				fatal("Invalid start point.");
1163			break;
1164		case '?':
1165		default:
1166			usage();
1167		}
1168	}
1169
1170	/* reinit */
1171	log_init(av[0], log_level, SYSLOG_FACILITY_USER, 1);
1172
1173	if (optind < ac) {
1174		printf("Too many arguments.\n");
1175		usage();
1176	}
1177	if (change_passphrase && change_comment) {
1178		printf("Can only have one of -p and -c.\n");
1179		usage();
1180	}
1181	if (delete_host || hash_hosts || find_host)
1182		do_known_hosts(pw, rr_hostname);
1183	if (print_fingerprint || print_bubblebabble)
1184		do_fingerprint(pw);
1185	if (change_passphrase)
1186		do_change_passphrase(pw);
1187	if (change_comment)
1188		do_change_comment(pw);
1189	if (convert_to_ssh2)
1190		do_convert_to_ssh2(pw);
1191	if (convert_from_ssh2)
1192		do_convert_from_ssh2(pw);
1193	if (print_public)
1194		do_print_public(pw);
1195	if (rr_hostname != NULL) {
1196		do_print_resource_record(pw, rr_hostname);
1197	}
1198	if (reader_id != NULL) {
1199#ifdef SMARTCARD
1200		if (download)
1201			do_download(pw, reader_id);
1202		else
1203			do_upload(pw, reader_id);
1204#else /* SMARTCARD */
1205		fatal("no support for smartcards.");
1206#endif /* SMARTCARD */
1207	}
1208
1209	if (do_gen_candidates) {
1210		FILE *out = fopen(out_file, "w");
1211
1212		if (out == NULL) {
1213			error("Couldn't open modulus candidate file \"%s\": %s",
1214			    out_file, strerror(errno));
1215			return (1);
1216		}
1217		if (gen_candidates(out, memory, bits, start) != 0)
1218			fatal("modulus candidate generation failed\n");
1219
1220		return (0);
1221	}
1222
1223	if (do_screen_candidates) {
1224		FILE *in;
1225		FILE *out = fopen(out_file, "w");
1226
1227		if (have_identity && strcmp(identity_file, "-") != 0) {
1228			if ((in = fopen(identity_file, "r")) == NULL) {
1229				fatal("Couldn't open modulus candidate "
1230				    "file \"%s\": %s", identity_file,
1231				    strerror(errno));
1232			}
1233		} else
1234			in = stdin;
1235
1236		if (out == NULL) {
1237			fatal("Couldn't open moduli file \"%s\": %s",
1238			    out_file, strerror(errno));
1239		}
1240		if (prime_test(in, out, trials, generator_wanted) != 0)
1241			fatal("modulus screening failed\n");
1242		return (0);
1243	}
1244
1245	arc4random_stir();
1246
1247	if (key_type_name == NULL) {
1248		printf("You must specify a key type (-t).\n");
1249		usage();
1250	}
1251	type = key_type_from_name(key_type_name);
1252	if (type == KEY_UNSPEC) {
1253		fprintf(stderr, "unknown key type %s\n", key_type_name);
1254		exit(1);
1255	}
1256	if (!quiet)
1257		printf("Generating public/private %s key pair.\n", key_type_name);
1258	private = key_generate(type, bits);
1259	if (private == NULL) {
1260		fprintf(stderr, "key_generate failed");
1261		exit(1);
1262	}
1263	public  = key_from_private(private);
1264
1265	if (!have_identity)
1266		ask_filename(pw, "Enter file in which to save the key");
1267
1268	/* Create ~/.ssh directory if it doesn\'t already exist. */
1269	snprintf(dotsshdir, sizeof dotsshdir, "%s/%s", pw->pw_dir, _PATH_SSH_USER_DIR);
1270	if (strstr(identity_file, dotsshdir) != NULL &&
1271	    stat(dotsshdir, &st) < 0) {
1272		if (mkdir(dotsshdir, 0700) < 0)
1273			error("Could not create directory '%s'.", dotsshdir);
1274		else if (!quiet)
1275			printf("Created directory '%s'.\n", dotsshdir);
1276	}
1277	/* If the file already exists, ask the user to confirm. */
1278	if (stat(identity_file, &st) >= 0) {
1279		char yesno[3];
1280		printf("%s already exists.\n", identity_file);
1281		printf("Overwrite (y/n)? ");
1282		fflush(stdout);
1283		if (fgets(yesno, sizeof(yesno), stdin) == NULL)
1284			exit(1);
1285		if (yesno[0] != 'y' && yesno[0] != 'Y')
1286			exit(1);
1287	}
1288	/* Ask for a passphrase (twice). */
1289	if (identity_passphrase)
1290		passphrase1 = xstrdup(identity_passphrase);
1291	else if (identity_new_passphrase)
1292		passphrase1 = xstrdup(identity_new_passphrase);
1293	else {
1294passphrase_again:
1295		passphrase1 =
1296			read_passphrase("Enter passphrase (empty for no "
1297			    "passphrase): ", RP_ALLOW_STDIN);
1298		passphrase2 = read_passphrase("Enter same passphrase again: ",
1299		    RP_ALLOW_STDIN);
1300		if (strcmp(passphrase1, passphrase2) != 0) {
1301			/*
1302			 * The passphrases do not match.  Clear them and
1303			 * retry.
1304			 */
1305			memset(passphrase1, 0, strlen(passphrase1));
1306			memset(passphrase2, 0, strlen(passphrase2));
1307			xfree(passphrase1);
1308			xfree(passphrase2);
1309			printf("Passphrases do not match.  Try again.\n");
1310			goto passphrase_again;
1311		}
1312		/* Clear the other copy of the passphrase. */
1313		memset(passphrase2, 0, strlen(passphrase2));
1314		xfree(passphrase2);
1315	}
1316
1317	if (identity_comment) {
1318		strlcpy(comment, identity_comment, sizeof(comment));
1319	} else {
1320		/* Create default commend field for the passphrase. */
1321		snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname);
1322	}
1323
1324	/* Save the key with the given passphrase and comment. */
1325	if (!key_save_private(private, identity_file, passphrase1, comment)) {
1326		printf("Saving the key failed: %s.\n", identity_file);
1327		memset(passphrase1, 0, strlen(passphrase1));
1328		xfree(passphrase1);
1329		exit(1);
1330	}
1331	/* Clear the passphrase. */
1332	memset(passphrase1, 0, strlen(passphrase1));
1333	xfree(passphrase1);
1334
1335	/* Clear the private key and the random number generator. */
1336	key_free(private);
1337	arc4random_stir();
1338
1339	if (!quiet)
1340		printf("Your identification has been saved in %s.\n", identity_file);
1341
1342	strlcat(identity_file, ".pub", sizeof(identity_file));
1343	fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
1344	if (fd == -1) {
1345		printf("Could not save your public key in %s\n", identity_file);
1346		exit(1);
1347	}
1348	f = fdopen(fd, "w");
1349	if (f == NULL) {
1350		printf("fdopen %s failed", identity_file);
1351		exit(1);
1352	}
1353	if (!key_write(public, f))
1354		fprintf(stderr, "write key failed");
1355	fprintf(f, " %s\n", comment);
1356	fclose(f);
1357
1358	if (!quiet) {
1359		char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX);
1360		printf("Your public key has been saved in %s.\n",
1361		    identity_file);
1362		printf("The key fingerprint is:\n");
1363		printf("%s %s\n", fp, comment);
1364		xfree(fp);
1365	}
1366
1367	key_free(public);
1368	exit(0);
1369}
1370