xref: /titanic_50/usr/src/cmd/ssh/ssh-keygen/ssh-keygen.c (revision c51cb4bc539e1650eb5bb4f805cc779bfce99c06)
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 /* $OpenBSD: ssh-keygen.c,v 1.160 2007/01/21 01:41:54 stevesk Exp $ */
15 
16 #pragma ident	"%Z%%M%	%I%	%E% SMI"
17 
18 #include "includes.h"
19 #include <openssl/evp.h>
20 #include <openssl/pem.h>
21 
22 #include "xmalloc.h"
23 #include "key.h"
24 #include "rsa.h"
25 #include "authfile.h"
26 #include "uuencode.h"
27 #include "buffer.h"
28 #include "bufaux.h"
29 #include "pathnames.h"
30 #include "log.h"
31 #include "readpass.h"
32 #include "misc.h"
33 #include <langinfo.h>
34 #include "match.h"
35 #include "hostfile.h"
36 #include "tildexpand.h"
37 
38 #ifdef SMARTCARD
39 #include "scard.h"
40 #endif
41 
42 /* Number of bits in the RSA/DSA key.  This value can be set on the command line. */
43 u_int32_t bits = 1024;
44 
45 /*
46  * Flag indicating that we just want to change the passphrase.  This can be
47  * set on the command line.
48  */
49 int change_passphrase = 0;
50 
51 /*
52  * Flag indicating that we just want to change the comment.  This can be set
53  * on the command line.
54  */
55 int change_comment = 0;
56 
57 int quiet = 0;
58 
59 /* Flag indicating that we want to hash a known_hosts file */
60 int hash_hosts = 0;
61 /* Flag indicating that we want to lookup a host in known_hosts file */
62 int find_host = 0;
63 /* Flag indicating that we want to delete a host from a known_hosts file */
64 int delete_host = 0;
65 
66 /* Flag indicating that we just want to see the key fingerprint */
67 int print_fingerprint = 0;
68 int print_bubblebabble = 0;
69 
70 /* The identity file name, given on the command line or entered by the user. */
71 char identity_file[1024];
72 int have_identity = 0;
73 
74 /* This is set to the passphrase if given on the command line. */
75 char *identity_passphrase = NULL;
76 
77 /* This is set to the new passphrase if given on the command line. */
78 char *identity_new_passphrase = NULL;
79 
80 /* This is set to the new comment if given on the command line. */
81 char *identity_comment = NULL;
82 
83 /* Dump public key file in format used by real and the original SSH 2 */
84 int convert_to_ssh2 = 0;
85 int convert_from_ssh2 = 0;
86 int print_public = 0;
87 
88 char *key_type_name = NULL;
89 
90 /* argv0 */
91 #ifdef HAVE___PROGNAME
92 extern char *__progname;
93 #else
94 char *__progname;
95 #endif
96 
97 char hostname[MAXHOSTNAMELEN];
98 
99 static void
100 ask_filename(struct passwd *pw, const char *prompt)
101 {
102 	char buf[1024];
103 	char *name = NULL;
104 
105 	if (key_type_name == NULL)
106 		name = _PATH_SSH_CLIENT_ID_RSA;
107 	else {
108 		switch (key_type_from_name(key_type_name)) {
109 		case KEY_RSA1:
110 			name = _PATH_SSH_CLIENT_IDENTITY;
111 			break;
112 		case KEY_DSA:
113 			name = _PATH_SSH_CLIENT_ID_DSA;
114 			break;
115 		case KEY_RSA:
116 			name = _PATH_SSH_CLIENT_ID_RSA;
117 			break;
118 		default:
119 			fprintf(stderr, gettext("bad key type"));
120 			exit(1);
121 			break;
122 		}
123 	}
124 	snprintf(identity_file, sizeof(identity_file), "%s/%s", pw->pw_dir, name);
125 	fprintf(stderr, "%s (%s): ", gettext(prompt), identity_file);
126 	if (fgets(buf, sizeof(buf), stdin) == NULL)
127 		exit(1);
128 	if (strchr(buf, '\n'))
129 		*strchr(buf, '\n') = 0;
130 	if (strcmp(buf, "") != 0)
131 		strlcpy(identity_file, buf, sizeof(identity_file));
132 	have_identity = 1;
133 }
134 
135 static Key *
136 load_identity(char *filename)
137 {
138 	char *pass;
139 	Key *prv;
140 
141 	prv = key_load_private(filename, "", NULL);
142 	if (prv == NULL) {
143 		if (identity_passphrase)
144 			pass = xstrdup(identity_passphrase);
145 		else
146 			pass = read_passphrase(gettext("Enter passphrase: "),
147 			    RP_ALLOW_STDIN);
148 		prv = key_load_private(filename, pass, NULL);
149 		memset(pass, 0, strlen(pass));
150 		xfree(pass);
151 	}
152 	return prv;
153 }
154 
155 #define SSH_COM_PUBLIC_BEGIN		"---- BEGIN SSH2 PUBLIC KEY ----"
156 #define SSH_COM_PUBLIC_END		"---- END SSH2 PUBLIC KEY ----"
157 #define SSH_COM_PRIVATE_BEGIN		"---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"
158 #define	SSH_COM_PRIVATE_KEY_MAGIC	0x3f6ff9eb
159 
160 static void
161 do_convert_to_ssh2(struct passwd *pw)
162 {
163 	Key *k;
164 	u_int len;
165 	u_char *blob;
166 	struct stat st;
167 
168 	if (!have_identity)
169 		ask_filename(pw, gettext("Enter file in which the key is"));
170 	if (stat(identity_file, &st) < 0) {
171 		perror(identity_file);
172 		exit(1);
173 	}
174 	if ((k = key_load_public(identity_file, NULL)) == NULL) {
175 		if ((k = load_identity(identity_file)) == NULL) {
176 			fprintf(stderr, gettext("load failed\n"));
177 			exit(1);
178 		}
179 	}
180 	if (key_to_blob(k, &blob, &len) <= 0) {
181 		fprintf(stderr, gettext("key_to_blob failed\n"));
182 		exit(1);
183 	}
184 	fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN);
185 	fprintf(stdout, gettext(
186 	    "Comment: \"%u-bit %s, converted from OpenSSH by %s@%s\"\n"),
187 	    key_size(k), key_type(k),
188 	    pw->pw_name, hostname);
189 	dump_base64(stdout, blob, len);
190 	fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END);
191 	key_free(k);
192 	xfree(blob);
193 	exit(0);
194 }
195 
196 static void
197 buffer_get_bignum_bits(Buffer *b, BIGNUM *value)
198 {
199 	u_int bignum_bits = buffer_get_int(b);
200 	u_int bytes = (bignum_bits + 7) / 8;
201 
202 	if (buffer_len(b) < bytes)
203 		fatal("buffer_get_bignum_bits: input buffer too small: "
204 		    "need %d have %d", bytes, buffer_len(b));
205 	if (BN_bin2bn(buffer_ptr(b), bytes, value) == NULL)
206 		fatal("buffer_get_bignum_bits: BN_bin2bn failed");
207 	buffer_consume(b, bytes);
208 }
209 
210 static Key *
211 do_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 
303 static int
304 get_line(FILE *fp, char *line, size_t len)
305 {
306 	int c;
307 	size_t pos = 0;
308 
309 	line[0] = '\0';
310 	while ((c = fgetc(fp)) != EOF) {
311 		if (pos >= len - 1) {
312 			fprintf(stderr, "input line too long.\n");
313 			exit(1);
314 		}
315 		switch (c) {
316 		case '\r':
317 			c = fgetc(fp);
318 			if (c != EOF && c != '\n' && ungetc(c, fp) == EOF) {
319 				fprintf(stderr, "unget: %s\n", strerror(errno));
320 				exit(1);
321 			}
322 			return pos;
323 		case '\n':
324 			return pos;
325 		}
326 		line[pos++] = c;
327 		line[pos] = '\0';
328 	}
329 	/* We reached EOF */
330 	return -1;
331 }
332 
333 static void
334 do_convert_from_ssh2(struct passwd *pw)
335 {
336 	Key *k;
337 	int blen;
338 	u_int len;
339 	char line[1024];
340 	u_char blob[8096];
341 	char encoded[8096];
342 	struct stat st;
343 	int escaped = 0, private = 0, ok;
344 	FILE *fp;
345 
346 	if (!have_identity)
347 		ask_filename(pw, gettext("Enter file in which the key is"));
348 	if (stat(identity_file, &st) < 0) {
349 		perror(identity_file);
350 		exit(1);
351 	}
352 	fp = fopen(identity_file, "r");
353 	if (fp == NULL) {
354 		perror(identity_file);
355 		exit(1);
356 	}
357 	encoded[0] = '\0';
358 	while ((blen = get_line(fp, line, sizeof(line))) != -1) {
359 		if (line[blen - 1] == '\\')
360 			escaped++;
361 		if (strncmp(line, "----", 4) == 0 ||
362 		    strstr(line, ": ") != NULL) {
363 			if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL)
364 				private = 1;
365 			if (strstr(line, " END ") != NULL) {
366 				break;
367 			}
368 			/* fprintf(stderr, "ignore: %s", line); */
369 			continue;
370 		}
371 		if (escaped) {
372 			escaped--;
373 			/* fprintf(stderr, "escaped: %s", line); */
374 			continue;
375 		}
376 		strlcat(encoded, line, sizeof(encoded));
377 	}
378 	len = strlen(encoded);
379 	if (((len % 4) == 3) &&
380 	    (encoded[len-1] == '=') &&
381 	    (encoded[len-2] == '=') &&
382 	    (encoded[len-3] == '='))
383 		encoded[len-3] = '\0';
384 	blen = uudecode(encoded, blob, sizeof(blob));
385 	if (blen < 0) {
386 		fprintf(stderr, gettext("uudecode failed.\n"));
387 		exit(1);
388 	}
389 	k = private ?
390 	    do_convert_private_ssh2_from_blob(blob, blen) :
391 	    key_from_blob(blob, blen);
392 	if (k == NULL) {
393 		fprintf(stderr, gettext("decode blob failed.\n"));
394 		exit(1);
395 	}
396 	ok = private ?
397 	    (k->type == KEY_DSA ?
398 		 PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, NULL, 0, NULL, NULL) :
399 		 PEM_write_RSAPrivateKey(stdout, k->rsa, NULL, NULL, 0, NULL, NULL)) :
400 	    key_write(k, stdout);
401 	if (!ok) {
402 		fprintf(stderr, gettext("key write failed"));
403 		exit(1);
404 	}
405 	key_free(k);
406 	if (!private)
407 		fprintf(stdout, "\n");
408 	fclose(fp);
409 	exit(0);
410 }
411 
412 static void
413 do_print_public(struct passwd *pw)
414 {
415 	Key *prv;
416 	struct stat st;
417 
418 	if (!have_identity)
419 		ask_filename(pw, gettext("Enter file in which the key is"));
420 	if (stat(identity_file, &st) < 0) {
421 		perror(identity_file);
422 		exit(1);
423 	}
424 	prv = load_identity(identity_file);
425 	if (prv == NULL) {
426 		fprintf(stderr, gettext("load failed\n"));
427 		exit(1);
428 	}
429 	if (!key_write(prv, stdout))
430 		fprintf(stderr, gettext("key_write failed"));
431 	key_free(prv);
432 	fprintf(stdout, "\n");
433 	exit(0);
434 }
435 
436 #ifdef SMARTCARD
437 static void
438 do_upload(struct passwd *pw, const char *sc_reader_id)
439 {
440 	Key *prv = NULL;
441 	struct stat st;
442 	int ret;
443 
444 	if (!have_identity)
445 		ask_filename(pw, gettext("Enter file in which the key is"));
446 	if (stat(identity_file, &st) < 0) {
447 		perror(identity_file);
448 		exit(1);
449 	}
450 	prv = load_identity(identity_file);
451 	if (prv == NULL) {
452 		error("load failed");
453 		exit(1);
454 	}
455 	ret = sc_put_key(prv, sc_reader_id);
456 	key_free(prv);
457 	if (ret < 0)
458 		exit(1);
459 	log("loading key done");
460 	exit(0);
461 }
462 
463 static void
464 do_download(struct passwd *pw, const char *sc_reader_id)
465 {
466 	Key **keys = NULL;
467 	int i;
468 
469 	keys = sc_get_keys(sc_reader_id, NULL);
470 	if (keys == NULL)
471 		fatal("cannot read public key from smartcard");
472 	for (i = 0; keys[i]; i++) {
473 		key_write(keys[i], stdout);
474 		key_free(keys[i]);
475 		fprintf(stdout, "\n");
476 	}
477 	xfree(keys);
478 	exit(0);
479 }
480 #endif /* SMARTCARD */
481 
482 static void
483 do_fingerprint(struct passwd *pw)
484 {
485 	FILE *f;
486 	Key *public;
487 	char *comment = NULL, *cp, *ep, line[16*1024], *fp;
488 	int i, skip = 0, num = 1, invalid = 1;
489 	enum fp_rep rep;
490 	enum fp_type fptype;
491 	struct stat st;
492 
493 	fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
494 	rep =    print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
495 
496 	if (!have_identity)
497 		ask_filename(pw, gettext("Enter file in which the key is"));
498 	if (stat(identity_file, &st) < 0) {
499 		perror(identity_file);
500 		exit(1);
501 	}
502 	public = key_load_public(identity_file, &comment);
503 	if (public != NULL) {
504 		fp = key_fingerprint(public, fptype, rep);
505 		printf("%u %s %s\n", key_size(public), fp, comment);
506 		key_free(public);
507 		xfree(comment);
508 		xfree(fp);
509 		exit(0);
510 	}
511 	if (comment) {
512 		xfree(comment);
513 		comment = NULL;
514 	}
515 
516 	f = fopen(identity_file, "r");
517 	if (f != NULL) {
518 		while (fgets(line, sizeof(line), f)) {
519 			i = strlen(line) - 1;
520 			if (line[i] != '\n') {
521 				error("line %d too long: %.40s...", num, line);
522 				skip = 1;
523 				continue;
524 			}
525 			num++;
526 			if (skip) {
527 				skip = 0;
528 				continue;
529 			}
530 			line[i] = '\0';
531 
532 			/* Skip leading whitespace, empty and comment lines. */
533 			for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
534 				;
535 			if (!*cp || *cp == '\n' || *cp == '#')
536 				continue;
537 			i = strtol(cp, &ep, 10);
538 			if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) {
539 				int quoted = 0;
540 				comment = cp;
541 				for (; *cp && (quoted || (*cp != ' ' &&
542 				    *cp != '\t')); cp++) {
543 					if (*cp == '\\' && cp[1] == '"')
544 						cp++;	/* Skip both */
545 					else if (*cp == '"')
546 						quoted = !quoted;
547 				}
548 				if (!*cp)
549 					continue;
550 				*cp++ = '\0';
551 			}
552 			ep = cp;
553 			public = key_new(KEY_RSA1);
554 			if (key_read(public, &cp) != 1) {
555 				cp = ep;
556 				key_free(public);
557 				public = key_new(KEY_UNSPEC);
558 				if (key_read(public, &cp) != 1) {
559 					key_free(public);
560 					continue;
561 				}
562 			}
563 			comment = *cp ? cp : comment;
564 			fp = key_fingerprint(public, fptype, rep);
565 			printf("%u %s %s\n", key_size(public), fp,
566 			    comment ? comment : gettext("no comment"));
567 			xfree(fp);
568 			key_free(public);
569 			invalid = 0;
570 		}
571 		fclose(f);
572 	}
573 	if (invalid) {
574 		printf(gettext("%s is not a public key file.\n"),
575 		       identity_file);
576 		exit(1);
577 	}
578 	exit(0);
579 }
580 
581 static void
582 print_host(FILE *f, const char *name, Key *public, int hash)
583 {
584 	if (hash && (name = host_hash(name, NULL, 0)) == NULL)
585 		fatal("hash_host failed");
586 	fprintf(f, "%s ", name);
587 	if (!key_write(public, f))
588 		fatal("key_write failed");
589 	fprintf(f, "\n");
590 }
591 
592 static void
593 do_known_hosts(struct passwd *pw, const char *name)
594 {
595 	FILE *in, *out = stdout;
596 	Key *public;
597 	char *cp, *cp2, *kp, *kp2;
598 	char line[16*1024], tmp[MAXPATHLEN], old[MAXPATHLEN];
599 	int c, i, skip = 0, inplace = 0, num = 0, invalid = 0, has_unhashed = 0;
600 
601 	if (!have_identity) {
602 		cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid);
603 		if (strlcpy(identity_file, cp, sizeof(identity_file)) >=
604 		    sizeof(identity_file))
605 			fatal("Specified known hosts path too long");
606 		xfree(cp);
607 		have_identity = 1;
608 	}
609 	if ((in = fopen(identity_file, "r")) == NULL)
610 		fatal("fopen: %s", strerror(errno));
611 
612 	/*
613 	 * Find hosts goes to stdout, hash and deletions happen in-place
614 	 * A corner case is ssh-keygen -HF foo, which should go to stdout
615 	 */
616 	if (!find_host && (hash_hosts || delete_host)) {
617 		if (strlcpy(tmp, identity_file, sizeof(tmp)) >= sizeof(tmp) ||
618 		    strlcat(tmp, ".XXXXXXXXXX", sizeof(tmp)) >= sizeof(tmp) ||
619 		    strlcpy(old, identity_file, sizeof(old)) >= sizeof(old) ||
620 		    strlcat(old, ".old", sizeof(old)) >= sizeof(old))
621 			fatal("known_hosts path too long");
622 		umask(077);
623 		if ((c = mkstemp(tmp)) == -1)
624 			fatal("mkstemp: %s", strerror(errno));
625 		if ((out = fdopen(c, "w")) == NULL) {
626 			c = errno;
627 			unlink(tmp);
628 			fatal("fdopen: %s", strerror(c));
629 		}
630 		inplace = 1;
631 	}
632 
633 	while (fgets(line, sizeof(line), in)) {
634 		num++;
635 		i = strlen(line) - 1;
636 		if (line[i] != '\n') {
637 			error("line %d too long: %.40s...", num, line);
638 			skip = 1;
639 			invalid = 1;
640 			continue;
641 		}
642 		if (skip) {
643 			skip = 0;
644 			continue;
645 		}
646 		line[i] = '\0';
647 
648 		/* Skip leading whitespace, empty and comment lines. */
649 		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
650 			;
651 		if (!*cp || *cp == '\n' || *cp == '#') {
652 			if (inplace)
653 				fprintf(out, "%s\n", cp);
654 			continue;
655 		}
656 		/* Find the end of the host name portion. */
657 		for (kp = cp; *kp && *kp != ' ' && *kp != '\t'; kp++)
658 			;
659 		if (*kp == '\0' || *(kp + 1) == '\0') {
660 			error("line %d missing key: %.40s...",
661 			    num, line);
662 			invalid = 1;
663 			continue;
664 		}
665 		*kp++ = '\0';
666 		kp2 = kp;
667 
668 		public = key_new(KEY_RSA1);
669 		if (key_read(public, &kp) != 1) {
670 			kp = kp2;
671 			key_free(public);
672 			public = key_new(KEY_UNSPEC);
673 			if (key_read(public, &kp) != 1) {
674 				error("line %d invalid key: %.40s...",
675 				    num, line);
676 				key_free(public);
677 				invalid = 1;
678 				continue;
679 			}
680 		}
681 
682 		if (*cp == HASH_DELIM) {
683 			if (find_host || delete_host) {
684 				cp2 = host_hash(name, cp, strlen(cp));
685 				if (cp2 == NULL) {
686 					error("line %d: invalid hashed "
687 					    "name: %.64s...", num, line);
688 					invalid = 1;
689 					continue;
690 				}
691 				c = (strcmp(cp2, cp) == 0);
692 				if (find_host && c) {
693 					printf(gettext("# Host %s found: "
694 					    "line %d type %s\n"), name,
695 					    num, key_type(public));
696 					print_host(out, cp, public, 0);
697 				}
698 				if (delete_host && !c)
699 					print_host(out, cp, public, 0);
700 			} else if (hash_hosts)
701 				print_host(out, cp, public, 0);
702 		} else {
703 			if (find_host || delete_host) {
704 				c = (match_hostname(name, cp,
705 				    strlen(cp)) == 1);
706 				if (find_host && c) {
707 					printf(gettext("# Host %s found: "
708 					    "line %d type %s\n"), name,
709 					    num, key_type(public));
710 					print_host(out, name, public, hash_hosts);
711 				}
712 				if (delete_host && !c)
713 					print_host(out, cp, public, 0);
714 			} else if (hash_hosts) {
715 				for (cp2 = strsep(&cp, ",");
716 				    cp2 != NULL && *cp2 != '\0';
717 				    cp2 = strsep(&cp, ",")) {
718 					if (strcspn(cp2, "*?!") != strlen(cp2))
719 						fprintf(stderr, gettext("Warning: "
720 						   "ignoring host name with "
721 						   "metacharacters: %.64s\n"),
722 						    cp2);
723 					else
724 						print_host(out, cp2, public, 1);
725 				}
726 				has_unhashed = 1;
727 			}
728 		}
729 		key_free(public);
730 	}
731 	fclose(in);
732 
733 	if (invalid) {
734 		fprintf(stderr, gettext("%s is not a valid known_host file.\n"),
735 		    identity_file);
736 		if (inplace) {
737 			fprintf(stderr, gettext("Not replacing existing known_hosts "
738 			   "file because of errors\n"));
739 			fclose(out);
740 			unlink(tmp);
741 		}
742 		exit(1);
743 	}
744 
745 	if (inplace) {
746 		fclose(out);
747 
748 		/* Backup existing file */
749 		if (unlink(old) == -1 && errno != ENOENT)
750 			fatal("unlink %.100s: %s", old, strerror(errno));
751 		if (link(identity_file, old) == -1)
752 			fatal("link %.100s to %.100s: %s", identity_file, old,
753 			    strerror(errno));
754 		/* Move new one into place */
755 		if (rename(tmp, identity_file) == -1) {
756 			error("rename\"%s\" to \"%s\": %s", tmp, identity_file,
757 			    strerror(errno));
758 			unlink(tmp);
759 			unlink(old);
760 			exit(1);
761 		}
762 
763 		fprintf(stderr, gettext("%s updated.\n"), identity_file);
764 		fprintf(stderr, gettext("Original contents retained as %s\n"), old);
765 		if (has_unhashed) {
766 			fprintf(stderr, gettext("WARNING: %s contains unhashed "
767 			    "entries\n"), old);
768 			fprintf(stderr, gettext("Delete this file to ensure privacy "
769 			    "of hostnames\n"));
770 		}
771 	}
772 
773 	exit(0);
774 }
775 
776 /*
777  * Perform changing a passphrase.  The argument is the passwd structure
778  * for the current user.
779  */
780 static void
781 do_change_passphrase(struct passwd *pw)
782 {
783 	char *comment;
784 	char *old_passphrase, *passphrase1, *passphrase2;
785 	struct stat st;
786 	Key *private;
787 
788 	if (!have_identity)
789 		ask_filename(pw, gettext("Enter file in which the key is"));
790 	if (stat(identity_file, &st) < 0) {
791 		perror(identity_file);
792 		exit(1);
793 	}
794 	/* Try to load the file with empty passphrase. */
795 	private = key_load_private(identity_file, "", &comment);
796 	if (private == NULL) {
797 		if (identity_passphrase)
798 			old_passphrase = xstrdup(identity_passphrase);
799 		else
800 			old_passphrase =
801 			    read_passphrase(gettext("Enter old passphrase: "),
802 			    RP_ALLOW_STDIN);
803 		private = key_load_private(identity_file, old_passphrase,
804 		    &comment);
805 		memset(old_passphrase, 0, strlen(old_passphrase));
806 		xfree(old_passphrase);
807 		if (private == NULL) {
808 			printf(gettext("Bad passphrase.\n"));
809 			exit(1);
810 		}
811 	}
812 	printf(gettext("Key has comment '%s'\n"), comment);
813 
814 	/* Ask the new passphrase (twice). */
815 	if (identity_new_passphrase) {
816 		passphrase1 = xstrdup(identity_new_passphrase);
817 		passphrase2 = NULL;
818 	} else {
819 		passphrase1 =
820 			read_passphrase(gettext("Enter new passphrase (empty"
821 			    " for no passphrase): "), RP_ALLOW_STDIN);
822 		passphrase2 = read_passphrase(gettext("Enter same "
823 			    "passphrase again: "), RP_ALLOW_STDIN);
824 
825 		/* Verify that they are the same. */
826 		if (strcmp(passphrase1, passphrase2) != 0) {
827 			memset(passphrase1, 0, strlen(passphrase1));
828 			memset(passphrase2, 0, strlen(passphrase2));
829 			xfree(passphrase1);
830 			xfree(passphrase2);
831 			printf(gettext("Pass phrases do not match.  Try "
832 			    "again.\n"));
833 			exit(1);
834 		}
835 		/* Destroy the other copy. */
836 		memset(passphrase2, 0, strlen(passphrase2));
837 		xfree(passphrase2);
838 	}
839 
840 	/* Save the file using the new passphrase. */
841 	if (!key_save_private(private, identity_file, passphrase1, comment)) {
842 		printf(gettext("Saving the key failed: %s.\n"), identity_file);
843 		memset(passphrase1, 0, strlen(passphrase1));
844 		xfree(passphrase1);
845 		key_free(private);
846 		xfree(comment);
847 		exit(1);
848 	}
849 	/* Destroy the passphrase and the copy of the key in memory. */
850 	memset(passphrase1, 0, strlen(passphrase1));
851 	xfree(passphrase1);
852 	key_free(private);		 /* Destroys contents */
853 	xfree(comment);
854 
855 	printf(gettext("Your identification has been saved with the new "
856 	    "passphrase.\n"));
857 	exit(0);
858 }
859 
860 /*
861  * Change the comment of a private key file.
862  */
863 static void
864 do_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, gettext("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 =
887 			    read_passphrase(gettext("Enter passphrase: "),
888 			    RP_ALLOW_STDIN);
889 		/* Try to load using the passphrase. */
890 		private = key_load_private(identity_file, passphrase, &comment);
891 		if (private == NULL) {
892 			memset(passphrase, 0, strlen(passphrase));
893 			xfree(passphrase);
894 			printf(gettext("Bad passphrase.\n"));
895 			exit(1);
896 		}
897 	} else {
898 		passphrase = xstrdup("");
899 	}
900 	if (private->type != KEY_RSA1) {
901 		fprintf(stderr, gettext("Comments are only supported for "
902 		    "RSA1 keys.\n"));
903 		key_free(private);
904 		exit(1);
905 	}
906 	printf(gettext("Key now has comment '%s'\n"), comment);
907 
908 	if (identity_comment) {
909 		strlcpy(new_comment, identity_comment, sizeof(new_comment));
910 	} else {
911 		printf(gettext("Enter new comment: "));
912 		fflush(stdout);
913 		if (!fgets(new_comment, sizeof(new_comment), stdin)) {
914 			memset(passphrase, 0, strlen(passphrase));
915 			key_free(private);
916 			exit(1);
917 		}
918 		if (strchr(new_comment, '\n'))
919 			*strchr(new_comment, '\n') = 0;
920 	}
921 
922 	/* Save the file using the new passphrase. */
923 	if (!key_save_private(private, identity_file, passphrase, new_comment)) {
924 		printf(gettext("Saving the key failed: %s.\n"), identity_file);
925 		memset(passphrase, 0, strlen(passphrase));
926 		xfree(passphrase);
927 		key_free(private);
928 		xfree(comment);
929 		exit(1);
930 	}
931 	memset(passphrase, 0, strlen(passphrase));
932 	xfree(passphrase);
933 	public = key_from_private(private);
934 	key_free(private);
935 
936 	strlcat(identity_file, ".pub", sizeof(identity_file));
937 	fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
938 	if (fd == -1) {
939 		printf(gettext("Could not save your public key in %s\n"),
940 		    identity_file);
941 		exit(1);
942 	}
943 	f = fdopen(fd, "w");
944 	if (f == NULL) {
945 		printf(gettext("fdopen %s failed"), identity_file);
946 		exit(1);
947 	}
948 	if (!key_write(public, f))
949 		fprintf(stderr, gettext("write key failed"));
950 	key_free(public);
951 	fprintf(f, " %s\n", new_comment);
952 	fclose(f);
953 
954 	xfree(comment);
955 
956 	printf(gettext("The comment in your key file has been changed.\n"));
957 	exit(0);
958 }
959 
960 static void
961 usage(void)
962 {
963 	fprintf(stderr, gettext(
964 	"Usage: %s [options]\n"
965 	"Options:\n"
966 	"  -b bits     Number of bits in the key to create.\n"
967 	"  -B          Show bubblebabble digest of key file.\n"
968 	"  -c          Change comment in private and public key files.\n"
969 	"  -C comment  Provide new comment.\n"
970 #ifdef SMARTCARD
971 	"  -D reader   Download public key from smartcard.\n"
972 #endif /* SMARTCARD */
973 	"  -e          Convert OpenSSH to IETF SECSH key file.\n"
974 	"  -f filename Filename of the key file.\n"
975 	"  -F hostname Find hostname in known hosts file.\n"
976 	"  -H          Hash names in known_hosts file.\n"
977 	"  -i          Convert IETF SECSH to OpenSSH key file.\n"
978 	"  -l          Show fingerprint of key file.\n"
979 	"  -N phrase   Provide new passphrase.\n"
980 	"  -p          Change passphrase of private key file.\n"
981 	"  -P phrase   Provide old passphrase.\n"
982 	"  -q          Quiet.\n"
983 	"  -R hostname Remove host from known_hosts file.\n"
984 	"  -t type     Specify type of key to create.\n"
985 #ifdef SMARTCARD
986 	"  -U reader   Upload private key to smartcard.\n"
987 #endif /* SMARTCARD */
988 	"  -y          Read private key file and print public key.\n"
989 	), __progname);
990 
991 	exit(1);
992 }
993 
994 /*
995  * Main program for key management.
996  */
997 int
998 main(int argc, char **argv)
999 {
1000 	char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2;
1001 	char *reader_id = NULL;
1002 	char *rr_hostname = NULL;
1003 	Key *private, *public;
1004 	struct passwd *pw;
1005 	struct stat st;
1006 	int opt, type, fd;
1007 #ifdef SMARTCARD
1008 	int download = 0;
1009 #endif /* SMARTCARD */
1010 	FILE *f;
1011 
1012 	extern int optind;
1013 	extern char *optarg;
1014 
1015 	/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
1016 	sanitise_stdfd();
1017 
1018 	__progname = get_progname(argv[0]);
1019 
1020 	g11n_setlocale(LC_ALL, "");
1021 
1022 	SSLeay_add_all_algorithms();
1023 	init_rng();
1024 	seed_rng();
1025 
1026 	/* we need this for the home * directory.  */
1027 	pw = getpwuid(getuid());
1028 	if (!pw) {
1029 		printf(gettext("You don't exist, go away!\n"));
1030 		exit(1);
1031 	}
1032 	if (gethostname(hostname, sizeof(hostname)) < 0) {
1033 		perror("gethostname");
1034 		exit(1);
1035 	}
1036 
1037 #ifdef SMARTCARD
1038 #define GETOPT_ARGS "deiqpclBHRxXyb:f:F:t:U:D:P:N:C:"
1039 #else
1040 #define GETOPT_ARGS "BcdeHilpqxXyb:C:f:F:N:P:R:t:"
1041 #endif /* SMARTCARD */
1042 	while ((opt = getopt(argc, argv, GETOPT_ARGS)) != -1) {
1043 		switch (opt) {
1044 		case 'b':
1045 			bits = atoi(optarg);
1046 			if (bits < 512 || bits > 32768) {
1047 				printf(gettext("Bits has bad value.\n"));
1048 				exit(1);
1049 			}
1050 			break;
1051 		case 'F':
1052 			find_host = 1;
1053 			rr_hostname = optarg;
1054 			break;
1055 		case 'H':
1056 			hash_hosts = 1;
1057 			break;
1058 		case 'R':
1059 			delete_host = 1;
1060 			rr_hostname = optarg;
1061 			break;
1062 		case 'l':
1063 			print_fingerprint = 1;
1064 			break;
1065 		case 'B':
1066 			print_bubblebabble = 1;
1067 			break;
1068 		case 'p':
1069 			change_passphrase = 1;
1070 			break;
1071 		case 'c':
1072 			change_comment = 1;
1073 			break;
1074 		case 'f':
1075 			strlcpy(identity_file, optarg, sizeof(identity_file));
1076 			have_identity = 1;
1077 			break;
1078 		case 'P':
1079 			identity_passphrase = optarg;
1080 			break;
1081 		case 'N':
1082 			identity_new_passphrase = optarg;
1083 			break;
1084 		case 'C':
1085 			identity_comment = optarg;
1086 			break;
1087 		case 'q':
1088 			quiet = 1;
1089 			break;
1090 		case 'e':
1091 		case 'x':
1092 			/* export key */
1093 			convert_to_ssh2 = 1;
1094 			break;
1095 		case 'i':
1096 		case 'X':
1097 			/* import key */
1098 			convert_from_ssh2 = 1;
1099 			break;
1100 		case 'y':
1101 			print_public = 1;
1102 			break;
1103 		case 'd':
1104 			key_type_name = "dsa";
1105 			break;
1106 		case 't':
1107 			key_type_name = optarg;
1108 			break;
1109 #ifdef SMARTCARD
1110 		case 'D':
1111 			download = 1;
1112 		case 'U':
1113 			reader_id = optarg;
1114 			break;
1115 #endif
1116 		case '?':
1117 		default:
1118 			usage();
1119 		}
1120 	}
1121 	if (optind < argc) {
1122 		printf(gettext("Too many arguments.\n"));
1123 		usage();
1124 	}
1125 	if (change_passphrase && change_comment) {
1126 		printf(gettext("Can only have one of -p and -c.\n"));
1127 		usage();
1128 	}
1129 	if (delete_host || hash_hosts || find_host)
1130 		do_known_hosts(pw, rr_hostname);
1131 	if (print_fingerprint || print_bubblebabble)
1132 		do_fingerprint(pw);
1133 	if (change_passphrase)
1134 		do_change_passphrase(pw);
1135 	if (change_comment)
1136 		do_change_comment(pw);
1137 	if (convert_to_ssh2)
1138 		do_convert_to_ssh2(pw);
1139 	if (convert_from_ssh2)
1140 		do_convert_from_ssh2(pw);
1141 	if (print_public)
1142 		do_print_public(pw);
1143 	if (reader_id != NULL) {
1144 #ifdef SMARTCARD
1145 		if (download)
1146 			do_download(pw, reader_id);
1147 		else
1148 			do_upload(pw, reader_id);
1149 #else /* SMARTCARD */
1150 		fatal("no support for smartcards.");
1151 #endif /* SMARTCARD */
1152 	}
1153 
1154 	arc4random_stir();
1155 
1156 	if (key_type_name == NULL) {
1157 		printf(gettext("You must specify a key type (-t).\n"));
1158 		usage();
1159 	}
1160 	type = key_type_from_name(key_type_name);
1161 	if (type == KEY_UNSPEC) {
1162 		fprintf(stderr, gettext("unknown key type %s\n"),
1163 		    key_type_name);
1164 		exit(1);
1165 	}
1166 	if (!quiet)
1167 		printf(gettext("Generating public/private %s key pair.\n"),
1168 		    key_type_name);
1169 	private = key_generate(type, bits);
1170 	if (private == NULL) {
1171 		fprintf(stderr, gettext("key_generate failed"));
1172 		exit(1);
1173 	}
1174 	public  = key_from_private(private);
1175 
1176 	if (!have_identity)
1177 		ask_filename(pw, gettext("Enter file in which to save the key"));
1178 
1179 	/* Create ~/.ssh directory if it doesn't already exist. */
1180 	snprintf(dotsshdir, sizeof dotsshdir, "%s/%s", pw->pw_dir, _PATH_SSH_USER_DIR);
1181 	if (strstr(identity_file, dotsshdir) != NULL &&
1182 	    stat(dotsshdir, &st) < 0) {
1183 		if (mkdir(dotsshdir, 0700) < 0)
1184 			error("Could not create directory '%s'.", dotsshdir);
1185 		else if (!quiet)
1186 			printf(gettext("Created directory '%s'.\n"), dotsshdir);
1187 	}
1188 	/* If the file already exists, ask the user to confirm. */
1189 	if (stat(identity_file, &st) >= 0) {
1190 		char yesno[128];
1191 		printf(gettext("%s already exists.\n"), identity_file);
1192 		printf(gettext("Overwrite (%s/%s)? "),
1193 		    nl_langinfo(YESSTR), nl_langinfo(NOSTR));
1194 		fflush(stdout);
1195 		if (fgets(yesno, sizeof(yesno), stdin) == NULL)
1196 			exit(1);
1197 		if (strcasecmp(chop(yesno), nl_langinfo(YESSTR)) != 0)
1198 			exit(1);
1199 	}
1200 	/* Ask for a passphrase (twice). */
1201 	if (identity_passphrase)
1202 		passphrase1 = xstrdup(identity_passphrase);
1203 	else if (identity_new_passphrase)
1204 		passphrase1 = xstrdup(identity_new_passphrase);
1205 	else {
1206 passphrase_again:
1207 		passphrase1 =
1208 			read_passphrase(gettext("Enter passphrase (empty "
1209 			"for no passphrase): "), RP_ALLOW_STDIN);
1210 		passphrase2 = read_passphrase(gettext("Enter same "
1211 			    "passphrase again: "), RP_ALLOW_STDIN);
1212 		if (strcmp(passphrase1, passphrase2) != 0) {
1213 			/*
1214 			 * The passphrases do not match.  Clear them and
1215 			 * retry.
1216 			 */
1217 			memset(passphrase1, 0, strlen(passphrase1));
1218 			memset(passphrase2, 0, strlen(passphrase2));
1219 			xfree(passphrase1);
1220 			xfree(passphrase2);
1221 			printf(gettext("Passphrases do not match.  Try "
1222 			    "again.\n"));
1223 			goto passphrase_again;
1224 		}
1225 		/* Clear the other copy of the passphrase. */
1226 		memset(passphrase2, 0, strlen(passphrase2));
1227 		xfree(passphrase2);
1228 	}
1229 
1230 	if (identity_comment) {
1231 		strlcpy(comment, identity_comment, sizeof(comment));
1232 	} else {
1233 		/* Create default commend field for the passphrase. */
1234 		snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname);
1235 	}
1236 
1237 	/* Save the key with the given passphrase and comment. */
1238 	if (!key_save_private(private, identity_file, passphrase1, comment)) {
1239 		printf(gettext("Saving the key failed: %s.\n"), identity_file);
1240 		memset(passphrase1, 0, strlen(passphrase1));
1241 		xfree(passphrase1);
1242 		exit(1);
1243 	}
1244 	/* Clear the passphrase. */
1245 	memset(passphrase1, 0, strlen(passphrase1));
1246 	xfree(passphrase1);
1247 
1248 	/* Clear the private key and the random number generator. */
1249 	key_free(private);
1250 	arc4random_stir();
1251 
1252 	if (!quiet)
1253 		printf(gettext("Your identification has been saved in %s.\n"),
1254 		    identity_file);
1255 
1256 	strlcat(identity_file, ".pub", sizeof(identity_file));
1257 	fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
1258 	if (fd == -1) {
1259 		printf(gettext("Could not save your public key in %s\n"),
1260 		    identity_file);
1261 		exit(1);
1262 	}
1263 	f = fdopen(fd, "w");
1264 	if (f == NULL) {
1265 		printf(gettext("fdopen %s failed"), identity_file);
1266 		exit(1);
1267 	}
1268 	if (!key_write(public, f))
1269 		fprintf(stderr, gettext("write key failed"));
1270 	fprintf(f, " %s\n", comment);
1271 	fclose(f);
1272 
1273 	if (!quiet) {
1274 		char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX);
1275 		printf(gettext("Your public key has been saved in %s.\n"),
1276 		    identity_file);
1277 		printf(gettext("The key fingerprint is:\n"));
1278 		printf("%s %s\n", fp, comment);
1279 		xfree(fp);
1280 	}
1281 
1282 	key_free(public);
1283 	return(0);
1284 	/* NOTREACHED */
1285 }
1286