summaryrefslogtreecommitdiff
path: root/ssh-keygen.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2010-08-23 22:56:08 +0100
committerColin Watson <cjwatson@debian.org>2010-08-23 22:56:08 +0100
commit31e30b835fd9695d3b6647cab4867001b092e28f (patch)
tree138e715c25661825457c7280cd66e3f4853d474c /ssh-keygen.c
parent78eedc2c60ff4718200f9271d8ee4f437da3a0c5 (diff)
parent43094ebf14c9b16f1ea398bc5b65a7335e947288 (diff)
merge 5.6p1
Diffstat (limited to 'ssh-keygen.c')
-rw-r--r--ssh-keygen.c759
1 files changed, 524 insertions, 235 deletions
diff --git a/ssh-keygen.c b/ssh-keygen.c
index 37e516ff2..d90b1dfdd 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-keygen.c,v 1.185 2010/03/15 19:40:02 stevesk Exp $ */ 1/* $OpenBSD: ssh-keygen.c,v 1.197 2010/08/04 06:07:11 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -105,6 +105,9 @@ char *identity_comment = NULL;
105/* Path to CA key when certifying keys. */ 105/* Path to CA key when certifying keys. */
106char *ca_key_path = NULL; 106char *ca_key_path = NULL;
107 107
108/* Certificate serial number */
109long long cert_serial = 0;
110
108/* Key type when certifying */ 111/* Key type when certifying */
109u_int cert_key_type = SSH2_CERT_TYPE_USER; 112u_int cert_key_type = SSH2_CERT_TYPE_USER;
110 113
@@ -118,27 +121,34 @@ char *cert_principals = NULL;
118u_int64_t cert_valid_from = 0; 121u_int64_t cert_valid_from = 0;
119u_int64_t cert_valid_to = ~0ULL; 122u_int64_t cert_valid_to = ~0ULL;
120 123
121/* Certificate constraints */ 124/* Certificate options */
122#define CONSTRAINT_X_FWD (1) 125#define CERTOPT_X_FWD (1)
123#define CONSTRAINT_AGENT_FWD (1<<1) 126#define CERTOPT_AGENT_FWD (1<<1)
124#define CONSTRAINT_PORT_FWD (1<<2) 127#define CERTOPT_PORT_FWD (1<<2)
125#define CONSTRAINT_PTY (1<<3) 128#define CERTOPT_PTY (1<<3)
126#define CONSTRAINT_USER_RC (1<<4) 129#define CERTOPT_USER_RC (1<<4)
127#define CONSTRAINT_DEFAULT (CONSTRAINT_X_FWD|CONSTRAINT_AGENT_FWD| \ 130#define CERTOPT_DEFAULT (CERTOPT_X_FWD|CERTOPT_AGENT_FWD| \
128 CONSTRAINT_PORT_FWD|CONSTRAINT_PTY| \ 131 CERTOPT_PORT_FWD|CERTOPT_PTY|CERTOPT_USER_RC)
129 CONSTRAINT_USER_RC) 132u_int32_t certflags_flags = CERTOPT_DEFAULT;
130u_int32_t constraint_flags = CONSTRAINT_DEFAULT; 133char *certflags_command = NULL;
131char *constraint_command = NULL; 134char *certflags_src_addr = NULL;
132char *constraint_src_addr = NULL; 135
133 136/* Conversion to/from various formats */
134/* Dump public key file in format used by real and the original SSH 2 */ 137int convert_to = 0;
135int convert_to_ssh2 = 0; 138int convert_from = 0;
136int convert_from_ssh2 = 0; 139enum {
140 FMT_RFC4716,
141 FMT_PKCS8,
142 FMT_PEM
143} convert_format = FMT_RFC4716;
137int print_public = 0; 144int print_public = 0;
138int print_generic = 0; 145int print_generic = 0;
139 146
140char *key_type_name = NULL; 147char *key_type_name = NULL;
141 148
149/* Load key from this PKCS#11 provider */
150char *pkcs11provider = NULL;
151
142/* argv0 */ 152/* argv0 */
143extern char *__progname; 153extern char *__progname;
144 154
@@ -161,9 +171,13 @@ ask_filename(struct passwd *pw, const char *prompt)
161 case KEY_RSA1: 171 case KEY_RSA1:
162 name = _PATH_SSH_CLIENT_IDENTITY; 172 name = _PATH_SSH_CLIENT_IDENTITY;
163 break; 173 break;
174 case KEY_DSA_CERT:
175 case KEY_DSA_CERT_V00:
164 case KEY_DSA: 176 case KEY_DSA:
165 name = _PATH_SSH_CLIENT_ID_DSA; 177 name = _PATH_SSH_CLIENT_ID_DSA;
166 break; 178 break;
179 case KEY_RSA_CERT:
180 case KEY_RSA_CERT_V00:
167 case KEY_RSA: 181 case KEY_RSA:
168 name = _PATH_SSH_CLIENT_ID_RSA; 182 name = _PATH_SSH_CLIENT_ID_RSA;
169 break; 183 break;
@@ -209,30 +223,12 @@ load_identity(char *filename)
209#define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb 223#define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb
210 224
211static void 225static void
212do_convert_to_ssh2(struct passwd *pw) 226do_convert_to_ssh2(struct passwd *pw, Key *k)
213{ 227{
214 Key *k;
215 u_int len; 228 u_int len;
216 u_char *blob; 229 u_char *blob;
217 char comment[61]; 230 char comment[61];
218 struct stat st;
219 231
220 if (!have_identity)
221 ask_filename(pw, "Enter file in which the key is");
222 if (stat(identity_file, &st) < 0) {
223 perror(identity_file);
224 exit(1);
225 }
226 if ((k = key_load_public(identity_file, NULL)) == NULL) {
227 if ((k = load_identity(identity_file)) == NULL) {
228 fprintf(stderr, "load failed\n");
229 exit(1);
230 }
231 }
232 if (k->type == KEY_RSA1) {
233 fprintf(stderr, "version 1 keys are not supported\n");
234 exit(1);
235 }
236 if (key_to_blob(k, &blob, &len) <= 0) { 232 if (key_to_blob(k, &blob, &len) <= 0) {
237 fprintf(stderr, "key_to_blob failed\n"); 233 fprintf(stderr, "key_to_blob failed\n");
238 exit(1); 234 exit(1);
@@ -253,6 +249,81 @@ do_convert_to_ssh2(struct passwd *pw)
253} 249}
254 250
255static void 251static void
252do_convert_to_pkcs8(Key *k)
253{
254 switch (key_type_plain(k->type)) {
255 case KEY_RSA:
256 if (!PEM_write_RSA_PUBKEY(stdout, k->rsa))
257 fatal("PEM_write_RSA_PUBKEY failed");
258 break;
259 case KEY_DSA:
260 if (!PEM_write_DSA_PUBKEY(stdout, k->dsa))
261 fatal("PEM_write_DSA_PUBKEY failed");
262 break;
263 default:
264 fatal("%s: unsupported key type %s", __func__, key_type(k));
265 }
266 exit(0);
267}
268
269static void
270do_convert_to_pem(Key *k)
271{
272 switch (key_type_plain(k->type)) {
273 case KEY_RSA:
274 if (!PEM_write_RSAPublicKey(stdout, k->rsa))
275 fatal("PEM_write_RSAPublicKey failed");
276 break;
277#if notyet /* OpenSSH 0.9.8 lacks this function */
278 case KEY_DSA:
279 if (!PEM_write_DSAPublicKey(stdout, k->dsa))
280 fatal("PEM_write_DSAPublicKey failed");
281 break;
282#endif
283 default:
284 fatal("%s: unsupported key type %s", __func__, key_type(k));
285 }
286 exit(0);
287}
288
289static void
290do_convert_to(struct passwd *pw)
291{
292 Key *k;
293 struct stat st;
294
295 if (!have_identity)
296 ask_filename(pw, "Enter file in which the key is");
297 if (stat(identity_file, &st) < 0)
298 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
299 if ((k = key_load_public(identity_file, NULL)) == NULL) {
300 if ((k = load_identity(identity_file)) == NULL) {
301 fprintf(stderr, "load failed\n");
302 exit(1);
303 }
304 }
305 if (k->type == KEY_RSA1) {
306 fprintf(stderr, "version 1 keys are not supported\n");
307 exit(1);
308 }
309
310 switch (convert_format) {
311 case FMT_RFC4716:
312 do_convert_to_ssh2(pw, k);
313 break;
314 case FMT_PKCS8:
315 do_convert_to_pkcs8(k);
316 break;
317 case FMT_PEM:
318 do_convert_to_pem(k);
319 break;
320 default:
321 fatal("%s: unknown key format %d", __func__, convert_format);
322 }
323 exit(0);
324}
325
326static void
256buffer_get_bignum_bits(Buffer *b, BIGNUM *value) 327buffer_get_bignum_bits(Buffer *b, BIGNUM *value)
257{ 328{
258 u_int bignum_bits = buffer_get_int(b); 329 u_int bignum_bits = buffer_get_int(b);
@@ -390,29 +461,18 @@ get_line(FILE *fp, char *line, size_t len)
390} 461}
391 462
392static void 463static void
393do_convert_from_ssh2(struct passwd *pw) 464do_convert_from_ssh2(struct passwd *pw, Key **k, int *private)
394{ 465{
395 Key *k;
396 int blen; 466 int blen;
397 u_int len; 467 u_int len;
398 char line[1024]; 468 char line[1024];
399 u_char blob[8096]; 469 u_char blob[8096];
400 char encoded[8096]; 470 char encoded[8096];
401 struct stat st; 471 int escaped = 0;
402 int escaped = 0, private = 0, ok;
403 FILE *fp; 472 FILE *fp;
404 473
405 if (!have_identity) 474 if ((fp = fopen(identity_file, "r")) == NULL)
406 ask_filename(pw, "Enter file in which the key is"); 475 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
407 if (stat(identity_file, &st) < 0) {
408 perror(identity_file);
409 exit(1);
410 }
411 fp = fopen(identity_file, "r");
412 if (fp == NULL) {
413 perror(identity_file);
414 exit(1);
415 }
416 encoded[0] = '\0'; 476 encoded[0] = '\0';
417 while ((blen = get_line(fp, line, sizeof(line))) != -1) { 477 while ((blen = get_line(fp, line, sizeof(line))) != -1) {
418 if (line[blen - 1] == '\\') 478 if (line[blen - 1] == '\\')
@@ -420,7 +480,7 @@ do_convert_from_ssh2(struct passwd *pw)
420 if (strncmp(line, "----", 4) == 0 || 480 if (strncmp(line, "----", 4) == 0 ||
421 strstr(line, ": ") != NULL) { 481 strstr(line, ": ") != NULL) {
422 if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL) 482 if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL)
423 private = 1; 483 *private = 1;
424 if (strstr(line, " END ") != NULL) { 484 if (strstr(line, " END ") != NULL) {
425 break; 485 break;
426 } 486 }
@@ -445,26 +505,130 @@ do_convert_from_ssh2(struct passwd *pw)
445 fprintf(stderr, "uudecode failed.\n"); 505 fprintf(stderr, "uudecode failed.\n");
446 exit(1); 506 exit(1);
447 } 507 }
448 k = private ? 508 *k = *private ?
449 do_convert_private_ssh2_from_blob(blob, blen) : 509 do_convert_private_ssh2_from_blob(blob, blen) :
450 key_from_blob(blob, blen); 510 key_from_blob(blob, blen);
451 if (k == NULL) { 511 if (*k == NULL) {
452 fprintf(stderr, "decode blob failed.\n"); 512 fprintf(stderr, "decode blob failed.\n");
453 exit(1); 513 exit(1);
454 } 514 }
455 ok = private ? 515 fclose(fp);
456 (k->type == KEY_DSA ? 516}
457 PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, NULL, 0, NULL, NULL) : 517
458 PEM_write_RSAPrivateKey(stdout, k->rsa, NULL, NULL, 0, NULL, NULL)) : 518static void
459 key_write(k, stdout); 519do_convert_from_pkcs8(Key **k, int *private)
520{
521 EVP_PKEY *pubkey;
522 FILE *fp;
523
524 if ((fp = fopen(identity_file, "r")) == NULL)
525 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
526 if ((pubkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) {
527 fatal("%s: %s is not a recognised public key format", __func__,
528 identity_file);
529 }
530 fclose(fp);
531 switch (EVP_PKEY_type(pubkey->type)) {
532 case EVP_PKEY_RSA:
533 *k = key_new(KEY_UNSPEC);
534 (*k)->type = KEY_RSA;
535 (*k)->rsa = EVP_PKEY_get1_RSA(pubkey);
536 break;
537 case EVP_PKEY_DSA:
538 *k = key_new(KEY_UNSPEC);
539 (*k)->type = KEY_DSA;
540 (*k)->dsa = EVP_PKEY_get1_DSA(pubkey);
541 break;
542 default:
543 fatal("%s: unsupported pubkey type %d", __func__,
544 EVP_PKEY_type(pubkey->type));
545 }
546 EVP_PKEY_free(pubkey);
547 return;
548}
549
550static void
551do_convert_from_pem(Key **k, int *private)
552{
553 FILE *fp;
554 RSA *rsa;
555#ifdef notyet
556 DSA *dsa;
557#endif
558
559 if ((fp = fopen(identity_file, "r")) == NULL)
560 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
561 if ((rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL)) != NULL) {
562 *k = key_new(KEY_UNSPEC);
563 (*k)->type = KEY_RSA;
564 (*k)->rsa = rsa;
565 fclose(fp);
566 return;
567 }
568#if notyet /* OpenSSH 0.9.8 lacks this function */
569 rewind(fp);
570 if ((dsa = PEM_read_DSAPublicKey(fp, NULL, NULL, NULL)) != NULL) {
571 *k = key_new(KEY_UNSPEC);
572 (*k)->type = KEY_DSA;
573 (*k)->dsa = dsa;
574 fclose(fp);
575 return;
576 }
577#endif
578 fatal("%s: unrecognised raw private key format", __func__);
579}
580
581static void
582do_convert_from(struct passwd *pw)
583{
584 Key *k = NULL;
585 int private = 0, ok = 0;
586 struct stat st;
587
588 if (!have_identity)
589 ask_filename(pw, "Enter file in which the key is");
590 if (stat(identity_file, &st) < 0)
591 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
592
593 switch (convert_format) {
594 case FMT_RFC4716:
595 do_convert_from_ssh2(pw, &k, &private);
596 break;
597 case FMT_PKCS8:
598 do_convert_from_pkcs8(&k, &private);
599 break;
600 case FMT_PEM:
601 do_convert_from_pem(&k, &private);
602 break;
603 default:
604 fatal("%s: unknown key format %d", __func__, convert_format);
605 }
606
607 if (!private)
608 ok = key_write(k, stdout);
609 if (ok)
610 fprintf(stdout, "\n");
611 else {
612 switch (k->type) {
613 case KEY_DSA:
614 ok = PEM_write_DSAPrivateKey(stdout, k->dsa, NULL,
615 NULL, 0, NULL, NULL);
616 break;
617 case KEY_RSA:
618 ok = PEM_write_RSAPrivateKey(stdout, k->rsa, NULL,
619 NULL, 0, NULL, NULL);
620 break;
621 default:
622 fatal("%s: unsupported key type %s", __func__,
623 key_type(k));
624 }
625 }
626
460 if (!ok) { 627 if (!ok) {
461 fprintf(stderr, "key write failed\n"); 628 fprintf(stderr, "key write failed\n");
462 exit(1); 629 exit(1);
463 } 630 }
464 key_free(k); 631 key_free(k);
465 if (!private)
466 fprintf(stdout, "\n");
467 fclose(fp);
468 exit(0); 632 exit(0);
469} 633}
470 634
@@ -493,7 +657,7 @@ do_print_public(struct passwd *pw)
493} 657}
494 658
495static void 659static void
496do_download(struct passwd *pw, char *pkcs11provider) 660do_download(struct passwd *pw)
497{ 661{
498#ifdef ENABLE_PKCS11 662#ifdef ENABLE_PKCS11
499 Key **keys = NULL; 663 Key **keys = NULL;
@@ -555,67 +719,68 @@ do_fingerprint(struct passwd *pw)
555 comment = NULL; 719 comment = NULL;
556 } 720 }
557 721
558 f = fopen(identity_file, "r"); 722 if ((f = fopen(identity_file, "r")) == NULL)
559 if (f != NULL) { 723 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
560 while (fgets(line, sizeof(line), f)) {
561 if ((cp = strchr(line, '\n')) == NULL) {
562 error("line %d too long: %.40s...",
563 num + 1, line);
564 skip = 1;
565 continue;
566 }
567 num++;
568 if (skip) {
569 skip = 0;
570 continue;
571 }
572 *cp = '\0';
573 724
574 /* Skip leading whitespace, empty and comment lines. */ 725 while (fgets(line, sizeof(line), f)) {
575 for (cp = line; *cp == ' ' || *cp == '\t'; cp++) 726 if ((cp = strchr(line, '\n')) == NULL) {
576 ; 727 error("line %d too long: %.40s...",
577 if (!*cp || *cp == '\n' || *cp == '#') 728 num + 1, line);
578 continue; 729 skip = 1;
579 i = strtol(cp, &ep, 10); 730 continue;
580 if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) { 731 }
581 int quoted = 0; 732 num++;
582 comment = cp; 733 if (skip) {
583 for (; *cp && (quoted || (*cp != ' ' && 734 skip = 0;
584 *cp != '\t')); cp++) { 735 continue;
585 if (*cp == '\\' && cp[1] == '"') 736 }
586 cp++; /* Skip both */ 737 *cp = '\0';
587 else if (*cp == '"') 738
588 quoted = !quoted; 739 /* Skip leading whitespace, empty and comment lines. */
589 } 740 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
590 if (!*cp) 741 ;
591 continue; 742 if (!*cp || *cp == '\n' || *cp == '#')
592 *cp++ = '\0'; 743 continue;
744 i = strtol(cp, &ep, 10);
745 if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) {
746 int quoted = 0;
747 comment = cp;
748 for (; *cp && (quoted || (*cp != ' ' &&
749 *cp != '\t')); cp++) {
750 if (*cp == '\\' && cp[1] == '"')
751 cp++; /* Skip both */
752 else if (*cp == '"')
753 quoted = !quoted;
593 } 754 }
594 ep = cp; 755 if (!*cp)
595 public = key_new(KEY_RSA1); 756 continue;
757 *cp++ = '\0';
758 }
759 ep = cp;
760 public = key_new(KEY_RSA1);
761 if (key_read(public, &cp) != 1) {
762 cp = ep;
763 key_free(public);
764 public = key_new(KEY_UNSPEC);
596 if (key_read(public, &cp) != 1) { 765 if (key_read(public, &cp) != 1) {
597 cp = ep;
598 key_free(public); 766 key_free(public);
599 public = key_new(KEY_UNSPEC); 767 continue;
600 if (key_read(public, &cp) != 1) {
601 key_free(public);
602 continue;
603 }
604 } 768 }
605 comment = *cp ? cp : comment;
606 fp = key_fingerprint(public, fptype, rep);
607 ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
608 printf("%u %s %s (%s)\n", key_size(public), fp,
609 comment ? comment : "no comment", key_type(public));
610 if (log_level >= SYSLOG_LEVEL_VERBOSE)
611 printf("%s\n", ra);
612 xfree(ra);
613 xfree(fp);
614 key_free(public);
615 invalid = 0;
616 } 769 }
617 fclose(f); 770 comment = *cp ? cp : comment;
771 fp = key_fingerprint(public, fptype, rep);
772 ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
773 printf("%u %s %s (%s)\n", key_size(public), fp,
774 comment ? comment : "no comment", key_type(public));
775 if (log_level >= SYSLOG_LEVEL_VERBOSE)
776 printf("%s\n", ra);
777 xfree(ra);
778 xfree(fp);
779 key_free(public);
780 invalid = 0;
618 } 781 }
782 fclose(f);
783
619 if (invalid) { 784 if (invalid) {
620 printf("%s is not a public key file.\n", identity_file); 785 printf("%s is not a public key file.\n", identity_file);
621 exit(1); 786 exit(1);
@@ -670,7 +835,7 @@ do_known_hosts(struct passwd *pw, const char *name)
670 have_identity = 1; 835 have_identity = 1;
671 } 836 }
672 if ((in = fopen(identity_file, "r")) == NULL) 837 if ((in = fopen(identity_file, "r")) == NULL)
673 fatal("fopen: %s", strerror(errno)); 838 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
674 839
675 /* 840 /*
676 * Find hosts goes to stdout, hash and deletions happen in-place 841 * Find hosts goes to stdout, hash and deletions happen in-place
@@ -1104,7 +1269,7 @@ fmt_validity(u_int64_t valid_from, u_int64_t valid_to)
1104} 1269}
1105 1270
1106static void 1271static void
1107add_flag_constraint(Buffer *c, const char *name) 1272add_flag_option(Buffer *c, const char *name)
1108{ 1273{
1109 debug3("%s: %s", __func__, name); 1274 debug3("%s: %s", __func__, name);
1110 buffer_put_cstring(c, name); 1275 buffer_put_cstring(c, name);
@@ -1112,7 +1277,7 @@ add_flag_constraint(Buffer *c, const char *name)
1112} 1277}
1113 1278
1114static void 1279static void
1115add_string_constraint(Buffer *c, const char *name, const char *value) 1280add_string_option(Buffer *c, const char *name, const char *value)
1116{ 1281{
1117 Buffer b; 1282 Buffer b;
1118 1283
@@ -1126,25 +1291,62 @@ add_string_constraint(Buffer *c, const char *name, const char *value)
1126 buffer_free(&b); 1291 buffer_free(&b);
1127} 1292}
1128 1293
1294#define OPTIONS_CRITICAL 1
1295#define OPTIONS_EXTENSIONS 2
1129static void 1296static void
1130prepare_constraint_buf(Buffer *c) 1297prepare_options_buf(Buffer *c, int which)
1131{ 1298{
1132
1133 buffer_clear(c); 1299 buffer_clear(c);
1134 if ((constraint_flags & CONSTRAINT_X_FWD) != 0) 1300 if ((which & OPTIONS_CRITICAL) != 0 &&
1135 add_flag_constraint(c, "permit-X11-forwarding"); 1301 certflags_command != NULL)
1136 if ((constraint_flags & CONSTRAINT_AGENT_FWD) != 0) 1302 add_string_option(c, "force-command", certflags_command);
1137 add_flag_constraint(c, "permit-agent-forwarding"); 1303 if ((which & OPTIONS_EXTENSIONS) != 0 &&
1138 if ((constraint_flags & CONSTRAINT_PORT_FWD) != 0) 1304 (certflags_flags & CERTOPT_AGENT_FWD) != 0)
1139 add_flag_constraint(c, "permit-port-forwarding"); 1305 add_flag_option(c, "permit-agent-forwarding");
1140 if ((constraint_flags & CONSTRAINT_PTY) != 0) 1306 if ((which & OPTIONS_EXTENSIONS) != 0 &&
1141 add_flag_constraint(c, "permit-pty"); 1307 (certflags_flags & CERTOPT_PORT_FWD) != 0)
1142 if ((constraint_flags & CONSTRAINT_USER_RC) != 0) 1308 add_flag_option(c, "permit-port-forwarding");
1143 add_flag_constraint(c, "permit-user-rc"); 1309 if ((which & OPTIONS_EXTENSIONS) != 0 &&
1144 if (constraint_command != NULL) 1310 (certflags_flags & CERTOPT_PTY) != 0)
1145 add_string_constraint(c, "force-command", constraint_command); 1311 add_flag_option(c, "permit-pty");
1146 if (constraint_src_addr != NULL) 1312 if ((which & OPTIONS_EXTENSIONS) != 0 &&
1147 add_string_constraint(c, "source-address", constraint_src_addr); 1313 (certflags_flags & CERTOPT_USER_RC) != 0)
1314 add_flag_option(c, "permit-user-rc");
1315 if ((which & OPTIONS_EXTENSIONS) != 0 &&
1316 (certflags_flags & CERTOPT_X_FWD) != 0)
1317 add_flag_option(c, "permit-X11-forwarding");
1318 if ((which & OPTIONS_CRITICAL) != 0 &&
1319 certflags_src_addr != NULL)
1320 add_string_option(c, "source-address", certflags_src_addr);
1321}
1322
1323static Key *
1324load_pkcs11_key(char *path)
1325{
1326#ifdef ENABLE_PKCS11
1327 Key **keys = NULL, *public, *private = NULL;
1328 int i, nkeys;
1329
1330 if ((public = key_load_public(path, NULL)) == NULL)
1331 fatal("Couldn't load CA public key \"%s\"", path);
1332
1333 nkeys = pkcs11_add_provider(pkcs11provider, identity_passphrase, &keys);
1334 debug3("%s: %d keys", __func__, nkeys);
1335 if (nkeys <= 0)
1336 fatal("cannot read public key from pkcs11");
1337 for (i = 0; i < nkeys; i++) {
1338 if (key_equal_public(public, keys[i])) {
1339 private = keys[i];
1340 continue;
1341 }
1342 key_free(keys[i]);
1343 }
1344 xfree(keys);
1345 key_free(public);
1346 return private;
1347#else
1348 fatal("no pkcs11 support");
1349#endif /* ENABLE_PKCS11 */
1148} 1350}
1149 1351
1150static void 1352static void
@@ -1155,9 +1357,33 @@ do_ca_sign(struct passwd *pw, int argc, char **argv)
1155 Key *ca, *public; 1357 Key *ca, *public;
1156 char *otmp, *tmp, *cp, *out, *comment, **plist = NULL; 1358 char *otmp, *tmp, *cp, *out, *comment, **plist = NULL;
1157 FILE *f; 1359 FILE *f;
1360 int v00 = 0; /* legacy keys */
1361
1362 if (key_type_name != NULL) {
1363 switch (key_type_from_name(key_type_name)) {
1364 case KEY_RSA_CERT_V00:
1365 case KEY_DSA_CERT_V00:
1366 v00 = 1;
1367 break;
1368 case KEY_UNSPEC:
1369 if (strcasecmp(key_type_name, "v00") == 0) {
1370 v00 = 1;
1371 break;
1372 } else if (strcasecmp(key_type_name, "v01") == 0)
1373 break;
1374 /* FALLTHROUGH */
1375 default:
1376 fprintf(stderr, "unknown key type %s\n", key_type_name);
1377 exit(1);
1378 }
1379 }
1158 1380
1381 pkcs11_init(1);
1159 tmp = tilde_expand_filename(ca_key_path, pw->pw_uid); 1382 tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
1160 if ((ca = load_identity(tmp)) == NULL) 1383 if (pkcs11provider != NULL) {
1384 if ((ca = load_pkcs11_key(tmp)) == NULL)
1385 fatal("No PKCS#11 key matching %s found", ca_key_path);
1386 } else if ((ca = load_identity(tmp)) == NULL)
1161 fatal("Couldn't load CA key \"%s\"", tmp); 1387 fatal("Couldn't load CA key \"%s\"", tmp);
1162 xfree(tmp); 1388 xfree(tmp);
1163 1389
@@ -1183,15 +1409,24 @@ do_ca_sign(struct passwd *pw, int argc, char **argv)
1183 __func__, tmp, key_type(public)); 1409 __func__, tmp, key_type(public));
1184 1410
1185 /* Prepare certificate to sign */ 1411 /* Prepare certificate to sign */
1186 if (key_to_certified(public) != 0) 1412 if (key_to_certified(public, v00) != 0)
1187 fatal("Could not upgrade key %s to certificate", tmp); 1413 fatal("Could not upgrade key %s to certificate", tmp);
1188 public->cert->type = cert_key_type; 1414 public->cert->type = cert_key_type;
1415 public->cert->serial = (u_int64_t)cert_serial;
1189 public->cert->key_id = xstrdup(cert_key_id); 1416 public->cert->key_id = xstrdup(cert_key_id);
1190 public->cert->nprincipals = n; 1417 public->cert->nprincipals = n;
1191 public->cert->principals = plist; 1418 public->cert->principals = plist;
1192 public->cert->valid_after = cert_valid_from; 1419 public->cert->valid_after = cert_valid_from;
1193 public->cert->valid_before = cert_valid_to; 1420 public->cert->valid_before = cert_valid_to;
1194 prepare_constraint_buf(&public->cert->constraints); 1421 if (v00) {
1422 prepare_options_buf(&public->cert->critical,
1423 OPTIONS_CRITICAL|OPTIONS_EXTENSIONS);
1424 } else {
1425 prepare_options_buf(&public->cert->critical,
1426 OPTIONS_CRITICAL);
1427 prepare_options_buf(&public->cert->extensions,
1428 OPTIONS_EXTENSIONS);
1429 }
1195 public->cert->signature_key = key_from_private(ca); 1430 public->cert->signature_key = key_from_private(ca);
1196 1431
1197 if (key_certify(public, ca) != 0) 1432 if (key_certify(public, ca) != 0)
@@ -1212,17 +1447,19 @@ do_ca_sign(struct passwd *pw, int argc, char **argv)
1212 fprintf(f, " %s\n", comment); 1447 fprintf(f, " %s\n", comment);
1213 fclose(f); 1448 fclose(f);
1214 1449
1215 if (!quiet) 1450 if (!quiet) {
1216 logit("Signed %s key %s: id \"%s\"%s%s valid %s", 1451 logit("Signed %s key %s: id \"%s\" serial %llu%s%s "
1217 cert_key_type == SSH2_CERT_TYPE_USER?"user":"host", 1452 "valid %s", key_cert_type(public),
1218 out, cert_key_id, 1453 out, public->cert->key_id, public->cert->serial,
1219 cert_principals != NULL ? " for " : "", 1454 cert_principals != NULL ? " for " : "",
1220 cert_principals != NULL ? cert_principals : "", 1455 cert_principals != NULL ? cert_principals : "",
1221 fmt_validity(cert_valid_from, cert_valid_to)); 1456 fmt_validity(cert_valid_from, cert_valid_to));
1457 }
1222 1458
1223 key_free(public); 1459 key_free(public);
1224 xfree(out); 1460 xfree(out);
1225 } 1461 }
1462 pkcs11_terminate();
1226 exit(0); 1463 exit(0);
1227} 1464}
1228 1465
@@ -1321,50 +1558,92 @@ parse_cert_times(char *timespec)
1321} 1558}
1322 1559
1323static void 1560static void
1324add_cert_constraint(char *opt) 1561add_cert_option(char *opt)
1325{ 1562{
1326 char *val; 1563 char *val;
1327 1564
1328 if (strcmp(opt, "clear") == 0) 1565 if (strcmp(opt, "clear") == 0)
1329 constraint_flags = 0; 1566 certflags_flags = 0;
1330 else if (strcasecmp(opt, "no-x11-forwarding") == 0) 1567 else if (strcasecmp(opt, "no-x11-forwarding") == 0)
1331 constraint_flags &= ~CONSTRAINT_X_FWD; 1568 certflags_flags &= ~CERTOPT_X_FWD;
1332 else if (strcasecmp(opt, "permit-x11-forwarding") == 0) 1569 else if (strcasecmp(opt, "permit-x11-forwarding") == 0)
1333 constraint_flags |= CONSTRAINT_X_FWD; 1570 certflags_flags |= CERTOPT_X_FWD;
1334 else if (strcasecmp(opt, "no-agent-forwarding") == 0) 1571 else if (strcasecmp(opt, "no-agent-forwarding") == 0)
1335 constraint_flags &= ~CONSTRAINT_AGENT_FWD; 1572 certflags_flags &= ~CERTOPT_AGENT_FWD;
1336 else if (strcasecmp(opt, "permit-agent-forwarding") == 0) 1573 else if (strcasecmp(opt, "permit-agent-forwarding") == 0)
1337 constraint_flags |= CONSTRAINT_AGENT_FWD; 1574 certflags_flags |= CERTOPT_AGENT_FWD;
1338 else if (strcasecmp(opt, "no-port-forwarding") == 0) 1575 else if (strcasecmp(opt, "no-port-forwarding") == 0)
1339 constraint_flags &= ~CONSTRAINT_PORT_FWD; 1576 certflags_flags &= ~CERTOPT_PORT_FWD;
1340 else if (strcasecmp(opt, "permit-port-forwarding") == 0) 1577 else if (strcasecmp(opt, "permit-port-forwarding") == 0)
1341 constraint_flags |= CONSTRAINT_PORT_FWD; 1578 certflags_flags |= CERTOPT_PORT_FWD;
1342 else if (strcasecmp(opt, "no-pty") == 0) 1579 else if (strcasecmp(opt, "no-pty") == 0)
1343 constraint_flags &= ~CONSTRAINT_PTY; 1580 certflags_flags &= ~CERTOPT_PTY;
1344 else if (strcasecmp(opt, "permit-pty") == 0) 1581 else if (strcasecmp(opt, "permit-pty") == 0)
1345 constraint_flags |= CONSTRAINT_PTY; 1582 certflags_flags |= CERTOPT_PTY;
1346 else if (strcasecmp(opt, "no-user-rc") == 0) 1583 else if (strcasecmp(opt, "no-user-rc") == 0)
1347 constraint_flags &= ~CONSTRAINT_USER_RC; 1584 certflags_flags &= ~CERTOPT_USER_RC;
1348 else if (strcasecmp(opt, "permit-user-rc") == 0) 1585 else if (strcasecmp(opt, "permit-user-rc") == 0)
1349 constraint_flags |= CONSTRAINT_USER_RC; 1586 certflags_flags |= CERTOPT_USER_RC;
1350 else if (strncasecmp(opt, "force-command=", 14) == 0) { 1587 else if (strncasecmp(opt, "force-command=", 14) == 0) {
1351 val = opt + 14; 1588 val = opt + 14;
1352 if (*val == '\0') 1589 if (*val == '\0')
1353 fatal("Empty force-command constraint"); 1590 fatal("Empty force-command option");
1354 if (constraint_command != NULL) 1591 if (certflags_command != NULL)
1355 fatal("force-command already specified"); 1592 fatal("force-command already specified");
1356 constraint_command = xstrdup(val); 1593 certflags_command = xstrdup(val);
1357 } else if (strncasecmp(opt, "source-address=", 15) == 0) { 1594 } else if (strncasecmp(opt, "source-address=", 15) == 0) {
1358 val = opt + 15; 1595 val = opt + 15;
1359 if (*val == '\0') 1596 if (*val == '\0')
1360 fatal("Empty source-address constraint"); 1597 fatal("Empty source-address option");
1361 if (constraint_src_addr != NULL) 1598 if (certflags_src_addr != NULL)
1362 fatal("source-address already specified"); 1599 fatal("source-address already specified");
1363 if (addr_match_cidr_list(NULL, val) != 0) 1600 if (addr_match_cidr_list(NULL, val) != 0)
1364 fatal("Invalid source-address list"); 1601 fatal("Invalid source-address list");
1365 constraint_src_addr = xstrdup(val); 1602 certflags_src_addr = xstrdup(val);
1366 } else 1603 } else
1367 fatal("Unsupported certificate constraint \"%s\"", opt); 1604 fatal("Unsupported certificate option \"%s\"", opt);
1605}
1606
1607static void
1608show_options(const Buffer *optbuf, int v00, int in_critical)
1609{
1610 u_char *name, *data;
1611 u_int dlen;
1612 Buffer options, option;
1613
1614 buffer_init(&options);
1615 buffer_append(&options, buffer_ptr(optbuf), buffer_len(optbuf));
1616
1617 buffer_init(&option);
1618 while (buffer_len(&options) != 0) {
1619 name = buffer_get_string(&options, NULL);
1620 data = buffer_get_string_ptr(&options, &dlen);
1621 buffer_append(&option, data, dlen);
1622 printf(" %s", name);
1623 if ((v00 || !in_critical) &&
1624 (strcmp(name, "permit-X11-forwarding") == 0 ||
1625 strcmp(name, "permit-agent-forwarding") == 0 ||
1626 strcmp(name, "permit-port-forwarding") == 0 ||
1627 strcmp(name, "permit-pty") == 0 ||
1628 strcmp(name, "permit-user-rc") == 0))
1629 printf("\n");
1630 else if ((v00 || in_critical) &&
1631 (strcmp(name, "force-command") == 0 ||
1632 strcmp(name, "source-address") == 0)) {
1633 data = buffer_get_string(&option, NULL);
1634 printf(" %s\n", data);
1635 xfree(data);
1636 } else {
1637 printf(" UNKNOWN OPTION (len %u)\n",
1638 buffer_len(&option));
1639 buffer_clear(&option);
1640 }
1641 xfree(name);
1642 if (buffer_len(&option) != 0)
1643 fatal("Option corrupt: extra data at end");
1644 }
1645 buffer_free(&option);
1646 buffer_free(&options);
1368} 1647}
1369 1648
1370static void 1649static void
@@ -1373,31 +1652,31 @@ do_show_cert(struct passwd *pw)
1373 Key *key; 1652 Key *key;
1374 struct stat st; 1653 struct stat st;
1375 char *key_fp, *ca_fp; 1654 char *key_fp, *ca_fp;
1376 Buffer constraints, constraint; 1655 u_int i, v00;
1377 u_char *name, *data;
1378 u_int i, dlen;
1379 1656
1380 if (!have_identity) 1657 if (!have_identity)
1381 ask_filename(pw, "Enter file in which the key is"); 1658 ask_filename(pw, "Enter file in which the key is");
1382 if (stat(identity_file, &st) < 0) { 1659 if (stat(identity_file, &st) < 0)
1383 perror(identity_file); 1660 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
1384 exit(1);
1385 }
1386 if ((key = key_load_public(identity_file, NULL)) == NULL) 1661 if ((key = key_load_public(identity_file, NULL)) == NULL)
1387 fatal("%s is not a public key", identity_file); 1662 fatal("%s is not a public key", identity_file);
1388 if (!key_is_cert(key)) 1663 if (!key_is_cert(key))
1389 fatal("%s is not a certificate", identity_file); 1664 fatal("%s is not a certificate", identity_file);
1390 1665 v00 = key->type == KEY_RSA_CERT_V00 || key->type == KEY_DSA_CERT_V00;
1666
1391 key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); 1667 key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
1392 ca_fp = key_fingerprint(key->cert->signature_key, 1668 ca_fp = key_fingerprint(key->cert->signature_key,
1393 SSH_FP_MD5, SSH_FP_HEX); 1669 SSH_FP_MD5, SSH_FP_HEX);
1394 1670
1395 printf("%s:\n", identity_file); 1671 printf("%s:\n", identity_file);
1396 printf(" %s %s certificate %s\n", key_type(key), 1672 printf(" Type: %s %s certificate\n", key_ssh_name(key),
1397 key_cert_type(key), key_fp); 1673 key_cert_type(key));
1398 printf(" Signed by %s CA %s\n", 1674 printf(" Public key: %s %s\n", key_type(key), key_fp);
1675 printf(" Signing CA: %s %s\n",
1399 key_type(key->cert->signature_key), ca_fp); 1676 key_type(key->cert->signature_key), ca_fp);
1400 printf(" Key ID \"%s\"\n", key->cert->key_id); 1677 printf(" Key ID: \"%s\"\n", key->cert->key_id);
1678 if (!v00)
1679 printf(" Serial: %llu\n", key->cert->serial);
1401 printf(" Valid: %s\n", 1680 printf(" Valid: %s\n",
1402 fmt_validity(key->cert->valid_after, key->cert->valid_before)); 1681 fmt_validity(key->cert->valid_after, key->cert->valid_before));
1403 printf(" Principals: "); 1682 printf(" Principals: ");
@@ -1409,45 +1688,22 @@ do_show_cert(struct passwd *pw)
1409 key->cert->principals[i]); 1688 key->cert->principals[i]);
1410 printf("\n"); 1689 printf("\n");
1411 } 1690 }
1412 printf(" Constraints: "); 1691 printf(" Critical Options: ");
1413 if (buffer_len(&key->cert->constraints) == 0) 1692 if (buffer_len(&key->cert->critical) == 0)
1414 printf("(none)\n"); 1693 printf("(none)\n");
1415 else { 1694 else {
1416 printf("\n"); 1695 printf("\n");
1417 buffer_init(&constraints); 1696 show_options(&key->cert->critical, v00, 1);
1418 buffer_append(&constraints, 1697 }
1419 buffer_ptr(&key->cert->constraints), 1698 if (!v00) {
1420 buffer_len(&key->cert->constraints)); 1699 printf(" Extensions: ");
1421 buffer_init(&constraint); 1700 if (buffer_len(&key->cert->extensions) == 0)
1422 while (buffer_len(&constraints) != 0) { 1701 printf("(none)\n");
1423 name = buffer_get_string(&constraints, NULL); 1702 else {
1424 data = buffer_get_string_ptr(&constraints, &dlen); 1703 printf("\n");
1425 buffer_append(&constraint, data, dlen); 1704 show_options(&key->cert->extensions, v00, 0);
1426 printf(" %s", name);
1427 if (strcmp(name, "permit-X11-forwarding") == 0 ||
1428 strcmp(name, "permit-agent-forwarding") == 0 ||
1429 strcmp(name, "permit-port-forwarding") == 0 ||
1430 strcmp(name, "permit-pty") == 0 ||
1431 strcmp(name, "permit-user-rc") == 0)
1432 printf("\n");
1433 else if (strcmp(name, "force-command") == 0 ||
1434 strcmp(name, "source-address") == 0) {
1435 data = buffer_get_string(&constraint, NULL);
1436 printf(" %s\n", data);
1437 xfree(data);
1438 } else {
1439 printf(" UNKNOWN CONSTRAINT (len %u)\n",
1440 buffer_len(&constraint));
1441 buffer_clear(&constraint);
1442 }
1443 xfree(name);
1444 if (buffer_len(&constraint) != 0)
1445 fatal("Constraint corrupt: extra data at end");
1446 } 1705 }
1447 buffer_free(&constraint);
1448 buffer_free(&constraints);
1449 } 1706 }
1450
1451 exit(0); 1707 exit(0);
1452} 1708}
1453 1709
@@ -1464,7 +1720,7 @@ usage(void)
1464#ifdef ENABLE_PKCS11 1720#ifdef ENABLE_PKCS11
1465 fprintf(stderr, " -D pkcs11 Download public key from pkcs11 token.\n"); 1721 fprintf(stderr, " -D pkcs11 Download public key from pkcs11 token.\n");
1466#endif 1722#endif
1467 fprintf(stderr, " -e Convert OpenSSH to RFC 4716 key file.\n"); 1723 fprintf(stderr, " -e Export OpenSSH to foreign format key file.\n");
1468 fprintf(stderr, " -F hostname Find hostname in known hosts file.\n"); 1724 fprintf(stderr, " -F hostname Find hostname in known hosts file.\n");
1469 fprintf(stderr, " -f filename Filename of the key file.\n"); 1725 fprintf(stderr, " -f filename Filename of the key file.\n");
1470 fprintf(stderr, " -G file Generate candidates for DH-GEX moduli.\n"); 1726 fprintf(stderr, " -G file Generate candidates for DH-GEX moduli.\n");
@@ -1472,26 +1728,28 @@ usage(void)
1472 fprintf(stderr, " -H Hash names in known_hosts file.\n"); 1728 fprintf(stderr, " -H Hash names in known_hosts file.\n");
1473 fprintf(stderr, " -h Generate host certificate instead of a user certificate.\n"); 1729 fprintf(stderr, " -h Generate host certificate instead of a user certificate.\n");
1474 fprintf(stderr, " -I key_id Key identifier to include in certificate.\n"); 1730 fprintf(stderr, " -I key_id Key identifier to include in certificate.\n");
1475 fprintf(stderr, " -i Convert RFC 4716 to OpenSSH key file.\n"); 1731 fprintf(stderr, " -i Import foreign format to OpenSSH key file.\n");
1476 fprintf(stderr, " -L Print the contents of a certificate.\n"); 1732 fprintf(stderr, " -L Print the contents of a certificate.\n");
1477 fprintf(stderr, " -l Show fingerprint of key file.\n"); 1733 fprintf(stderr, " -l Show fingerprint of key file.\n");
1478 fprintf(stderr, " -M memory Amount of memory (MB) to use for generating DH-GEX moduli.\n"); 1734 fprintf(stderr, " -M memory Amount of memory (MB) to use for generating DH-GEX moduli.\n");
1479 fprintf(stderr, " -n name,... User/host principal names to include in certificate\n"); 1735 fprintf(stderr, " -m key_fmt Conversion format for -e/-i (PEM|PKCS8|RFC4716).\n");
1480 fprintf(stderr, " -N phrase Provide new passphrase.\n"); 1736 fprintf(stderr, " -N phrase Provide new passphrase.\n");
1481 fprintf(stderr, " -O cnstr Specify a certificate constraint.\n"); 1737 fprintf(stderr, " -n name,... User/host principal names to include in certificate\n");
1738 fprintf(stderr, " -O option Specify a certificate option.\n");
1482 fprintf(stderr, " -P phrase Provide old passphrase.\n"); 1739 fprintf(stderr, " -P phrase Provide old passphrase.\n");
1483 fprintf(stderr, " -p Change passphrase of private key file.\n"); 1740 fprintf(stderr, " -p Change passphrase of private key file.\n");
1484 fprintf(stderr, " -q Quiet.\n"); 1741 fprintf(stderr, " -q Quiet.\n");
1485 fprintf(stderr, " -R hostname Remove host from known_hosts file.\n"); 1742 fprintf(stderr, " -R hostname Remove host from known_hosts file.\n");
1486 fprintf(stderr, " -r hostname Print DNS resource record.\n"); 1743 fprintf(stderr, " -r hostname Print DNS resource record.\n");
1487 fprintf(stderr, " -s ca_key Certify keys with CA key.\n");
1488 fprintf(stderr, " -S start Start point (hex) for generating DH-GEX moduli.\n"); 1744 fprintf(stderr, " -S start Start point (hex) for generating DH-GEX moduli.\n");
1745 fprintf(stderr, " -s ca_key Certify keys with CA key.\n");
1489 fprintf(stderr, " -T file Screen candidates for DH-GEX moduli.\n"); 1746 fprintf(stderr, " -T file Screen candidates for DH-GEX moduli.\n");
1490 fprintf(stderr, " -t type Specify type of key to create.\n"); 1747 fprintf(stderr, " -t type Specify type of key to create.\n");
1491 fprintf(stderr, " -V from:to Specify certificate validity interval.\n"); 1748 fprintf(stderr, " -V from:to Specify certificate validity interval.\n");
1492 fprintf(stderr, " -v Verbose.\n"); 1749 fprintf(stderr, " -v Verbose.\n");
1493 fprintf(stderr, " -W gen Generator to use for generating DH-GEX moduli.\n"); 1750 fprintf(stderr, " -W gen Generator to use for generating DH-GEX moduli.\n");
1494 fprintf(stderr, " -y Read private key file and print public key.\n"); 1751 fprintf(stderr, " -y Read private key file and print public key.\n");
1752 fprintf(stderr, " -z serial Specify a serial number.\n");
1495 1753
1496 exit(1); 1754 exit(1);
1497} 1755}
@@ -1503,12 +1761,12 @@ int
1503main(int argc, char **argv) 1761main(int argc, char **argv)
1504{ 1762{
1505 char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2; 1763 char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2;
1506 char out_file[MAXPATHLEN], *pkcs11provider = NULL; 1764 char out_file[MAXPATHLEN], *rr_hostname = NULL;
1507 char *rr_hostname = NULL;
1508 Key *private, *public; 1765 Key *private, *public;
1509 struct passwd *pw; 1766 struct passwd *pw;
1510 struct stat st; 1767 struct stat st;
1511 int opt, type, fd; 1768 int opt, type, fd;
1769 u_int maxbits;
1512 u_int32_t memory = 0, generator_wanted = 0, trials = 100; 1770 u_int32_t memory = 0, generator_wanted = 0, trials = 100;
1513 int do_gen_candidates = 0, do_screen_candidates = 0; 1771 int do_gen_candidates = 0, do_screen_candidates = 0;
1514 BIGNUM *start = NULL; 1772 BIGNUM *start = NULL;
@@ -1540,8 +1798,8 @@ main(int argc, char **argv)
1540 exit(1); 1798 exit(1);
1541 } 1799 }
1542 1800
1543 while ((opt = getopt(argc, argv, "degiqpclBHLhvxXyF:b:f:t:D:I:P:N:n:" 1801 while ((opt = getopt(argc, argv, "degiqpclBHLhvxXyF:b:f:t:D:I:P:m:N:n:"
1544 "O:C:r:g:R:T:G:M:S:s:a:V:W:")) != -1) { 1802 "O:C:r:g:R:T:G:M:S:s:a:V:W:z:")) != -1) {
1545 switch (opt) { 1803 switch (opt) {
1546 case 'b': 1804 case 'b':
1547 bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr); 1805 bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr);
@@ -1572,6 +1830,21 @@ main(int argc, char **argv)
1572 case 'B': 1830 case 'B':
1573 print_bubblebabble = 1; 1831 print_bubblebabble = 1;
1574 break; 1832 break;
1833 case 'm':
1834 if (strcasecmp(optarg, "RFC4716") == 0 ||
1835 strcasecmp(optarg, "ssh2") == 0) {
1836 convert_format = FMT_RFC4716;
1837 break;
1838 }
1839 if (strcasecmp(optarg, "PKCS8") == 0) {
1840 convert_format = FMT_PKCS8;
1841 break;
1842 }
1843 if (strcasecmp(optarg, "PEM") == 0) {
1844 convert_format = FMT_PEM;
1845 break;
1846 }
1847 fatal("Unsupported conversion format \"%s\"", optarg);
1575 case 'n': 1848 case 'n':
1576 cert_principals = optarg; 1849 cert_principals = optarg;
1577 break; 1850 break;
@@ -1597,7 +1870,7 @@ main(int argc, char **argv)
1597 identity_new_passphrase = optarg; 1870 identity_new_passphrase = optarg;
1598 break; 1871 break;
1599 case 'O': 1872 case 'O':
1600 add_cert_constraint(optarg); 1873 add_cert_option(optarg);
1601 break; 1874 break;
1602 case 'C': 1875 case 'C':
1603 identity_comment = optarg; 1876 identity_comment = optarg;
@@ -1608,16 +1881,16 @@ main(int argc, char **argv)
1608 case 'e': 1881 case 'e':
1609 case 'x': 1882 case 'x':
1610 /* export key */ 1883 /* export key */
1611 convert_to_ssh2 = 1; 1884 convert_to = 1;
1612 break; 1885 break;
1613 case 'h': 1886 case 'h':
1614 cert_key_type = SSH2_CERT_TYPE_HOST; 1887 cert_key_type = SSH2_CERT_TYPE_HOST;
1615 constraint_flags = 0; 1888 certflags_flags = 0;
1616 break; 1889 break;
1617 case 'i': 1890 case 'i':
1618 case 'X': 1891 case 'X':
1619 /* import key */ 1892 /* import key */
1620 convert_from_ssh2 = 1; 1893 convert_from = 1;
1621 break; 1894 break;
1622 case 'y': 1895 case 'y':
1623 print_public = 1; 1896 print_public = 1;
@@ -1661,9 +1934,8 @@ main(int argc, char **argv)
1661 break; 1934 break;
1662 case 'M': 1935 case 'M':
1663 memory = (u_int32_t)strtonum(optarg, 1, UINT_MAX, &errstr); 1936 memory = (u_int32_t)strtonum(optarg, 1, UINT_MAX, &errstr);
1664 if (errstr) { 1937 if (errstr)
1665 fatal("Memory limit is %s: %s", errstr, optarg); 1938 fatal("Memory limit is %s: %s", errstr, optarg);
1666 }
1667 break; 1939 break;
1668 case 'G': 1940 case 'G':
1669 do_gen_candidates = 1; 1941 do_gen_candidates = 1;
@@ -1685,6 +1957,11 @@ main(int argc, char **argv)
1685 case 'V': 1957 case 'V':
1686 parse_cert_times(optarg); 1958 parse_cert_times(optarg);
1687 break; 1959 break;
1960 case 'z':
1961 cert_serial = strtonum(optarg, 0, LLONG_MAX, &errstr);
1962 if (errstr)
1963 fatal("Invalid serial number: %s", errstr);
1964 break;
1688 case '?': 1965 case '?':
1689 default: 1966 default:
1690 usage(); 1967 usage();
@@ -1729,10 +2006,10 @@ main(int argc, char **argv)
1729 do_change_passphrase(pw); 2006 do_change_passphrase(pw);
1730 if (change_comment) 2007 if (change_comment)
1731 do_change_comment(pw); 2008 do_change_comment(pw);
1732 if (convert_to_ssh2) 2009 if (convert_to)
1733 do_convert_to_ssh2(pw); 2010 do_convert_to(pw);
1734 if (convert_from_ssh2) 2011 if (convert_from)
1735 do_convert_from_ssh2(pw); 2012 do_convert_from(pw);
1736 if (print_public) 2013 if (print_public)
1737 do_print_public(pw); 2014 do_print_public(pw);
1738 if (rr_hostname != NULL) { 2015 if (rr_hostname != NULL) {
@@ -1759,7 +2036,7 @@ main(int argc, char **argv)
1759 } 2036 }
1760 } 2037 }
1761 if (pkcs11provider != NULL) 2038 if (pkcs11provider != NULL)
1762 do_download(pw, pkcs11provider); 2039 do_download(pw);
1763 2040
1764 if (do_gen_candidates) { 2041 if (do_gen_candidates) {
1765 FILE *out = fopen(out_file, "w"); 2042 FILE *out = fopen(out_file, "w");
@@ -1811,6 +2088,12 @@ main(int argc, char **argv)
1811 } 2088 }
1812 if (bits == 0) 2089 if (bits == 0)
1813 bits = (type == KEY_DSA) ? DEFAULT_BITS_DSA : DEFAULT_BITS; 2090 bits = (type == KEY_DSA) ? DEFAULT_BITS_DSA : DEFAULT_BITS;
2091 maxbits = (type == KEY_DSA) ?
2092 OPENSSL_DSA_MAX_MODULUS_BITS : OPENSSL_RSA_MAX_MODULUS_BITS;
2093 if (bits > maxbits) {
2094 fprintf(stderr, "key bits exceeds maximum %d\n", maxbits);
2095 exit(1);
2096 }
1814 if (type == KEY_DSA && bits != 1024) 2097 if (type == KEY_DSA && bits != 1024)
1815 fatal("DSA keys must be 1024 bits"); 2098 fatal("DSA keys must be 1024 bits");
1816 if (!quiet) 2099 if (!quiet)
@@ -1826,13 +2109,19 @@ main(int argc, char **argv)
1826 ask_filename(pw, "Enter file in which to save the key"); 2109 ask_filename(pw, "Enter file in which to save the key");
1827 2110
1828 /* Create ~/.ssh directory if it doesn't already exist. */ 2111 /* Create ~/.ssh directory if it doesn't already exist. */
1829 snprintf(dotsshdir, sizeof dotsshdir, "%s/%s", pw->pw_dir, _PATH_SSH_USER_DIR); 2112 snprintf(dotsshdir, sizeof dotsshdir, "%s/%s",
1830 if (strstr(identity_file, dotsshdir) != NULL && 2113 pw->pw_dir, _PATH_SSH_USER_DIR);
1831 stat(dotsshdir, &st) < 0) { 2114 if (strstr(identity_file, dotsshdir) != NULL) {
1832 if (mkdir(dotsshdir, 0700) < 0) 2115 if (stat(dotsshdir, &st) < 0) {
1833 error("Could not create directory '%s'.", dotsshdir); 2116 if (errno != ENOENT) {
1834 else if (!quiet) 2117 error("Could not stat %s: %s", dotsshdir,
1835 printf("Created directory '%s'.\n", dotsshdir); 2118 strerror(errno));
2119 } else if (mkdir(dotsshdir, 0700) < 0) {
2120 error("Could not create directory '%s': %s",
2121 dotsshdir, strerror(errno));
2122 } else if (!quiet)
2123 printf("Created directory '%s'.\n", dotsshdir);
2124 }
1836 } 2125 }
1837 /* If the file already exists, ask the user to confirm. */ 2126 /* If the file already exists, ask the user to confirm. */
1838 if (stat(identity_file, &st) >= 0) { 2127 if (stat(identity_file, &st) >= 0) {