diff options
author | Colin Watson <cjwatson@debian.org> | 2016-02-29 12:15:15 +0000 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2016-03-08 11:51:22 +0000 |
commit | 46961f5704f8e86cea3e99253faad55aef4d8f35 (patch) | |
tree | 0dd97fa4fb649a62b4639fe2674380872b1f3e98 /ssh-keygen.c | |
parent | c753fe267efb1b027424fa8706cf0385fc3d14c1 (diff) | |
parent | 85e40e87a75fb80a0bf893ac05a417d6c353537d (diff) |
New upstream release (7.2).
Diffstat (limited to 'ssh-keygen.c')
-rw-r--r-- | ssh-keygen.c | 366 |
1 files changed, 210 insertions, 156 deletions
diff --git a/ssh-keygen.c b/ssh-keygen.c index 4e0a85554..478520123 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-keygen.c,v 1.277 2015/08/19 23:17:51 djm Exp $ */ | 1 | /* $OpenBSD: ssh-keygen.c,v 1.288 2016/02/15 09:47:49 dtucker 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 |
@@ -523,7 +523,7 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) | |||
523 | sshbuf_free(b); | 523 | sshbuf_free(b); |
524 | 524 | ||
525 | /* try the key */ | 525 | /* try the key */ |
526 | if (sshkey_sign(key, &sig, &slen, data, sizeof(data), 0) != 0 || | 526 | if (sshkey_sign(key, &sig, &slen, data, sizeof(data), NULL, 0) != 0 || |
527 | sshkey_verify(key, sig, slen, data, sizeof(data), 0) != 0) { | 527 | sshkey_verify(key, sig, slen, data, sizeof(data), 0) != 0) { |
528 | sshkey_free(key); | 528 | sshkey_free(key); |
529 | free(sig); | 529 | free(sig); |
@@ -808,116 +808,162 @@ do_download(struct passwd *pw) | |||
808 | #endif /* ENABLE_PKCS11 */ | 808 | #endif /* ENABLE_PKCS11 */ |
809 | } | 809 | } |
810 | 810 | ||
811 | static struct sshkey * | ||
812 | try_read_key(char **cpp) | ||
813 | { | ||
814 | struct sshkey *ret; | ||
815 | int r; | ||
816 | |||
817 | if ((ret = sshkey_new(KEY_RSA1)) == NULL) | ||
818 | fatal("sshkey_new failed"); | ||
819 | /* Try RSA1 */ | ||
820 | if ((r = sshkey_read(ret, cpp)) == 0) | ||
821 | return ret; | ||
822 | /* Try modern */ | ||
823 | sshkey_free(ret); | ||
824 | if ((ret = sshkey_new(KEY_UNSPEC)) == NULL) | ||
825 | fatal("sshkey_new failed"); | ||
826 | if ((r = sshkey_read(ret, cpp)) == 0) | ||
827 | return ret; | ||
828 | /* Not a key */ | ||
829 | sshkey_free(ret); | ||
830 | return NULL; | ||
831 | } | ||
832 | |||
811 | static void | 833 | static void |
812 | do_fingerprint(struct passwd *pw) | 834 | fingerprint_one_key(const struct sshkey *public, const char *comment) |
813 | { | 835 | { |
814 | FILE *f; | 836 | char *fp = NULL, *ra = NULL; |
815 | struct sshkey *public; | ||
816 | char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra; | ||
817 | int r, i, skip = 0, num = 0, invalid = 1; | ||
818 | enum sshkey_fp_rep rep; | 837 | enum sshkey_fp_rep rep; |
819 | int fptype; | 838 | int fptype; |
820 | struct stat st; | ||
821 | 839 | ||
822 | fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash; | 840 | fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash; |
823 | rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT; | 841 | rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT; |
824 | if (!have_identity) | 842 | fp = sshkey_fingerprint(public, fptype, rep); |
825 | ask_filename(pw, "Enter file in which the key is"); | 843 | ra = sshkey_fingerprint(public, fingerprint_hash, SSH_FP_RANDOMART); |
844 | if (fp == NULL || ra == NULL) | ||
845 | fatal("%s: sshkey_fingerprint failed", __func__); | ||
846 | printf("%u %s %s (%s)\n", sshkey_size(public), fp, | ||
847 | comment ? comment : "no comment", sshkey_type(public)); | ||
848 | if (log_level >= SYSLOG_LEVEL_VERBOSE) | ||
849 | printf("%s\n", ra); | ||
850 | free(ra); | ||
851 | free(fp); | ||
852 | } | ||
853 | |||
854 | static void | ||
855 | fingerprint_private(const char *path) | ||
856 | { | ||
857 | struct stat st; | ||
858 | char *comment = NULL; | ||
859 | struct sshkey *public = NULL; | ||
860 | int r; | ||
861 | |||
826 | if (stat(identity_file, &st) < 0) | 862 | if (stat(identity_file, &st) < 0) |
827 | fatal("%s: %s", identity_file, strerror(errno)); | 863 | fatal("%s: %s", path, strerror(errno)); |
828 | if ((r = sshkey_load_public(identity_file, &public, &comment)) != 0) | 864 | if ((r = sshkey_load_public(path, &public, &comment)) != 0) { |
829 | debug2("Error loading public key \"%s\": %s", | 865 | debug("load public \"%s\": %s", path, ssh_err(r)); |
830 | identity_file, ssh_err(r)); | 866 | if ((r = sshkey_load_private(path, NULL, |
831 | else { | 867 | &public, &comment)) != 0) { |
832 | fp = sshkey_fingerprint(public, fptype, rep); | 868 | debug("load private \"%s\": %s", path, ssh_err(r)); |
833 | ra = sshkey_fingerprint(public, fingerprint_hash, | 869 | fatal("%s is not a key file.", path); |
834 | SSH_FP_RANDOMART); | 870 | } |
835 | if (fp == NULL || ra == NULL) | ||
836 | fatal("%s: sshkey_fingerprint fail", __func__); | ||
837 | printf("%u %s %s (%s)\n", sshkey_size(public), fp, comment, | ||
838 | sshkey_type(public)); | ||
839 | if (log_level >= SYSLOG_LEVEL_VERBOSE) | ||
840 | printf("%s\n", ra); | ||
841 | sshkey_free(public); | ||
842 | free(comment); | ||
843 | free(ra); | ||
844 | free(fp); | ||
845 | exit(0); | ||
846 | } | ||
847 | if (comment) { | ||
848 | free(comment); | ||
849 | comment = NULL; | ||
850 | } | 871 | } |
851 | 872 | ||
852 | if ((f = fopen(identity_file, "r")) == NULL) | 873 | fingerprint_one_key(public, comment); |
853 | fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); | 874 | sshkey_free(public); |
875 | free(comment); | ||
876 | } | ||
854 | 877 | ||
855 | while (fgets(line, sizeof(line), f)) { | 878 | static void |
856 | if ((cp = strchr(line, '\n')) == NULL) { | 879 | do_fingerprint(struct passwd *pw) |
857 | error("line %d too long: %.40s...", | 880 | { |
858 | num + 1, line); | 881 | FILE *f; |
859 | skip = 1; | 882 | struct sshkey *public = NULL; |
883 | char *comment = NULL, *cp, *ep, line[SSH_MAX_PUBKEY_BYTES]; | ||
884 | int i, invalid = 1; | ||
885 | const char *path; | ||
886 | long int lnum = 0; | ||
887 | |||
888 | if (!have_identity) | ||
889 | ask_filename(pw, "Enter file in which the key is"); | ||
890 | path = identity_file; | ||
891 | |||
892 | if (strcmp(identity_file, "-") == 0) { | ||
893 | f = stdin; | ||
894 | path = "(stdin)"; | ||
895 | } else if ((f = fopen(path, "r")) == NULL) | ||
896 | fatal("%s: %s: %s", __progname, path, strerror(errno)); | ||
897 | |||
898 | while (read_keyfile_line(f, path, line, sizeof(line), &lnum) == 0) { | ||
899 | cp = line; | ||
900 | cp[strcspn(cp, "\n")] = '\0'; | ||
901 | /* Trim leading space and comments */ | ||
902 | cp = line + strspn(line, " \t"); | ||
903 | if (*cp == '#' || *cp == '\0') | ||
860 | continue; | 904 | continue; |
905 | |||
906 | /* | ||
907 | * Input may be plain keys, private keys, authorized_keys | ||
908 | * or known_hosts. | ||
909 | */ | ||
910 | |||
911 | /* | ||
912 | * Try private keys first. Assume a key is private if | ||
913 | * "SSH PRIVATE KEY" appears on the first line and we're | ||
914 | * not reading from stdin (XXX support private keys on stdin). | ||
915 | */ | ||
916 | if (lnum == 1 && strcmp(identity_file, "-") != 0 && | ||
917 | strstr(cp, "PRIVATE KEY") != NULL) { | ||
918 | fclose(f); | ||
919 | fingerprint_private(path); | ||
920 | exit(0); | ||
861 | } | 921 | } |
862 | num++; | 922 | |
863 | if (skip) { | 923 | /* |
864 | skip = 0; | 924 | * If it's not a private key, then this must be prepared to |
925 | * accept a public key prefixed with a hostname or options. | ||
926 | * Try a bare key first, otherwise skip the leading stuff. | ||
927 | */ | ||
928 | if ((public = try_read_key(&cp)) == NULL) { | ||
929 | i = strtol(cp, &ep, 10); | ||
930 | if (i == 0 || ep == NULL || | ||
931 | (*ep != ' ' && *ep != '\t')) { | ||
932 | int quoted = 0; | ||
933 | |||
934 | comment = cp; | ||
935 | for (; *cp && (quoted || (*cp != ' ' && | ||
936 | *cp != '\t')); cp++) { | ||
937 | if (*cp == '\\' && cp[1] == '"') | ||
938 | cp++; /* Skip both */ | ||
939 | else if (*cp == '"') | ||
940 | quoted = !quoted; | ||
941 | } | ||
942 | if (!*cp) | ||
943 | continue; | ||
944 | *cp++ = '\0'; | ||
945 | } | ||
946 | } | ||
947 | /* Retry after parsing leading hostname/key options */ | ||
948 | if (public == NULL && (public = try_read_key(&cp)) == NULL) { | ||
949 | debug("%s:%ld: not a public key", path, lnum); | ||
865 | continue; | 950 | continue; |
866 | } | 951 | } |
867 | *cp = '\0'; | ||
868 | 952 | ||
869 | /* Skip leading whitespace, empty and comment lines. */ | 953 | /* Find trailing comment, if any */ |
870 | for (cp = line; *cp == ' ' || *cp == '\t'; cp++) | 954 | for (; *cp == ' ' || *cp == '\t'; cp++) |
871 | ; | 955 | ; |
872 | if (!*cp || *cp == '\n' || *cp == '#') | 956 | if (*cp != '\0' && *cp != '#') |
873 | continue; | ||
874 | i = strtol(cp, &ep, 10); | ||
875 | if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) { | ||
876 | int quoted = 0; | ||
877 | comment = cp; | 957 | comment = cp; |
878 | for (; *cp && (quoted || (*cp != ' ' && | 958 | |
879 | *cp != '\t')); cp++) { | 959 | fingerprint_one_key(public, comment); |
880 | if (*cp == '\\' && cp[1] == '"') | ||
881 | cp++; /* Skip both */ | ||
882 | else if (*cp == '"') | ||
883 | quoted = !quoted; | ||
884 | } | ||
885 | if (!*cp) | ||
886 | continue; | ||
887 | *cp++ = '\0'; | ||
888 | } | ||
889 | ep = cp; | ||
890 | if ((public = sshkey_new(KEY_RSA1)) == NULL) | ||
891 | fatal("sshkey_new failed"); | ||
892 | if ((r = sshkey_read(public, &cp)) != 0) { | ||
893 | cp = ep; | ||
894 | sshkey_free(public); | ||
895 | if ((public = sshkey_new(KEY_UNSPEC)) == NULL) | ||
896 | fatal("sshkey_new failed"); | ||
897 | if ((r = sshkey_read(public, &cp)) != 0) { | ||
898 | sshkey_free(public); | ||
899 | continue; | ||
900 | } | ||
901 | } | ||
902 | comment = *cp ? cp : comment; | ||
903 | fp = sshkey_fingerprint(public, fptype, rep); | ||
904 | ra = sshkey_fingerprint(public, fingerprint_hash, | ||
905 | SSH_FP_RANDOMART); | ||
906 | if (fp == NULL || ra == NULL) | ||
907 | fatal("%s: sshkey_fingerprint fail", __func__); | ||
908 | printf("%u %s %s (%s)\n", sshkey_size(public), fp, | ||
909 | comment ? comment : "no comment", sshkey_type(public)); | ||
910 | if (log_level >= SYSLOG_LEVEL_VERBOSE) | ||
911 | printf("%s\n", ra); | ||
912 | free(ra); | ||
913 | free(fp); | ||
914 | sshkey_free(public); | 960 | sshkey_free(public); |
915 | invalid = 0; | 961 | invalid = 0; /* One good key in the file is sufficient */ |
916 | } | 962 | } |
917 | fclose(f); | 963 | fclose(f); |
918 | 964 | ||
919 | if (invalid) | 965 | if (invalid) |
920 | fatal("%s is not a public key file.", identity_file); | 966 | fatal("%s is not a public key file.", path); |
921 | exit(0); | 967 | exit(0); |
922 | } | 968 | } |
923 | 969 | ||
@@ -1185,8 +1231,11 @@ do_known_hosts(struct passwd *pw, const char *name) | |||
1185 | foreach_options |= print_fingerprint ? HKF_WANT_PARSE_KEY : 0; | 1231 | foreach_options |= print_fingerprint ? HKF_WANT_PARSE_KEY : 0; |
1186 | if ((r = hostkeys_foreach(identity_file, | 1232 | if ((r = hostkeys_foreach(identity_file, |
1187 | hash_hosts ? known_hosts_hash : known_hosts_find_delete, &ctx, | 1233 | hash_hosts ? known_hosts_hash : known_hosts_find_delete, &ctx, |
1188 | name, NULL, foreach_options)) != 0) | 1234 | name, NULL, foreach_options)) != 0) { |
1235 | if (inplace) | ||
1236 | unlink(tmp); | ||
1189 | fatal("%s: hostkeys_foreach failed: %s", __func__, ssh_err(r)); | 1237 | fatal("%s: hostkeys_foreach failed: %s", __func__, ssh_err(r)); |
1238 | } | ||
1190 | 1239 | ||
1191 | if (inplace) | 1240 | if (inplace) |
1192 | fclose(ctx.out); | 1241 | fclose(ctx.out); |
@@ -1383,9 +1432,11 @@ do_change_comment(struct passwd *pw) | |||
1383 | identity_file, ssh_err(r)); | 1432 | identity_file, ssh_err(r)); |
1384 | } | 1433 | } |
1385 | } | 1434 | } |
1386 | /* XXX what about new-format keys? */ | 1435 | |
1387 | if (private->type != KEY_RSA1) { | 1436 | if (private->type != KEY_RSA1 && private->type != KEY_ED25519 && |
1388 | error("Comments are only supported for RSA1 keys."); | 1437 | !use_new_format) { |
1438 | error("Comments are only supported for RSA1 or keys stored in " | ||
1439 | "the new format (-o)."); | ||
1389 | explicit_bzero(passphrase, strlen(passphrase)); | 1440 | explicit_bzero(passphrase, strlen(passphrase)); |
1390 | sshkey_free(private); | 1441 | sshkey_free(private); |
1391 | exit(1); | 1442 | exit(1); |
@@ -1441,44 +1492,6 @@ do_change_comment(struct passwd *pw) | |||
1441 | exit(0); | 1492 | exit(0); |
1442 | } | 1493 | } |
1443 | 1494 | ||
1444 | static const char * | ||
1445 | fmt_validity(u_int64_t valid_from, u_int64_t valid_to) | ||
1446 | { | ||
1447 | char from[32], to[32]; | ||
1448 | static char ret[64]; | ||
1449 | time_t tt; | ||
1450 | struct tm *tm; | ||
1451 | |||
1452 | *from = *to = '\0'; | ||
1453 | if (valid_from == 0 && valid_to == 0xffffffffffffffffULL) | ||
1454 | return "forever"; | ||
1455 | |||
1456 | if (valid_from != 0) { | ||
1457 | /* XXX revisit INT_MAX in 2038 :) */ | ||
1458 | tt = valid_from > INT_MAX ? INT_MAX : valid_from; | ||
1459 | tm = localtime(&tt); | ||
1460 | strftime(from, sizeof(from), "%Y-%m-%dT%H:%M:%S", tm); | ||
1461 | } | ||
1462 | if (valid_to != 0xffffffffffffffffULL) { | ||
1463 | /* XXX revisit INT_MAX in 2038 :) */ | ||
1464 | tt = valid_to > INT_MAX ? INT_MAX : valid_to; | ||
1465 | tm = localtime(&tt); | ||
1466 | strftime(to, sizeof(to), "%Y-%m-%dT%H:%M:%S", tm); | ||
1467 | } | ||
1468 | |||
1469 | if (valid_from == 0) { | ||
1470 | snprintf(ret, sizeof(ret), "before %s", to); | ||
1471 | return ret; | ||
1472 | } | ||
1473 | if (valid_to == 0xffffffffffffffffULL) { | ||
1474 | snprintf(ret, sizeof(ret), "after %s", from); | ||
1475 | return ret; | ||
1476 | } | ||
1477 | |||
1478 | snprintf(ret, sizeof(ret), "from %s to %s", from, to); | ||
1479 | return ret; | ||
1480 | } | ||
1481 | |||
1482 | static void | 1495 | static void |
1483 | add_flag_option(struct sshbuf *c, const char *name) | 1496 | add_flag_option(struct sshbuf *c, const char *name) |
1484 | { | 1497 | { |
@@ -1572,7 +1585,7 @@ do_ca_sign(struct passwd *pw, int argc, char **argv) | |||
1572 | int r, i, fd; | 1585 | int r, i, fd; |
1573 | u_int n; | 1586 | u_int n; |
1574 | struct sshkey *ca, *public; | 1587 | struct sshkey *ca, *public; |
1575 | char *otmp, *tmp, *cp, *out, *comment, **plist = NULL; | 1588 | char valid[64], *otmp, *tmp, *cp, *out, *comment, **plist = NULL; |
1576 | FILE *f; | 1589 | FILE *f; |
1577 | 1590 | ||
1578 | #ifdef ENABLE_PKCS11 | 1591 | #ifdef ENABLE_PKCS11 |
@@ -1647,13 +1660,15 @@ do_ca_sign(struct passwd *pw, int argc, char **argv) | |||
1647 | fclose(f); | 1660 | fclose(f); |
1648 | 1661 | ||
1649 | if (!quiet) { | 1662 | if (!quiet) { |
1663 | sshkey_format_cert_validity(public->cert, | ||
1664 | valid, sizeof(valid)); | ||
1650 | logit("Signed %s key %s: id \"%s\" serial %llu%s%s " | 1665 | logit("Signed %s key %s: id \"%s\" serial %llu%s%s " |
1651 | "valid %s", sshkey_cert_type(public), | 1666 | "valid %s", sshkey_cert_type(public), |
1652 | out, public->cert->key_id, | 1667 | out, public->cert->key_id, |
1653 | (unsigned long long)public->cert->serial, | 1668 | (unsigned long long)public->cert->serial, |
1654 | cert_principals != NULL ? " for " : "", | 1669 | cert_principals != NULL ? " for " : "", |
1655 | cert_principals != NULL ? cert_principals : "", | 1670 | cert_principals != NULL ? cert_principals : "", |
1656 | fmt_validity(cert_valid_from, cert_valid_to)); | 1671 | valid); |
1657 | } | 1672 | } |
1658 | 1673 | ||
1659 | sshkey_free(public); | 1674 | sshkey_free(public); |
@@ -1687,7 +1702,7 @@ parse_absolute_time(const char *s) | |||
1687 | char buf[32], *fmt; | 1702 | char buf[32], *fmt; |
1688 | 1703 | ||
1689 | /* | 1704 | /* |
1690 | * POSIX strptime says "The application shall ensure that there | 1705 | * POSIX strptime says "The application shall ensure that there |
1691 | * is white-space or other non-alphanumeric characters between | 1706 | * is white-space or other non-alphanumeric characters between |
1692 | * any two conversion specifications" so arrange things this way. | 1707 | * any two conversion specifications" so arrange things this way. |
1693 | */ | 1708 | */ |
@@ -1851,31 +1866,18 @@ show_options(struct sshbuf *optbuf, int in_critical) | |||
1851 | } | 1866 | } |
1852 | 1867 | ||
1853 | static void | 1868 | static void |
1854 | do_show_cert(struct passwd *pw) | 1869 | print_cert(struct sshkey *key) |
1855 | { | 1870 | { |
1856 | struct sshkey *key; | 1871 | char valid[64], *key_fp, *ca_fp; |
1857 | struct stat st; | ||
1858 | char *key_fp, *ca_fp; | ||
1859 | u_int i; | 1872 | u_int i; |
1860 | int r; | ||
1861 | |||
1862 | if (!have_identity) | ||
1863 | ask_filename(pw, "Enter file in which the key is"); | ||
1864 | if (stat(identity_file, &st) < 0) | ||
1865 | fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); | ||
1866 | if ((r = sshkey_load_public(identity_file, &key, NULL)) != 0) | ||
1867 | fatal("Cannot load public key \"%s\": %s", | ||
1868 | identity_file, ssh_err(r)); | ||
1869 | if (!sshkey_is_cert(key)) | ||
1870 | fatal("%s is not a certificate", identity_file); | ||
1871 | 1873 | ||
1872 | key_fp = sshkey_fingerprint(key, fingerprint_hash, SSH_FP_DEFAULT); | 1874 | key_fp = sshkey_fingerprint(key, fingerprint_hash, SSH_FP_DEFAULT); |
1873 | ca_fp = sshkey_fingerprint(key->cert->signature_key, | 1875 | ca_fp = sshkey_fingerprint(key->cert->signature_key, |
1874 | fingerprint_hash, SSH_FP_DEFAULT); | 1876 | fingerprint_hash, SSH_FP_DEFAULT); |
1875 | if (key_fp == NULL || ca_fp == NULL) | 1877 | if (key_fp == NULL || ca_fp == NULL) |
1876 | fatal("%s: sshkey_fingerprint fail", __func__); | 1878 | fatal("%s: sshkey_fingerprint fail", __func__); |
1879 | sshkey_format_cert_validity(key->cert, valid, sizeof(valid)); | ||
1877 | 1880 | ||
1878 | printf("%s:\n", identity_file); | ||
1879 | printf(" Type: %s %s certificate\n", sshkey_ssh_name(key), | 1881 | printf(" Type: %s %s certificate\n", sshkey_ssh_name(key), |
1880 | sshkey_cert_type(key)); | 1882 | sshkey_cert_type(key)); |
1881 | printf(" Public key: %s %s\n", sshkey_type(key), key_fp); | 1883 | printf(" Public key: %s %s\n", sshkey_type(key), key_fp); |
@@ -1883,8 +1885,7 @@ do_show_cert(struct passwd *pw) | |||
1883 | sshkey_type(key->cert->signature_key), ca_fp); | 1885 | sshkey_type(key->cert->signature_key), ca_fp); |
1884 | printf(" Key ID: \"%s\"\n", key->cert->key_id); | 1886 | printf(" Key ID: \"%s\"\n", key->cert->key_id); |
1885 | printf(" Serial: %llu\n", (unsigned long long)key->cert->serial); | 1887 | printf(" Serial: %llu\n", (unsigned long long)key->cert->serial); |
1886 | printf(" Valid: %s\n", | 1888 | printf(" Valid: %s\n", valid); |
1887 | fmt_validity(key->cert->valid_after, key->cert->valid_before)); | ||
1888 | printf(" Principals: "); | 1889 | printf(" Principals: "); |
1889 | if (key->cert->nprincipals == 0) | 1890 | if (key->cert->nprincipals == 0) |
1890 | printf("(none)\n"); | 1891 | printf("(none)\n"); |
@@ -1908,7 +1909,60 @@ do_show_cert(struct passwd *pw) | |||
1908 | printf("\n"); | 1909 | printf("\n"); |
1909 | show_options(key->cert->extensions, 0); | 1910 | show_options(key->cert->extensions, 0); |
1910 | } | 1911 | } |
1911 | exit(0); | 1912 | } |
1913 | |||
1914 | static void | ||
1915 | do_show_cert(struct passwd *pw) | ||
1916 | { | ||
1917 | struct sshkey *key = NULL; | ||
1918 | struct stat st; | ||
1919 | int r, is_stdin = 0, ok = 0; | ||
1920 | FILE *f; | ||
1921 | char *cp, line[SSH_MAX_PUBKEY_BYTES]; | ||
1922 | const char *path; | ||
1923 | long int lnum = 0; | ||
1924 | |||
1925 | if (!have_identity) | ||
1926 | ask_filename(pw, "Enter file in which the key is"); | ||
1927 | if (strcmp(identity_file, "-") != 0 && stat(identity_file, &st) < 0) | ||
1928 | fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); | ||
1929 | |||
1930 | path = identity_file; | ||
1931 | if (strcmp(path, "-") == 0) { | ||
1932 | f = stdin; | ||
1933 | path = "(stdin)"; | ||
1934 | is_stdin = 1; | ||
1935 | } else if ((f = fopen(identity_file, "r")) == NULL) | ||
1936 | fatal("fopen %s: %s", identity_file, strerror(errno)); | ||
1937 | |||
1938 | while (read_keyfile_line(f, path, line, sizeof(line), &lnum) == 0) { | ||
1939 | sshkey_free(key); | ||
1940 | key = NULL; | ||
1941 | /* Trim leading space and comments */ | ||
1942 | cp = line + strspn(line, " \t"); | ||
1943 | if (*cp == '#' || *cp == '\0') | ||
1944 | continue; | ||
1945 | if ((key = sshkey_new(KEY_UNSPEC)) == NULL) | ||
1946 | fatal("key_new"); | ||
1947 | if ((r = sshkey_read(key, &cp)) != 0) { | ||
1948 | error("%s:%lu: invalid key: %s", path, | ||
1949 | lnum, ssh_err(r)); | ||
1950 | continue; | ||
1951 | } | ||
1952 | if (!sshkey_is_cert(key)) { | ||
1953 | error("%s:%lu is not a certificate", path, lnum); | ||
1954 | continue; | ||
1955 | } | ||
1956 | ok = 1; | ||
1957 | if (!is_stdin && lnum == 1) | ||
1958 | printf("%s:\n", path); | ||
1959 | else | ||
1960 | printf("%s:%lu:\n", path, lnum); | ||
1961 | print_cert(key); | ||
1962 | } | ||
1963 | sshkey_free(key); | ||
1964 | fclose(f); | ||
1965 | exit(ok ? 0 : 1); | ||
1912 | } | 1966 | } |
1913 | 1967 | ||
1914 | static void | 1968 | static void |
@@ -2112,8 +2166,7 @@ do_gen_krl(struct passwd *pw, int updating, int argc, char **argv) | |||
2112 | close(fd); | 2166 | close(fd); |
2113 | sshbuf_free(kbuf); | 2167 | sshbuf_free(kbuf); |
2114 | ssh_krl_free(krl); | 2168 | ssh_krl_free(krl); |
2115 | if (ca != NULL) | 2169 | sshkey_free(ca); |
2116 | sshkey_free(ca); | ||
2117 | } | 2170 | } |
2118 | 2171 | ||
2119 | static void | 2172 | static void |
@@ -2208,6 +2261,7 @@ main(int argc, char **argv) | |||
2208 | extern int optind; | 2261 | extern int optind; |
2209 | extern char *optarg; | 2262 | extern char *optarg; |
2210 | 2263 | ||
2264 | ssh_malloc_init(); /* must be called before any mallocs */ | ||
2211 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ | 2265 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ |
2212 | sanitise_stdfd(); | 2266 | sanitise_stdfd(); |
2213 | 2267 | ||