Viewing cetificate details
Damien Miller
djm at mindrot.org
Thu Mar 4 13:08:58 EST 2010
On Wed, 3 Mar 2010, Iain Morgan wrote:
> Hi,
>
> I don't see any way to view the details of a certificate once it is
> generated. Having such a capability would be very handy for debugging
> purposes to check what constraints, principals, and validity interval
> are associated with a given cert.
Yes, I had been meaning to add that - thanks for reminding me. This
diff adds "ssh-keygen -L" to print certificate details.
Index: ssh-keygen.1
===================================================================
RCS file: /cvs/src/usr.bin/ssh/ssh-keygen.1,v
retrieving revision 1.85
diff -u -p -r1.85 ssh-keygen.1
--- ssh-keygen.1 26 Feb 2010 22:09:28 -0000 1.85
+++ ssh-keygen.1 4 Mar 2010 02:07:48 -0000
@@ -115,6 +115,10 @@
.Op Fl O Ar constraint
.Op Fl V Ar validity_interval
.Ar
+.Nm ssh-keygen
+.Bk -words
+.Fl L
+.Op Fl f Ar input_keyfile
.Ek
.Sh DESCRIPTION
.Nm
@@ -275,6 +279,8 @@ also reads the
RFC 4716 SSH Public Key File Format.
This option allows importing keys from several commercial
SSH implementations.
+.It Fl L
+Prints the contents of a certificate.
.It Fl l
Show fingerprint of specified public key file.
Private RSA1 keys are also supported.
Index: ssh-keygen.c
===================================================================
RCS file: /cvs/src/usr.bin/ssh/ssh-keygen.c,v
retrieving revision 1.180
diff -u -p -r1.180 ssh-keygen.c
--- ssh-keygen.c 2 Mar 2010 23:20:57 -0000 1.180
+++ ssh-keygen.c 4 Mar 2010 02:07:49 -0000
@@ -74,6 +74,9 @@ int find_host = 0;
/* Flag indicating that we want to delete a host from a known_hosts file */
int delete_host = 0;
+/* Flag indicating that we want to show the contents of a certificate */
+int show_cert = 0;
+
/* Flag indicating that we just want to see the key fingerprint */
int print_fingerprint = 0;
int print_bubblebabble = 0;
@@ -1055,7 +1058,7 @@ do_change_comment(struct passwd *pw)
}
static const char *
-fmt_validity(void)
+fmt_validity(u_int64_t valid_from, u_int64_t valid_to)
{
char from[32], to[32];
static char ret[64];
@@ -1063,28 +1066,27 @@ fmt_validity(void)
struct tm *tm;
*from = *to = '\0';
- if (cert_valid_from == 0 &&
- cert_valid_to == 0xffffffffffffffffULL)
+ if (valid_from == 0 && valid_to == 0xffffffffffffffffULL)
return "forever";
- if (cert_valid_from != 0) {
+ if (valid_from != 0) {
/* XXX revisit INT_MAX in 2038 :) */
- tt = cert_valid_from > INT_MAX ? INT_MAX : cert_valid_from;
+ tt = valid_from > INT_MAX ? INT_MAX : valid_from;
tm = localtime(&tt);
strftime(from, sizeof(from), "%Y-%m-%dT%H:%M:%S", tm);
}
- if (cert_valid_to != 0xffffffffffffffffULL) {
+ if (valid_to != 0xffffffffffffffffULL) {
/* XXX revisit INT_MAX in 2038 :) */
- tt = cert_valid_to > INT_MAX ? INT_MAX : cert_valid_to;
+ tt = valid_to > INT_MAX ? INT_MAX : valid_to;
tm = localtime(&tt);
strftime(to, sizeof(to), "%Y-%m-%dT%H:%M:%S", tm);
}
- if (cert_valid_from == 0) {
+ if (valid_from == 0) {
snprintf(ret, sizeof(ret), "before %s", to);
return ret;
}
- if (cert_valid_to == 0xffffffffffffffffULL) {
+ if (valid_to == 0xffffffffffffffffULL) {
snprintf(ret, sizeof(ret), "after %s", from);
return ret;
}
@@ -1208,7 +1210,7 @@ do_ca_sign(struct passwd *pw, int argc,
out, cert_key_id,
cert_principals != NULL ? " for " : "",
cert_principals != NULL ? cert_principals : "",
- fmt_validity());
+ fmt_validity(cert_valid_from, cert_valid_to));
key_free(public);
xfree(out);
@@ -1358,6 +1360,89 @@ add_cert_constraint(char *opt)
}
static void
+do_show_cert(struct passwd *pw)
+{
+ Key *key;
+ struct stat st;
+ char *key_fp, *ca_fp;
+ Buffer constraints, constraint;
+ u_char *name, *data;
+ u_int i, dlen;
+
+ if (!have_identity)
+ ask_filename(pw, "Enter file in which the key is");
+ if (stat(identity_file, &st) < 0) {
+ perror(identity_file);
+ exit(1);
+ }
+ if ((key = key_load_public(identity_file, NULL)) == NULL)
+ fatal("%s is not a public key", identity_file);
+ if (!key_is_cert(key))
+ fatal("%s is not a certificate", identity_file);
+
+ key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ ca_fp = key_fingerprint(key->cert->signature_key,
+ SSH_FP_MD5, SSH_FP_HEX);
+
+ printf("%s:\n", identity_file);
+ printf(" %s certificate %s\n", key_type(key), key_fp);
+ printf(" Signed by %s CA %s\n",
+ key_type(key->cert->signature_key), ca_fp);
+ printf(" Key ID \"%s\"\n", key->cert->key_id);
+ printf(" Valid: %s\n",
+ fmt_validity(key->cert->valid_after, key->cert->valid_before));
+ printf(" Principals: ");
+ if (key->cert->nprincipals == 0)
+ printf("(none)\n");
+ else {
+ for (i = 0; i < key->cert->nprincipals; i++)
+ printf("\n %s",
+ key->cert->principals[i]);
+ printf("\n");
+ }
+ printf(" Constraints: ");
+ if (buffer_len(&key->cert->constraints) == 0)
+ printf("(none)\n");
+ else {
+ printf("\n");
+ buffer_init(&constraints);
+ buffer_append(&constraints,
+ buffer_ptr(&key->cert->constraints),
+ buffer_len(&key->cert->constraints));
+ buffer_init(&constraint);
+ while (buffer_len(&constraints) != 0) {
+ name = buffer_get_string(&constraints, NULL);
+ data = buffer_get_string_ptr(&constraints, &dlen);
+ buffer_append(&constraint, data, dlen);
+ printf(" %s", name);
+ if (strcmp(name, "permit-X11-forwarding") == 0 ||
+ strcmp(name, "permit-agent-forwarding") == 0 ||
+ strcmp(name, "permit-port-forwarding") == 0 ||
+ strcmp(name, "permit-pty") == 0 ||
+ strcmp(name, "permit-user-rc") == 0)
+ printf("\n");
+ else if (strcmp(name, "force-command") == 0 ||
+ strcmp(name, "source-address") == 0) {
+ data = buffer_get_string(&constraint, NULL);
+ printf(" %s\n", data);
+ xfree(data);
+ } else {
+ printf(" UNKNOWN CONSTRAINT (len %u)\n",
+ buffer_len(&constraint));
+ buffer_clear(&constraint);
+ }
+ xfree(name);
+ if (buffer_len(&constraint) != 0)
+ fatal("Constraint corrupt: extra data at end");
+ }
+ buffer_free(&constraint);
+ buffer_free(&constraints);
+ }
+
+ exit(0);
+}
+
+static void
usage(void)
{
fprintf(stderr, "usage: %s [options]\n", __progname);
@@ -1379,6 +1464,7 @@ usage(void)
fprintf(stderr, " -h Generate host certificate instead of a user certificate.\n");
fprintf(stderr, " -I key_id Key identifier to include in certificate.\n");
fprintf(stderr, " -i Convert RFC 4716 to OpenSSH key file.\n");
+ fprintf(stderr, " -L Print the contents of a certificate.\n");
fprintf(stderr, " -l Show fingerprint of key file.\n");
fprintf(stderr, " -M memory Amount of memory (MB) to use for generating DH-GEX moduli.\n");
fprintf(stderr, " -n name,... User/host principal names to include in certificate\n");
@@ -1440,7 +1526,7 @@ main(int argc, char **argv)
exit(1);
}
- while ((opt = getopt(argc, argv, "degiqpclBHhvxXyF:b:f:t:D:I:P:N:n:"
+ while ((opt = getopt(argc, argv, "degiqpclBHLhvxXyF:b:f:t:D:I:P:N:n:"
"O:C:r:g:R:T:G:M:S:s:a:V:W:")) != -1) {
switch (opt) {
case 'b':
@@ -1463,6 +1549,9 @@ main(int argc, char **argv)
delete_host = 1;
rr_hostname = optarg;
break;
+ case 'L':
+ show_cert = 1;
+ break;
case 'l':
print_fingerprint = 1;
break;
@@ -1616,6 +1705,8 @@ main(int argc, char **argv)
fatal("Must specify key id (-I) when certifying");
do_ca_sign(pw, argc, argv);
}
+ if (show_cert)
+ do_show_cert(pw);
if (delete_host || hash_hosts || find_host)
do_known_hosts(pw, rr_hostname);
if (print_fingerprint || print_bubblebabble)
More information about the openssh-unix-dev
mailing list