=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/ssh-keygen.c,v retrieving revision 1.189 retrieving revision 1.197 diff -u -r1.189 -r1.197 --- src/usr.bin/ssh/ssh-keygen.c 2010/04/23 22:48:31 1.189 +++ src/usr.bin/ssh/ssh-keygen.c 2010/08/04 06:07:11 1.197 @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keygen.c,v 1.189 2010/04/23 22:48:31 djm Exp $ */ +/* $OpenBSD: ssh-keygen.c,v 1.197 2010/08/04 06:07:11 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland @@ -114,26 +114,33 @@ u_int64_t cert_valid_to = ~0ULL; /* Certificate options */ -#define CRITOPT_X_FWD (1) -#define CRITOPT_AGENT_FWD (1<<1) -#define CRITOPT_PORT_FWD (1<<2) -#define CRITOPT_PTY (1<<3) -#define CRITOPT_USER_RC (1<<4) -#define CRITOPT_DEFAULT (CRITOPT_X_FWD|CRITOPT_AGENT_FWD| \ - CRITOPT_PORT_FWD|CRITOPT_PTY| \ - CRITOPT_USER_RC) -u_int32_t critical_flags = CRITOPT_DEFAULT; -char *critical_command = NULL; -char *critical_src_addr = NULL; +#define CERTOPT_X_FWD (1) +#define CERTOPT_AGENT_FWD (1<<1) +#define CERTOPT_PORT_FWD (1<<2) +#define CERTOPT_PTY (1<<3) +#define CERTOPT_USER_RC (1<<4) +#define CERTOPT_DEFAULT (CERTOPT_X_FWD|CERTOPT_AGENT_FWD| \ + CERTOPT_PORT_FWD|CERTOPT_PTY|CERTOPT_USER_RC) +u_int32_t certflags_flags = CERTOPT_DEFAULT; +char *certflags_command = NULL; +char *certflags_src_addr = NULL; -/* Dump public key file in format used by real and the original SSH 2 */ -int convert_to_ssh2 = 0; -int convert_from_ssh2 = 0; +/* Conversion to/from various formats */ +int convert_to = 0; +int convert_from = 0; +enum { + FMT_RFC4716, + FMT_PKCS8, + FMT_PEM +} convert_format = FMT_RFC4716; int print_public = 0; int print_generic = 0; char *key_type_name = NULL; +/* Load key from this PKCS#11 provider */ +char *pkcs11provider = NULL; + /* argv0 */ extern char *__progname; @@ -208,30 +215,12 @@ #define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb static void -do_convert_to_ssh2(struct passwd *pw) +do_convert_to_ssh2(struct passwd *pw, Key *k) { - Key *k; u_int len; u_char *blob; char comment[61]; - struct stat st; - 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 ((k = key_load_public(identity_file, NULL)) == NULL) { - if ((k = load_identity(identity_file)) == NULL) { - fprintf(stderr, "load failed\n"); - exit(1); - } - } - if (k->type == KEY_RSA1) { - fprintf(stderr, "version 1 keys are not supported\n"); - exit(1); - } if (key_to_blob(k, &blob, &len) <= 0) { fprintf(stderr, "key_to_blob failed\n"); exit(1); @@ -252,6 +241,81 @@ } static void +do_convert_to_pkcs8(Key *k) +{ + switch (key_type_plain(k->type)) { + case KEY_RSA: + if (!PEM_write_RSA_PUBKEY(stdout, k->rsa)) + fatal("PEM_write_RSA_PUBKEY failed"); + break; + case KEY_DSA: + if (!PEM_write_DSA_PUBKEY(stdout, k->dsa)) + fatal("PEM_write_DSA_PUBKEY failed"); + break; + default: + fatal("%s: unsupported key type %s", __func__, key_type(k)); + } + exit(0); +} + +static void +do_convert_to_pem(Key *k) +{ + switch (key_type_plain(k->type)) { + case KEY_RSA: + if (!PEM_write_RSAPublicKey(stdout, k->rsa)) + fatal("PEM_write_RSAPublicKey failed"); + break; +#if notyet /* OpenSSH 0.9.8 lacks this function */ + case KEY_DSA: + if (!PEM_write_DSAPublicKey(stdout, k->dsa)) + fatal("PEM_write_DSAPublicKey failed"); + break; +#endif + default: + fatal("%s: unsupported key type %s", __func__, key_type(k)); + } + exit(0); +} + +static void +do_convert_to(struct passwd *pw) +{ + Key *k; + struct stat st; + + if (!have_identity) + ask_filename(pw, "Enter file in which the key is"); + if (stat(identity_file, &st) < 0) + fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); + if ((k = key_load_public(identity_file, NULL)) == NULL) { + if ((k = load_identity(identity_file)) == NULL) { + fprintf(stderr, "load failed\n"); + exit(1); + } + } + if (k->type == KEY_RSA1) { + fprintf(stderr, "version 1 keys are not supported\n"); + exit(1); + } + + switch (convert_format) { + case FMT_RFC4716: + do_convert_to_ssh2(pw, k); + break; + case FMT_PKCS8: + do_convert_to_pkcs8(k); + break; + case FMT_PEM: + do_convert_to_pem(k); + break; + default: + fatal("%s: unknown key format %d", __func__, convert_format); + } + exit(0); +} + +static void buffer_get_bignum_bits(Buffer *b, BIGNUM *value) { u_int bignum_bits = buffer_get_int(b); @@ -389,29 +453,18 @@ } static void -do_convert_from_ssh2(struct passwd *pw) +do_convert_from_ssh2(struct passwd *pw, Key **k, int *private) { - Key *k; int blen; u_int len; char line[1024]; u_char blob[8096]; char encoded[8096]; - struct stat st; - int escaped = 0, private = 0, ok; + int escaped = 0; FILE *fp; - if (!have_identity) - ask_filename(pw, "Enter file in which the key is"); - if (stat(identity_file, &st) < 0) { - perror(identity_file); - exit(1); - } - fp = fopen(identity_file, "r"); - if (fp == NULL) { - perror(identity_file); - exit(1); - } + if ((fp = fopen(identity_file, "r")) == NULL) + fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); encoded[0] = '\0'; while ((blen = get_line(fp, line, sizeof(line))) != -1) { if (line[blen - 1] == '\\') @@ -419,7 +472,7 @@ if (strncmp(line, "----", 4) == 0 || strstr(line, ": ") != NULL) { if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL) - private = 1; + *private = 1; if (strstr(line, " END ") != NULL) { break; } @@ -444,26 +497,130 @@ fprintf(stderr, "uudecode failed.\n"); exit(1); } - k = private ? + *k = *private ? do_convert_private_ssh2_from_blob(blob, blen) : key_from_blob(blob, blen); - if (k == NULL) { + if (*k == NULL) { fprintf(stderr, "decode blob failed.\n"); exit(1); } - ok = private ? - (k->type == KEY_DSA ? - PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, NULL, 0, NULL, NULL) : - PEM_write_RSAPrivateKey(stdout, k->rsa, NULL, NULL, 0, NULL, NULL)) : - key_write(k, stdout); + fclose(fp); +} + +static void +do_convert_from_pkcs8(Key **k, int *private) +{ + EVP_PKEY *pubkey; + FILE *fp; + + if ((fp = fopen(identity_file, "r")) == NULL) + fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); + if ((pubkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) { + fatal("%s: %s is not a recognised public key format", __func__, + identity_file); + } + fclose(fp); + switch (EVP_PKEY_type(pubkey->type)) { + case EVP_PKEY_RSA: + *k = key_new(KEY_UNSPEC); + (*k)->type = KEY_RSA; + (*k)->rsa = EVP_PKEY_get1_RSA(pubkey); + break; + case EVP_PKEY_DSA: + *k = key_new(KEY_UNSPEC); + (*k)->type = KEY_DSA; + (*k)->dsa = EVP_PKEY_get1_DSA(pubkey); + break; + default: + fatal("%s: unsupported pubkey type %d", __func__, + EVP_PKEY_type(pubkey->type)); + } + EVP_PKEY_free(pubkey); + return; +} + +static void +do_convert_from_pem(Key **k, int *private) +{ + FILE *fp; + RSA *rsa; +#ifdef notyet + DSA *dsa; +#endif + + if ((fp = fopen(identity_file, "r")) == NULL) + fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); + if ((rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL)) != NULL) { + *k = key_new(KEY_UNSPEC); + (*k)->type = KEY_RSA; + (*k)->rsa = rsa; + fclose(fp); + return; + } +#if notyet /* OpenSSH 0.9.8 lacks this function */ + rewind(fp); + if ((dsa = PEM_read_DSAPublicKey(fp, NULL, NULL, NULL)) != NULL) { + *k = key_new(KEY_UNSPEC); + (*k)->type = KEY_DSA; + (*k)->dsa = dsa; + fclose(fp); + return; + } +#endif + fatal("%s: unrecognised raw private key format", __func__); +} + +static void +do_convert_from(struct passwd *pw) +{ + Key *k = NULL; + int private = 0, ok = 0; + struct stat st; + + if (!have_identity) + ask_filename(pw, "Enter file in which the key is"); + if (stat(identity_file, &st) < 0) + fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); + + switch (convert_format) { + case FMT_RFC4716: + do_convert_from_ssh2(pw, &k, &private); + break; + case FMT_PKCS8: + do_convert_from_pkcs8(&k, &private); + break; + case FMT_PEM: + do_convert_from_pem(&k, &private); + break; + default: + fatal("%s: unknown key format %d", __func__, convert_format); + } + + if (!private) + ok = key_write(k, stdout); + if (ok) + fprintf(stdout, "\n"); + else { + switch (k->type) { + case KEY_DSA: + ok = PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, + NULL, 0, NULL, NULL); + break; + case KEY_RSA: + ok = PEM_write_RSAPrivateKey(stdout, k->rsa, NULL, + NULL, 0, NULL, NULL); + break; + default: + fatal("%s: unsupported key type %s", __func__, + key_type(k)); + } + } + if (!ok) { fprintf(stderr, "key write failed\n"); exit(1); } key_free(k); - if (!private) - fprintf(stdout, "\n"); - fclose(fp); exit(0); } @@ -492,7 +649,7 @@ } static void -do_download(struct passwd *pw, char *pkcs11provider) +do_download(struct passwd *pw) { #ifdef ENABLE_PKCS11 Key **keys = NULL; @@ -554,67 +711,68 @@ comment = NULL; } - f = fopen(identity_file, "r"); - if (f != NULL) { - while (fgets(line, sizeof(line), f)) { - if ((cp = strchr(line, '\n')) == NULL) { - error("line %d too long: %.40s...", - num + 1, line); - skip = 1; - continue; - } - num++; - if (skip) { - skip = 0; - continue; - } - *cp = '\0'; + if ((f = fopen(identity_file, "r")) == NULL) + fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); - /* Skip leading whitespace, empty and comment lines. */ - for (cp = line; *cp == ' ' || *cp == '\t'; cp++) - ; - if (!*cp || *cp == '\n' || *cp == '#') - continue; - i = strtol(cp, &ep, 10); - if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) { - int quoted = 0; - comment = cp; - for (; *cp && (quoted || (*cp != ' ' && - *cp != '\t')); cp++) { - if (*cp == '\\' && cp[1] == '"') - cp++; /* Skip both */ - else if (*cp == '"') - quoted = !quoted; - } - if (!*cp) - continue; - *cp++ = '\0'; + while (fgets(line, sizeof(line), f)) { + if ((cp = strchr(line, '\n')) == NULL) { + error("line %d too long: %.40s...", + num + 1, line); + skip = 1; + continue; + } + num++; + if (skip) { + skip = 0; + continue; + } + *cp = '\0'; + + /* Skip leading whitespace, empty and comment lines. */ + for (cp = line; *cp == ' ' || *cp == '\t'; cp++) + ; + if (!*cp || *cp == '\n' || *cp == '#') + continue; + i = strtol(cp, &ep, 10); + if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) { + int quoted = 0; + comment = cp; + for (; *cp && (quoted || (*cp != ' ' && + *cp != '\t')); cp++) { + if (*cp == '\\' && cp[1] == '"') + cp++; /* Skip both */ + else if (*cp == '"') + quoted = !quoted; } - ep = cp; - public = key_new(KEY_RSA1); + if (!*cp) + continue; + *cp++ = '\0'; + } + ep = cp; + public = key_new(KEY_RSA1); + if (key_read(public, &cp) != 1) { + cp = ep; + key_free(public); + public = key_new(KEY_UNSPEC); if (key_read(public, &cp) != 1) { - cp = ep; key_free(public); - public = key_new(KEY_UNSPEC); - if (key_read(public, &cp) != 1) { - key_free(public); - continue; - } + continue; } - comment = *cp ? cp : comment; - fp = key_fingerprint(public, fptype, rep); - ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART); - printf("%u %s %s (%s)\n", key_size(public), fp, - comment ? comment : "no comment", key_type(public)); - if (log_level >= SYSLOG_LEVEL_VERBOSE) - printf("%s\n", ra); - xfree(ra); - xfree(fp); - key_free(public); - invalid = 0; } - fclose(f); + comment = *cp ? cp : comment; + fp = key_fingerprint(public, fptype, rep); + ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART); + printf("%u %s %s (%s)\n", key_size(public), fp, + comment ? comment : "no comment", key_type(public)); + if (log_level >= SYSLOG_LEVEL_VERBOSE) + printf("%s\n", ra); + xfree(ra); + xfree(fp); + key_free(public); + invalid = 0; } + fclose(f); + if (invalid) { printf("%s is not a public key file.\n", identity_file); exit(1); @@ -669,7 +827,7 @@ have_identity = 1; } if ((in = fopen(identity_file, "r")) == NULL) - fatal("fopen: %s", strerror(errno)); + fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); /* * Find hosts goes to stdout, hash and deletions happen in-place @@ -1125,26 +1283,64 @@ buffer_free(&b); } +#define OPTIONS_CRITICAL 1 +#define OPTIONS_EXTENSIONS 2 static void -prepare_options_buf(Buffer *c) +prepare_options_buf(Buffer *c, int which) { buffer_clear(c); - if ((critical_flags & CRITOPT_X_FWD) != 0) - add_flag_option(c, "permit-X11-forwarding"); - if ((critical_flags & CRITOPT_AGENT_FWD) != 0) + if ((which & OPTIONS_CRITICAL) != 0 && + certflags_command != NULL) + add_string_option(c, "force-command", certflags_command); + if ((which & OPTIONS_EXTENSIONS) != 0 && + (certflags_flags & CERTOPT_AGENT_FWD) != 0) add_flag_option(c, "permit-agent-forwarding"); - if ((critical_flags & CRITOPT_PORT_FWD) != 0) + if ((which & OPTIONS_EXTENSIONS) != 0 && + (certflags_flags & CERTOPT_PORT_FWD) != 0) add_flag_option(c, "permit-port-forwarding"); - if ((critical_flags & CRITOPT_PTY) != 0) + if ((which & OPTIONS_EXTENSIONS) != 0 && + (certflags_flags & CERTOPT_PTY) != 0) add_flag_option(c, "permit-pty"); - if ((critical_flags & CRITOPT_USER_RC) != 0) + if ((which & OPTIONS_EXTENSIONS) != 0 && + (certflags_flags & CERTOPT_USER_RC) != 0) add_flag_option(c, "permit-user-rc"); - if (critical_command != NULL) - add_string_option(c, "force-command", critical_command); - if (critical_src_addr != NULL) - add_string_option(c, "source-address", critical_src_addr); + if ((which & OPTIONS_EXTENSIONS) != 0 && + (certflags_flags & CERTOPT_X_FWD) != 0) + add_flag_option(c, "permit-X11-forwarding"); + if ((which & OPTIONS_CRITICAL) != 0 && + certflags_src_addr != NULL) + add_string_option(c, "source-address", certflags_src_addr); } +static Key * +load_pkcs11_key(char *path) +{ +#ifdef ENABLE_PKCS11 + Key **keys = NULL, *public, *private = NULL; + int i, nkeys; + + if ((public = key_load_public(path, NULL)) == NULL) + fatal("Couldn't load CA public key \"%s\"", path); + + nkeys = pkcs11_add_provider(pkcs11provider, identity_passphrase, &keys); + debug3("%s: %d keys", __func__, nkeys); + if (nkeys <= 0) + fatal("cannot read public key from pkcs11"); + for (i = 0; i < nkeys; i++) { + if (key_equal_public(public, keys[i])) { + private = keys[i]; + continue; + } + key_free(keys[i]); + } + xfree(keys); + key_free(public); + return private; +#else + fatal("no pkcs11 support"); +#endif /* ENABLE_PKCS11 */ +} + static void do_ca_sign(struct passwd *pw, int argc, char **argv) { @@ -1155,11 +1351,6 @@ FILE *f; int v00 = 0; /* legacy keys */ - tmp = tilde_expand_filename(ca_key_path, pw->pw_uid); - if ((ca = load_identity(tmp)) == NULL) - fatal("Couldn't load CA key \"%s\"", tmp); - xfree(tmp); - if (key_type_name != NULL) { switch (key_type_from_name(key_type_name)) { case KEY_RSA_CERT_V00: @@ -1179,6 +1370,15 @@ } } + pkcs11_init(1); + tmp = tilde_expand_filename(ca_key_path, pw->pw_uid); + if (pkcs11provider != NULL) { + if ((ca = load_pkcs11_key(tmp)) == NULL) + fatal("No PKCS#11 key matching %s found", ca_key_path); + } else if ((ca = load_identity(tmp)) == NULL) + fatal("Couldn't load CA key \"%s\"", tmp); + xfree(tmp); + for (i = 0; i < argc; i++) { /* Split list of principals */ n = 0; @@ -1210,7 +1410,15 @@ public->cert->principals = plist; public->cert->valid_after = cert_valid_from; public->cert->valid_before = cert_valid_to; - prepare_options_buf(&public->cert->critical); + if (v00) { + prepare_options_buf(&public->cert->critical, + OPTIONS_CRITICAL|OPTIONS_EXTENSIONS); + } else { + prepare_options_buf(&public->cert->critical, + OPTIONS_CRITICAL); + prepare_options_buf(&public->cert->extensions, + OPTIONS_EXTENSIONS); + } public->cert->signature_key = key_from_private(ca); if (key_certify(public, ca) != 0) @@ -1243,6 +1451,7 @@ key_free(public); xfree(out); } + pkcs11_terminate(); exit(0); } @@ -1346,63 +1555,101 @@ char *val; if (strcmp(opt, "clear") == 0) - critical_flags = 0; + certflags_flags = 0; else if (strcasecmp(opt, "no-x11-forwarding") == 0) - critical_flags &= ~CRITOPT_X_FWD; + certflags_flags &= ~CERTOPT_X_FWD; else if (strcasecmp(opt, "permit-x11-forwarding") == 0) - critical_flags |= CRITOPT_X_FWD; + certflags_flags |= CERTOPT_X_FWD; else if (strcasecmp(opt, "no-agent-forwarding") == 0) - critical_flags &= ~CRITOPT_AGENT_FWD; + certflags_flags &= ~CERTOPT_AGENT_FWD; else if (strcasecmp(opt, "permit-agent-forwarding") == 0) - critical_flags |= CRITOPT_AGENT_FWD; + certflags_flags |= CERTOPT_AGENT_FWD; else if (strcasecmp(opt, "no-port-forwarding") == 0) - critical_flags &= ~CRITOPT_PORT_FWD; + certflags_flags &= ~CERTOPT_PORT_FWD; else if (strcasecmp(opt, "permit-port-forwarding") == 0) - critical_flags |= CRITOPT_PORT_FWD; + certflags_flags |= CERTOPT_PORT_FWD; else if (strcasecmp(opt, "no-pty") == 0) - critical_flags &= ~CRITOPT_PTY; + certflags_flags &= ~CERTOPT_PTY; else if (strcasecmp(opt, "permit-pty") == 0) - critical_flags |= CRITOPT_PTY; + certflags_flags |= CERTOPT_PTY; else if (strcasecmp(opt, "no-user-rc") == 0) - critical_flags &= ~CRITOPT_USER_RC; + certflags_flags &= ~CERTOPT_USER_RC; else if (strcasecmp(opt, "permit-user-rc") == 0) - critical_flags |= CRITOPT_USER_RC; + certflags_flags |= CERTOPT_USER_RC; else if (strncasecmp(opt, "force-command=", 14) == 0) { val = opt + 14; if (*val == '\0') fatal("Empty force-command option"); - if (critical_command != NULL) + if (certflags_command != NULL) fatal("force-command already specified"); - critical_command = xstrdup(val); + certflags_command = xstrdup(val); } else if (strncasecmp(opt, "source-address=", 15) == 0) { val = opt + 15; if (*val == '\0') fatal("Empty source-address option"); - if (critical_src_addr != NULL) + if (certflags_src_addr != NULL) fatal("source-address already specified"); if (addr_match_cidr_list(NULL, val) != 0) fatal("Invalid source-address list"); - critical_src_addr = xstrdup(val); + certflags_src_addr = xstrdup(val); } else fatal("Unsupported certificate option \"%s\"", opt); } static void +show_options(const Buffer *optbuf, int v00, int in_critical) +{ + u_char *name, *data; + u_int dlen; + Buffer options, option; + + buffer_init(&options); + buffer_append(&options, buffer_ptr(optbuf), buffer_len(optbuf)); + + buffer_init(&option); + while (buffer_len(&options) != 0) { + name = buffer_get_string(&options, NULL); + data = buffer_get_string_ptr(&options, &dlen); + buffer_append(&option, data, dlen); + printf(" %s", name); + if ((v00 || !in_critical) && + (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 ((v00 || in_critical) && + (strcmp(name, "force-command") == 0 || + strcmp(name, "source-address") == 0)) { + data = buffer_get_string(&option, NULL); + printf(" %s\n", data); + xfree(data); + } else { + printf(" UNKNOWN OPTION (len %u)\n", + buffer_len(&option)); + buffer_clear(&option); + } + xfree(name); + if (buffer_len(&option) != 0) + fatal("Option corrupt: extra data at end"); + } + buffer_free(&option); + buffer_free(&options); +} + +static void do_show_cert(struct passwd *pw) { Key *key; struct stat st; char *key_fp, *ca_fp; - Buffer options, option; - u_char *name, *data; - u_int i, dlen, v00; + u_int i, v00; 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 (stat(identity_file, &st) < 0) + fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); if ((key = key_load_public(identity_file, NULL)) == NULL) fatal("%s is not a public key", identity_file); if (!key_is_cert(key)) @@ -1438,38 +1685,7 @@ printf("(none)\n"); else { printf("\n"); - buffer_init(&options); - buffer_append(&options, - buffer_ptr(&key->cert->critical), - buffer_len(&key->cert->critical)); - buffer_init(&option); - while (buffer_len(&options) != 0) { - name = buffer_get_string(&options, NULL); - data = buffer_get_string_ptr(&options, &dlen); - buffer_append(&option, 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(&option, NULL); - printf(" %s\n", data); - xfree(data); - } else { - printf(" UNKNOWN OPTION (len %u)\n", - buffer_len(&option)); - buffer_clear(&option); - } - xfree(name); - if (buffer_len(&option) != 0) - fatal("Option corrupt: extra data at end"); - } - buffer_free(&option); - buffer_free(&options); + show_options(&key->cert->critical, v00, 1); } if (!v00) { printf(" Extensions: "); @@ -1477,20 +1693,7 @@ printf("(none)\n"); else { printf("\n"); - buffer_init(&options); - buffer_append(&options, - buffer_ptr(&key->cert->extensions), - buffer_len(&key->cert->extensions)); - buffer_init(&option); - while (buffer_len(&options) != 0) { - name = buffer_get_string(&options, NULL); - (void)buffer_get_string_ptr(&options, &dlen); - printf(" %s UNKNOWN OPTION " - "(len %u)\n", name, dlen); - xfree(name); - } - buffer_free(&option); - buffer_free(&options); + show_options(&key->cert->extensions, v00, 0); } } exit(0); @@ -1509,7 +1712,7 @@ #ifdef ENABLE_PKCS11 fprintf(stderr, " -D pkcs11 Download public key from pkcs11 token.\n"); #endif - fprintf(stderr, " -e Convert OpenSSH to RFC 4716 key file.\n"); + fprintf(stderr, " -e Export OpenSSH to foreign format key file.\n"); fprintf(stderr, " -F hostname Find hostname in known hosts file.\n"); fprintf(stderr, " -f filename Filename of the key file.\n"); fprintf(stderr, " -G file Generate candidates for DH-GEX moduli.\n"); @@ -1517,20 +1720,21 @@ fprintf(stderr, " -H Hash names in known_hosts file.\n"); 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, " -i Import foreign format 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"); + fprintf(stderr, " -m key_fmt Conversion format for -e/-i (PEM|PKCS8|RFC4716).\n"); fprintf(stderr, " -N phrase Provide new passphrase.\n"); + fprintf(stderr, " -n name,... User/host principal names to include in certificate\n"); fprintf(stderr, " -O option Specify a certificate option.\n"); fprintf(stderr, " -P phrase Provide old passphrase.\n"); fprintf(stderr, " -p Change passphrase of private key file.\n"); fprintf(stderr, " -q Quiet.\n"); fprintf(stderr, " -R hostname Remove host from known_hosts file.\n"); fprintf(stderr, " -r hostname Print DNS resource record.\n"); - fprintf(stderr, " -s ca_key Certify keys with CA key.\n"); fprintf(stderr, " -S start Start point (hex) for generating DH-GEX moduli.\n"); + fprintf(stderr, " -s ca_key Certify keys with CA key.\n"); fprintf(stderr, " -T file Screen candidates for DH-GEX moduli.\n"); fprintf(stderr, " -t type Specify type of key to create.\n"); fprintf(stderr, " -V from:to Specify certificate validity interval.\n"); @@ -1549,8 +1753,7 @@ main(int argc, char **argv) { char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2; - char out_file[MAXPATHLEN], *pkcs11provider = NULL; - char *rr_hostname = NULL; + char out_file[MAXPATHLEN], *rr_hostname = NULL; Key *private, *public; struct passwd *pw; struct stat st; @@ -1582,7 +1785,7 @@ exit(1); } - while ((opt = getopt(argc, argv, "degiqpclBHLhvxXyF:b:f:t:D:I:P:N:n:" + while ((opt = getopt(argc, argv, "degiqpclBHLhvxXyF:b:f:t:D:I:P:m:N:n:" "O:C:r:g:R:T:G:M:S:s:a:V:W:z:")) != -1) { switch (opt) { case 'b': @@ -1614,6 +1817,21 @@ case 'B': print_bubblebabble = 1; break; + case 'm': + if (strcasecmp(optarg, "RFC4716") == 0 || + strcasecmp(optarg, "ssh2") == 0) { + convert_format = FMT_RFC4716; + break; + } + if (strcasecmp(optarg, "PKCS8") == 0) { + convert_format = FMT_PKCS8; + break; + } + if (strcasecmp(optarg, "PEM") == 0) { + convert_format = FMT_PEM; + break; + } + fatal("Unsupported conversion format \"%s\"", optarg); case 'n': cert_principals = optarg; break; @@ -1650,16 +1868,16 @@ case 'e': case 'x': /* export key */ - convert_to_ssh2 = 1; + convert_to = 1; break; case 'h': cert_key_type = SSH2_CERT_TYPE_HOST; - critical_flags = 0; + certflags_flags = 0; break; case 'i': case 'X': /* import key */ - convert_from_ssh2 = 1; + convert_from = 1; break; case 'y': print_public = 1; @@ -1775,10 +1993,10 @@ do_change_passphrase(pw); if (change_comment) do_change_comment(pw); - if (convert_to_ssh2) - do_convert_to_ssh2(pw); - if (convert_from_ssh2) - do_convert_from_ssh2(pw); + if (convert_to) + do_convert_to(pw); + if (convert_from) + do_convert_from(pw); if (print_public) do_print_public(pw); if (rr_hostname != NULL) { @@ -1805,7 +2023,7 @@ } } if (pkcs11provider != NULL) - do_download(pw, pkcs11provider); + do_download(pw); if (do_gen_candidates) { FILE *out = fopen(out_file, "w");