version 1.247, 2014/06/24 01:13:21 |
version 1.251, 2014/12/21 22:27:56 |
|
|
|
|
#include <errno.h> |
#include <errno.h> |
#include <fcntl.h> |
#include <fcntl.h> |
|
#include <netdb.h> |
#include <pwd.h> |
#include <pwd.h> |
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
|
|
#include "ssh2.h" |
#include "ssh2.h" |
#include "atomicio.h" |
#include "atomicio.h" |
#include "krl.h" |
#include "krl.h" |
|
#include "digest.h" |
|
|
#ifdef ENABLE_PKCS11 |
#ifdef ENABLE_PKCS11 |
#include "ssh-pkcs11.h" |
#include "ssh-pkcs11.h" |
|
|
int print_fingerprint = 0; |
int print_fingerprint = 0; |
int print_bubblebabble = 0; |
int print_bubblebabble = 0; |
|
|
|
/* Hash algorithm to use for fingerprints. */ |
|
int fingerprint_hash = SSH_FP_HASH_DEFAULT; |
|
|
/* The identity file name, given on the command line or entered by the user. */ |
/* The identity file name, given on the command line or entered by the user. */ |
char identity_file[1024]; |
char identity_file[1024]; |
int have_identity = 0; |
int have_identity = 0; |
|
|
/* argv0 */ |
/* argv0 */ |
extern char *__progname; |
extern char *__progname; |
|
|
char hostname[MAXHOSTNAMELEN]; |
char hostname[NI_MAXHOST]; |
|
|
/* moduli.c */ |
/* moduli.c */ |
int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *); |
int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *); |
|
|
Key **keys = NULL; |
Key **keys = NULL; |
int i, nkeys; |
int i, nkeys; |
enum fp_rep rep; |
enum fp_rep rep; |
enum fp_type fptype; |
int fptype; |
char *fp, *ra; |
char *fp, *ra; |
|
|
fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; |
fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash; |
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; |
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT; |
|
|
pkcs11_init(0); |
pkcs11_init(0); |
nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys); |
nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys); |
|
|
for (i = 0; i < nkeys; i++) { |
for (i = 0; i < nkeys; i++) { |
if (print_fingerprint) { |
if (print_fingerprint) { |
fp = key_fingerprint(keys[i], fptype, rep); |
fp = key_fingerprint(keys[i], fptype, rep); |
ra = key_fingerprint(keys[i], SSH_FP_MD5, |
ra = key_fingerprint(keys[i], fingerprint_hash, |
SSH_FP_RANDOMART); |
SSH_FP_RANDOMART); |
printf("%u %s %s (PKCS11 key)\n", key_size(keys[i]), |
printf("%u %s %s (PKCS11 key)\n", key_size(keys[i]), |
fp, key_type(keys[i])); |
fp, key_type(keys[i])); |
|
|
char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra; |
char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra; |
int i, skip = 0, num = 0, invalid = 1; |
int i, skip = 0, num = 0, invalid = 1; |
enum fp_rep rep; |
enum fp_rep rep; |
enum fp_type fptype; |
int fptype; |
struct stat st; |
struct stat st; |
|
|
fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; |
fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash; |
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; |
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT; |
|
|
if (!have_identity) |
if (!have_identity) |
ask_filename(pw, "Enter file in which the key is"); |
ask_filename(pw, "Enter file in which the key is"); |
if (stat(identity_file, &st) < 0) { |
if (stat(identity_file, &st) < 0) { |
|
|
public = key_load_public(identity_file, &comment); |
public = key_load_public(identity_file, &comment); |
if (public != NULL) { |
if (public != NULL) { |
fp = key_fingerprint(public, fptype, rep); |
fp = key_fingerprint(public, fptype, rep); |
ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART); |
ra = key_fingerprint(public, fingerprint_hash, |
|
SSH_FP_RANDOMART); |
printf("%u %s %s (%s)\n", key_size(public), fp, comment, |
printf("%u %s %s (%s)\n", key_size(public), fp, comment, |
key_type(public)); |
key_type(public)); |
if (log_level >= SYSLOG_LEVEL_VERBOSE) |
if (log_level >= SYSLOG_LEVEL_VERBOSE) |
|
|
} |
} |
comment = *cp ? cp : comment; |
comment = *cp ? cp : comment; |
fp = key_fingerprint(public, fptype, rep); |
fp = key_fingerprint(public, fptype, rep); |
ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART); |
ra = key_fingerprint(public, fingerprint_hash, |
|
SSH_FP_RANDOMART); |
printf("%u %s %s (%s)\n", key_size(public), fp, |
printf("%u %s %s (%s)\n", key_size(public), fp, |
comment ? comment : "no comment", key_type(public)); |
comment ? comment : "no comment", key_type(public)); |
if (log_level >= SYSLOG_LEVEL_VERBOSE) |
if (log_level >= SYSLOG_LEVEL_VERBOSE) |
|
|
f = fdopen(fd, "w"); |
f = fdopen(fd, "w"); |
if (f == NULL) { |
if (f == NULL) { |
printf("fdopen %s failed\n", identity_file); |
printf("fdopen %s failed\n", identity_file); |
|
close(fd); |
key_free(public); |
key_free(public); |
first = 0; |
first = 0; |
continue; |
continue; |
} |
} |
if (!key_write(public, f)) { |
if (!key_write(public, f)) { |
fprintf(stderr, "write key failed\n"); |
fprintf(stderr, "write key failed\n"); |
|
fclose(f); |
key_free(public); |
key_free(public); |
first = 0; |
first = 0; |
continue; |
continue; |
|
|
} |
} |
|
|
static void |
static void |
printhost(FILE *f, const char *name, Key *public, int ca, int hash) |
printhost(FILE *f, const char *name, Key *public, int ca, int revoked, int hash) |
{ |
{ |
if (print_fingerprint) { |
if (print_fingerprint) { |
enum fp_rep rep; |
enum fp_rep rep; |
enum fp_type fptype; |
int fptype; |
char *fp, *ra; |
char *fp, *ra; |
|
|
fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; |
fptype = print_bubblebabble ? |
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; |
SSH_DIGEST_SHA1 : fingerprint_hash; |
|
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT; |
fp = key_fingerprint(public, fptype, rep); |
fp = key_fingerprint(public, fptype, rep); |
ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART); |
ra = key_fingerprint(public, fingerprint_hash, |
|
SSH_FP_RANDOMART); |
printf("%u %s %s (%s)\n", key_size(public), fp, name, |
printf("%u %s %s (%s)\n", key_size(public), fp, name, |
key_type(public)); |
key_type(public)); |
if (log_level >= SYSLOG_LEVEL_VERBOSE) |
if (log_level >= SYSLOG_LEVEL_VERBOSE) |
|
|
} else { |
} else { |
if (hash && (name = host_hash(name, NULL, 0)) == NULL) |
if (hash && (name = host_hash(name, NULL, 0)) == NULL) |
fatal("hash_host failed"); |
fatal("hash_host failed"); |
fprintf(f, "%s%s%s ", ca ? CA_MARKER : "", ca ? " " : "", name); |
fprintf(f, "%s%s%s ", ca ? CA_MARKER " " : "", |
|
revoked ? REVOKE_MARKER " " : "" , name); |
if (!key_write(public, f)) |
if (!key_write(public, f)) |
fatal("key_write failed"); |
fatal("key_write failed"); |
fprintf(f, "\n"); |
fprintf(f, "\n"); |
|
|
char *cp, *cp2, *kp, *kp2; |
char *cp, *cp2, *kp, *kp2; |
char line[16*1024], tmp[MAXPATHLEN], old[MAXPATHLEN]; |
char line[16*1024], tmp[MAXPATHLEN], old[MAXPATHLEN]; |
int c, skip = 0, inplace = 0, num = 0, invalid = 0, has_unhashed = 0; |
int c, skip = 0, inplace = 0, num = 0, invalid = 0, has_unhashed = 0; |
int ca; |
int ca, revoked; |
int found_key = 0; |
int found_key = 0; |
|
|
if (!have_identity) { |
if (!have_identity) { |
|
|
if ((in = fopen(identity_file, "r")) == NULL) |
if ((in = fopen(identity_file, "r")) == NULL) |
fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); |
fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); |
|
|
|
/* XXX this code is a mess; refactor -djm */ |
/* |
/* |
* Find hosts goes to stdout, hash and deletions happen in-place |
* Find hosts goes to stdout, hash and deletions happen in-place |
* A corner case is ssh-keygen -HF foo, which should go to stdout |
* A corner case is ssh-keygen -HF foo, which should go to stdout |
|
|
fprintf(out, "%s\n", cp); |
fprintf(out, "%s\n", cp); |
continue; |
continue; |
} |
} |
/* Check whether this is a CA key */ |
/* Check whether this is a CA key or revocation marker */ |
if (strncasecmp(cp, CA_MARKER, sizeof(CA_MARKER) - 1) == 0 && |
if (strncasecmp(cp, CA_MARKER, sizeof(CA_MARKER) - 1) == 0 && |
(cp[sizeof(CA_MARKER) - 1] == ' ' || |
(cp[sizeof(CA_MARKER) - 1] == ' ' || |
cp[sizeof(CA_MARKER) - 1] == '\t')) { |
cp[sizeof(CA_MARKER) - 1] == '\t')) { |
|
|
cp += sizeof(CA_MARKER); |
cp += sizeof(CA_MARKER); |
} else |
} else |
ca = 0; |
ca = 0; |
|
if (strncasecmp(cp, REVOKE_MARKER, |
|
sizeof(REVOKE_MARKER) - 1) == 0 && |
|
(cp[sizeof(REVOKE_MARKER) - 1] == ' ' || |
|
cp[sizeof(REVOKE_MARKER) - 1] == '\t')) { |
|
revoked = 1; |
|
cp += sizeof(REVOKE_MARKER); |
|
} else |
|
revoked = 0; |
|
|
/* Find the end of the host name portion. */ |
/* Find the end of the host name portion. */ |
for (kp = cp; *kp && *kp != ' ' && *kp != '\t'; kp++) |
for (kp = cp; *kp && *kp != ' ' && *kp != '\t'; kp++) |
|
|
printf("# Host %s found: " |
printf("# Host %s found: " |
"line %d type %s%s\n", name, |
"line %d type %s%s\n", name, |
num, key_type(pub), |
num, key_type(pub), |
ca ? " (CA key)" : ""); |
ca ? " (CA key)" : |
printhost(out, cp, pub, ca, 0); |
revoked? " (revoked)" : ""); |
|
printhost(out, cp, pub, ca, revoked, 0); |
found_key = 1; |
found_key = 1; |
} |
} |
if (delete_host) { |
if (delete_host) { |
if (!c && !ca) |
if (!c || ca || revoked) { |
printhost(out, cp, pub, ca, 0); |
printhost(out, cp, pub, |
else |
ca, revoked, 0); |
|
} else { |
printf("# Host %s found: " |
printf("# Host %s found: " |
"line %d type %s\n", name, |
"line %d type %s\n", name, |
num, key_type(pub)); |
num, key_type(pub)); |
|
} |
} |
} |
} else if (hash_hosts) |
} else if (hash_hosts) |
printhost(out, cp, pub, ca, 0); |
printhost(out, cp, pub, ca, revoked, 0); |
} else { |
} else { |
if (find_host || delete_host) { |
if (find_host || delete_host) { |
c = (match_hostname(name, cp, |
c = (match_hostname(name, cp, |
|
|
"line %d type %s%s\n", name, |
"line %d type %s%s\n", name, |
num, key_type(pub), |
num, key_type(pub), |
ca ? " (CA key)" : ""); |
ca ? " (CA key)" : ""); |
printhost(out, name, pub, |
printhost(out, name, pub, ca, revoked, |
ca, hash_hosts && !ca); |
hash_hosts && !(ca || revoked)); |
found_key = 1; |
found_key = 1; |
} |
} |
if (delete_host) { |
if (delete_host) { |
if (!c && !ca) |
if (!c || ca || revoked) { |
printhost(out, cp, pub, ca, 0); |
printhost(out, cp, pub, |
else |
ca, revoked, 0); |
|
} else { |
printf("# Host %s found: " |
printf("# Host %s found: " |
"line %d type %s\n", name, |
"line %d type %s\n", name, |
num, key_type(pub)); |
num, key_type(pub)); |
|
} |
} |
} |
|
} else if (hash_hosts && (ca || revoked)) { |
|
/* Don't hash CA and revoked keys' hostnames */ |
|
printhost(out, cp, pub, ca, revoked, 0); |
|
has_unhashed = 1; |
} else if (hash_hosts) { |
} else if (hash_hosts) { |
|
/* Hash each hostname separately */ |
for (cp2 = strsep(&cp, ","); |
for (cp2 = strsep(&cp, ","); |
cp2 != NULL && *cp2 != '\0'; |
cp2 != NULL && *cp2 != '\0'; |
cp2 = strsep(&cp, ",")) { |
cp2 = strsep(&cp, ",")) { |
if (ca) { |
if (strcspn(cp2, "*?!") != |
fprintf(stderr, "Warning: " |
|
"ignoring CA key for host: " |
|
"%.64s\n", cp2); |
|
printhost(out, cp2, pub, ca, 0); |
|
} else if (strcspn(cp2, "*?!") != |
|
strlen(cp2)) { |
strlen(cp2)) { |
fprintf(stderr, "Warning: " |
fprintf(stderr, "Warning: " |
"ignoring host name with " |
"ignoring host name with " |
"metacharacters: %.64s\n", |
"metacharacters: %.64s\n", |
cp2); |
cp2); |
printhost(out, cp2, pub, ca, 0); |
printhost(out, cp2, pub, ca, |
} else |
revoked, 0); |
printhost(out, cp2, pub, ca, 1); |
has_unhashed = 1; |
|
} else { |
|
printhost(out, cp2, pub, ca, |
|
revoked, 1); |
|
} |
} |
} |
has_unhashed = 1; |
|
} |
} |
} |
} |
key_free(pub); |
key_free(pub); |
|
|
fatal("%s is not a certificate", identity_file); |
fatal("%s is not a certificate", identity_file); |
v00 = key->type == KEY_RSA_CERT_V00 || key->type == KEY_DSA_CERT_V00; |
v00 = key->type == KEY_RSA_CERT_V00 || key->type == KEY_DSA_CERT_V00; |
|
|
key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); |
key_fp = key_fingerprint(key, fingerprint_hash, SSH_FP_DEFAULT); |
ca_fp = key_fingerprint(key->cert->signature_key, |
ca_fp = key_fingerprint(key->cert->signature_key, |
SSH_FP_MD5, SSH_FP_HEX); |
fingerprint_hash, SSH_FP_DEFAULT); |
|
|
printf("%s:\n", identity_file); |
printf("%s:\n", identity_file); |
printf(" Type: %s %s certificate\n", key_ssh_name(key), |
printf(" Type: %s %s certificate\n", key_ssh_name(key), |
|
|
" ssh-keygen -e [-m key_format] [-f input_keyfile]\n" |
" ssh-keygen -e [-m key_format] [-f input_keyfile]\n" |
" ssh-keygen -y [-f input_keyfile]\n" |
" ssh-keygen -y [-f input_keyfile]\n" |
" ssh-keygen -c [-P passphrase] [-C comment] [-f keyfile]\n" |
" ssh-keygen -c [-P passphrase] [-C comment] [-f keyfile]\n" |
" ssh-keygen -l [-f input_keyfile]\n" |
" ssh-keygen -l [-E fingerprint_hash] [-f input_keyfile]\n" |
" ssh-keygen -B [-f input_keyfile]\n"); |
" ssh-keygen -B [-f input_keyfile]\n"); |
#ifdef ENABLE_PKCS11 |
#ifdef ENABLE_PKCS11 |
fprintf(stderr, |
fprintf(stderr, |
|
|
exit(1); |
exit(1); |
} |
} |
|
|
/* Remaining characters: EUYdw */ |
/* Remaining characters: UYdw */ |
while ((opt = getopt(argc, argv, "ABHLQXceghiklopquvxy" |
while ((opt = getopt(argc, argv, "ABHLQXceghiklopquvxy" |
"C:D:F:G:I:J:K:M:N:O:P:R:S:T:V:W:Z:a:b:f:g:j:m:n:r:s:t:z:")) != -1) { |
"C:D:E:F:G:I:J:K:M:N:O:P:R:S:T:V:W:Z:" |
|
"a:b:f:g:j:m:n:r:s:t:z:")) != -1) { |
switch (opt) { |
switch (opt) { |
case 'A': |
case 'A': |
gen_all_hostkeys = 1; |
gen_all_hostkeys = 1; |
|
|
fatal("Bits has bad value %s (%s)", |
fatal("Bits has bad value %s (%s)", |
optarg, errstr); |
optarg, errstr); |
break; |
break; |
|
case 'E': |
|
fingerprint_hash = ssh_digest_alg_by_name(optarg); |
|
if (fingerprint_hash == -1) |
|
fatal("Invalid hash algorithm \"%s\"", optarg); |
|
break; |
case 'F': |
case 'F': |
find_host = 1; |
find_host = 1; |
rr_hostname = optarg; |
rr_hostname = optarg; |
|
|
fclose(f); |
fclose(f); |
|
|
if (!quiet) { |
if (!quiet) { |
char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX); |
char *fp = key_fingerprint(public, fingerprint_hash, |
char *ra = key_fingerprint(public, SSH_FP_MD5, |
SSH_FP_DEFAULT); |
|
char *ra = key_fingerprint(public, fingerprint_hash, |
SSH_FP_RANDOMART); |
SSH_FP_RANDOMART); |
printf("Your public key has been saved in %s.\n", |
printf("Your public key has been saved in %s.\n", |
identity_file); |
identity_file); |