- djm@cvs.openbsd.org 2010/03/04 20:35:08
[ssh-keygen.1 ssh-keygen.c]
Add a -L flag to print the contents of a certificate; ok markus@
diff --git a/ssh-keygen.c b/ssh-keygen.c
index c2120bb..492c301 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keygen.c,v 1.181 2010/03/04 10:36:03 djm Exp $ */
+/* $OpenBSD: ssh-keygen.c,v 1.182 2010/03/04 20:35:08 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -82,6 +82,9 @@
/* 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;
@@ -1063,7 +1066,7 @@
}
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];
@@ -1071,28 +1074,27 @@
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;
}
@@ -1216,7 +1218,7 @@
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);
@@ -1366,6 +1368,89 @@
}
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);
@@ -1387,6 +1472,7 @@
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");
@@ -1453,7 +1539,7 @@
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':
@@ -1476,6 +1562,9 @@
delete_host = 1;
rr_hostname = optarg;
break;
+ case 'L':
+ show_cert = 1;
+ break;
case 'l':
print_fingerprint = 1;
break;
@@ -1629,6 +1718,8 @@
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)