diff options
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | ssh-keygen.1 | 10 | ||||
-rw-r--r-- | ssh-keygen.c | 115 |
3 files changed, 114 insertions, 14 deletions
@@ -3,6 +3,9 @@ | |||
3 | - jmc@cvs.openbsd.org 2010/03/04 12:51:25 | 3 | - jmc@cvs.openbsd.org 2010/03/04 12:51:25 |
4 | [ssh.1 sshd_config.5] | 4 | [ssh.1 sshd_config.5] |
5 | tweak previous; | 5 | tweak previous; |
6 | - djm@cvs.openbsd.org 2010/03/04 20:35:08 | ||
7 | [ssh-keygen.1 ssh-keygen.c] | ||
8 | Add a -L flag to print the contents of a certificate; ok markus@ | ||
6 | 9 | ||
7 | 20100304 | 10 | 20100304 |
8 | - (djm) [ssh-keygen.c] Use correct local variable, instead of | 11 | - (djm) [ssh-keygen.c] Use correct local variable, instead of |
diff --git a/ssh-keygen.1 b/ssh-keygen.1 index d704f0660..dccf5eabc 100644 --- a/ssh-keygen.1 +++ b/ssh-keygen.1 | |||
@@ -1,4 +1,4 @@ | |||
1 | .\" $OpenBSD: ssh-keygen.1,v 1.85 2010/02/26 22:09:28 jmc Exp $ | 1 | .\" $OpenBSD: ssh-keygen.1,v 1.86 2010/03/04 20:35:08 djm Exp $ |
2 | .\" | 2 | .\" |
3 | .\" -*- nroff -*- | 3 | .\" -*- nroff -*- |
4 | .\" | 4 | .\" |
@@ -37,7 +37,7 @@ | |||
37 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 37 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
38 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 38 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
39 | .\" | 39 | .\" |
40 | .Dd $Mdocdate: February 26 2010 $ | 40 | .Dd $Mdocdate: March 4 2010 $ |
41 | .Dt SSH-KEYGEN 1 | 41 | .Dt SSH-KEYGEN 1 |
42 | .Os | 42 | .Os |
43 | .Sh NAME | 43 | .Sh NAME |
@@ -115,6 +115,10 @@ | |||
115 | .Op Fl O Ar constraint | 115 | .Op Fl O Ar constraint |
116 | .Op Fl V Ar validity_interval | 116 | .Op Fl V Ar validity_interval |
117 | .Ar | 117 | .Ar |
118 | .Nm ssh-keygen | ||
119 | .Bk -words | ||
120 | .Fl L | ||
121 | .Op Fl f Ar input_keyfile | ||
118 | .Ek | 122 | .Ek |
119 | .Sh DESCRIPTION | 123 | .Sh DESCRIPTION |
120 | .Nm | 124 | .Nm |
@@ -275,6 +279,8 @@ also reads the | |||
275 | RFC 4716 SSH Public Key File Format. | 279 | RFC 4716 SSH Public Key File Format. |
276 | This option allows importing keys from several commercial | 280 | This option allows importing keys from several commercial |
277 | SSH implementations. | 281 | SSH implementations. |
282 | .It Fl L | ||
283 | Prints the contents of a certificate. | ||
278 | .It Fl l | 284 | .It Fl l |
279 | Show fingerprint of specified public key file. | 285 | Show fingerprint of specified public key file. |
280 | Private RSA1 keys are also supported. | 286 | Private RSA1 keys are also supported. |
diff --git a/ssh-keygen.c b/ssh-keygen.c index c2120bbc1..492c301d3 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-keygen.c,v 1.181 2010/03/04 10:36:03 djm Exp $ */ | 1 | /* $OpenBSD: ssh-keygen.c,v 1.182 2010/03/04 20:35:08 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 |
@@ -82,6 +82,9 @@ int find_host = 0; | |||
82 | /* Flag indicating that we want to delete a host from a known_hosts file */ | 82 | /* Flag indicating that we want to delete a host from a known_hosts file */ |
83 | int delete_host = 0; | 83 | int delete_host = 0; |
84 | 84 | ||
85 | /* Flag indicating that we want to show the contents of a certificate */ | ||
86 | int show_cert = 0; | ||
87 | |||
85 | /* Flag indicating that we just want to see the key fingerprint */ | 88 | /* Flag indicating that we just want to see the key fingerprint */ |
86 | int print_fingerprint = 0; | 89 | int print_fingerprint = 0; |
87 | int print_bubblebabble = 0; | 90 | int print_bubblebabble = 0; |
@@ -1063,7 +1066,7 @@ do_change_comment(struct passwd *pw) | |||
1063 | } | 1066 | } |
1064 | 1067 | ||
1065 | static const char * | 1068 | static const char * |
1066 | fmt_validity(void) | 1069 | fmt_validity(u_int64_t valid_from, u_int64_t valid_to) |
1067 | { | 1070 | { |
1068 | char from[32], to[32]; | 1071 | char from[32], to[32]; |
1069 | static char ret[64]; | 1072 | static char ret[64]; |
@@ -1071,28 +1074,27 @@ fmt_validity(void) | |||
1071 | struct tm *tm; | 1074 | struct tm *tm; |
1072 | 1075 | ||
1073 | *from = *to = '\0'; | 1076 | *from = *to = '\0'; |
1074 | if (cert_valid_from == 0 && | 1077 | if (valid_from == 0 && valid_to == 0xffffffffffffffffULL) |
1075 | cert_valid_to == 0xffffffffffffffffULL) | ||
1076 | return "forever"; | 1078 | return "forever"; |
1077 | 1079 | ||
1078 | if (cert_valid_from != 0) { | 1080 | if (valid_from != 0) { |
1079 | /* XXX revisit INT_MAX in 2038 :) */ | 1081 | /* XXX revisit INT_MAX in 2038 :) */ |
1080 | tt = cert_valid_from > INT_MAX ? INT_MAX : cert_valid_from; | 1082 | tt = valid_from > INT_MAX ? INT_MAX : valid_from; |
1081 | tm = localtime(&tt); | 1083 | tm = localtime(&tt); |
1082 | strftime(from, sizeof(from), "%Y-%m-%dT%H:%M:%S", tm); | 1084 | strftime(from, sizeof(from), "%Y-%m-%dT%H:%M:%S", tm); |
1083 | } | 1085 | } |
1084 | if (cert_valid_to != 0xffffffffffffffffULL) { | 1086 | if (valid_to != 0xffffffffffffffffULL) { |
1085 | /* XXX revisit INT_MAX in 2038 :) */ | 1087 | /* XXX revisit INT_MAX in 2038 :) */ |
1086 | tt = cert_valid_to > INT_MAX ? INT_MAX : cert_valid_to; | 1088 | tt = valid_to > INT_MAX ? INT_MAX : valid_to; |
1087 | tm = localtime(&tt); | 1089 | tm = localtime(&tt); |
1088 | strftime(to, sizeof(to), "%Y-%m-%dT%H:%M:%S", tm); | 1090 | strftime(to, sizeof(to), "%Y-%m-%dT%H:%M:%S", tm); |
1089 | } | 1091 | } |
1090 | 1092 | ||
1091 | if (cert_valid_from == 0) { | 1093 | if (valid_from == 0) { |
1092 | snprintf(ret, sizeof(ret), "before %s", to); | 1094 | snprintf(ret, sizeof(ret), "before %s", to); |
1093 | return ret; | 1095 | return ret; |
1094 | } | 1096 | } |
1095 | if (cert_valid_to == 0xffffffffffffffffULL) { | 1097 | if (valid_to == 0xffffffffffffffffULL) { |
1096 | snprintf(ret, sizeof(ret), "after %s", from); | 1098 | snprintf(ret, sizeof(ret), "after %s", from); |
1097 | return ret; | 1099 | return ret; |
1098 | } | 1100 | } |
@@ -1216,7 +1218,7 @@ do_ca_sign(struct passwd *pw, int argc, char **argv) | |||
1216 | out, cert_key_id, | 1218 | out, cert_key_id, |
1217 | cert_principals != NULL ? " for " : "", | 1219 | cert_principals != NULL ? " for " : "", |
1218 | cert_principals != NULL ? cert_principals : "", | 1220 | cert_principals != NULL ? cert_principals : "", |
1219 | fmt_validity()); | 1221 | fmt_validity(cert_valid_from, cert_valid_to)); |
1220 | 1222 | ||
1221 | key_free(public); | 1223 | key_free(public); |
1222 | xfree(out); | 1224 | xfree(out); |
@@ -1366,6 +1368,89 @@ add_cert_constraint(char *opt) | |||
1366 | } | 1368 | } |
1367 | 1369 | ||
1368 | static void | 1370 | static void |
1371 | do_show_cert(struct passwd *pw) | ||
1372 | { | ||
1373 | Key *key; | ||
1374 | struct stat st; | ||
1375 | char *key_fp, *ca_fp; | ||
1376 | Buffer constraints, constraint; | ||
1377 | u_char *name, *data; | ||
1378 | u_int i, dlen; | ||
1379 | |||
1380 | if (!have_identity) | ||
1381 | ask_filename(pw, "Enter file in which the key is"); | ||
1382 | if (stat(identity_file, &st) < 0) { | ||
1383 | perror(identity_file); | ||
1384 | exit(1); | ||
1385 | } | ||
1386 | if ((key = key_load_public(identity_file, NULL)) == NULL) | ||
1387 | fatal("%s is not a public key", identity_file); | ||
1388 | if (!key_is_cert(key)) | ||
1389 | fatal("%s is not a certificate", identity_file); | ||
1390 | |||
1391 | key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); | ||
1392 | ca_fp = key_fingerprint(key->cert->signature_key, | ||
1393 | SSH_FP_MD5, SSH_FP_HEX); | ||
1394 | |||
1395 | printf("%s:\n", identity_file); | ||
1396 | printf(" %s certificate %s\n", key_type(key), key_fp); | ||
1397 | printf(" Signed by %s CA %s\n", | ||
1398 | key_type(key->cert->signature_key), ca_fp); | ||
1399 | printf(" Key ID \"%s\"\n", key->cert->key_id); | ||
1400 | printf(" Valid: %s\n", | ||
1401 | fmt_validity(key->cert->valid_after, key->cert->valid_before)); | ||
1402 | printf(" Principals: "); | ||
1403 | if (key->cert->nprincipals == 0) | ||
1404 | printf("(none)\n"); | ||
1405 | else { | ||
1406 | for (i = 0; i < key->cert->nprincipals; i++) | ||
1407 | printf("\n %s", | ||
1408 | key->cert->principals[i]); | ||
1409 | printf("\n"); | ||
1410 | } | ||
1411 | printf(" Constraints: "); | ||
1412 | if (buffer_len(&key->cert->constraints) == 0) | ||
1413 | printf("(none)\n"); | ||
1414 | else { | ||
1415 | printf("\n"); | ||
1416 | buffer_init(&constraints); | ||
1417 | buffer_append(&constraints, | ||
1418 | buffer_ptr(&key->cert->constraints), | ||
1419 | buffer_len(&key->cert->constraints)); | ||
1420 | buffer_init(&constraint); | ||
1421 | while (buffer_len(&constraints) != 0) { | ||
1422 | name = buffer_get_string(&constraints, NULL); | ||
1423 | data = buffer_get_string_ptr(&constraints, &dlen); | ||
1424 | buffer_append(&constraint, data, dlen); | ||
1425 | printf(" %s", name); | ||
1426 | if (strcmp(name, "permit-X11-forwarding") == 0 || | ||
1427 | strcmp(name, "permit-agent-forwarding") == 0 || | ||
1428 | strcmp(name, "permit-port-forwarding") == 0 || | ||
1429 | strcmp(name, "permit-pty") == 0 || | ||
1430 | strcmp(name, "permit-user-rc") == 0) | ||
1431 | printf("\n"); | ||
1432 | else if (strcmp(name, "force-command") == 0 || | ||
1433 | strcmp(name, "source-address") == 0) { | ||
1434 | data = buffer_get_string(&constraint, NULL); | ||
1435 | printf(" %s\n", data); | ||
1436 | xfree(data); | ||
1437 | } else { | ||
1438 | printf(" UNKNOWN CONSTRAINT (len %u)\n", | ||
1439 | buffer_len(&constraint)); | ||
1440 | buffer_clear(&constraint); | ||
1441 | } | ||
1442 | xfree(name); | ||
1443 | if (buffer_len(&constraint) != 0) | ||
1444 | fatal("Constraint corrupt: extra data at end"); | ||
1445 | } | ||
1446 | buffer_free(&constraint); | ||
1447 | buffer_free(&constraints); | ||
1448 | } | ||
1449 | |||
1450 | exit(0); | ||
1451 | } | ||
1452 | |||
1453 | static void | ||
1369 | usage(void) | 1454 | usage(void) |
1370 | { | 1455 | { |
1371 | fprintf(stderr, "usage: %s [options]\n", __progname); | 1456 | fprintf(stderr, "usage: %s [options]\n", __progname); |
@@ -1387,6 +1472,7 @@ usage(void) | |||
1387 | fprintf(stderr, " -h Generate host certificate instead of a user certificate.\n"); | 1472 | fprintf(stderr, " -h Generate host certificate instead of a user certificate.\n"); |
1388 | fprintf(stderr, " -I key_id Key identifier to include in certificate.\n"); | 1473 | fprintf(stderr, " -I key_id Key identifier to include in certificate.\n"); |
1389 | fprintf(stderr, " -i Convert RFC 4716 to OpenSSH key file.\n"); | 1474 | fprintf(stderr, " -i Convert RFC 4716 to OpenSSH key file.\n"); |
1475 | fprintf(stderr, " -L Print the contents of a certificate.\n"); | ||
1390 | fprintf(stderr, " -l Show fingerprint of key file.\n"); | 1476 | fprintf(stderr, " -l Show fingerprint of key file.\n"); |
1391 | fprintf(stderr, " -M memory Amount of memory (MB) to use for generating DH-GEX moduli.\n"); | 1477 | fprintf(stderr, " -M memory Amount of memory (MB) to use for generating DH-GEX moduli.\n"); |
1392 | fprintf(stderr, " -n name,... User/host principal names to include in certificate\n"); | 1478 | fprintf(stderr, " -n name,... User/host principal names to include in certificate\n"); |
@@ -1453,7 +1539,7 @@ main(int argc, char **argv) | |||
1453 | exit(1); | 1539 | exit(1); |
1454 | } | 1540 | } |
1455 | 1541 | ||
1456 | while ((opt = getopt(argc, argv, "degiqpclBHhvxXyF:b:f:t:D:I:P:N:n:" | 1542 | while ((opt = getopt(argc, argv, "degiqpclBHLhvxXyF:b:f:t:D:I:P:N:n:" |
1457 | "O:C:r:g:R:T:G:M:S:s:a:V:W:")) != -1) { | 1543 | "O:C:r:g:R:T:G:M:S:s:a:V:W:")) != -1) { |
1458 | switch (opt) { | 1544 | switch (opt) { |
1459 | case 'b': | 1545 | case 'b': |
@@ -1476,6 +1562,9 @@ main(int argc, char **argv) | |||
1476 | delete_host = 1; | 1562 | delete_host = 1; |
1477 | rr_hostname = optarg; | 1563 | rr_hostname = optarg; |
1478 | break; | 1564 | break; |
1565 | case 'L': | ||
1566 | show_cert = 1; | ||
1567 | break; | ||
1479 | case 'l': | 1568 | case 'l': |
1480 | print_fingerprint = 1; | 1569 | print_fingerprint = 1; |
1481 | break; | 1570 | break; |
@@ -1629,6 +1718,8 @@ main(int argc, char **argv) | |||
1629 | fatal("Must specify key id (-I) when certifying"); | 1718 | fatal("Must specify key id (-I) when certifying"); |
1630 | do_ca_sign(pw, argc, argv); | 1719 | do_ca_sign(pw, argc, argv); |
1631 | } | 1720 | } |
1721 | if (show_cert) | ||
1722 | do_show_cert(pw); | ||
1632 | if (delete_host || hash_hosts || find_host) | 1723 | if (delete_host || hash_hosts || find_host) |
1633 | do_known_hosts(pw, rr_hostname); | 1724 | do_known_hosts(pw, rr_hostname); |
1634 | if (print_fingerprint || print_bubblebabble) | 1725 | if (print_fingerprint || print_bubblebabble) |