version 1.453, 2022/05/31 14:05:12 |
version 1.472, 2024/01/11 01:45:36 |
|
|
#include "ssh-pkcs11.h" |
#include "ssh-pkcs11.h" |
#endif |
#endif |
|
|
#ifdef WITH_OPENSSL |
#define DEFAULT_KEY_TYPE_NAME "ed25519" |
# define DEFAULT_KEY_TYPE_NAME "rsa" |
|
#else |
|
# define DEFAULT_KEY_TYPE_NAME "ed25519" |
|
#endif |
|
|
|
/* |
/* |
* Default number of bits in the RSA, DSA and ECDSA keys. These value can be |
* Default number of bits in the RSA, DSA and ECDSA keys. These value can be |
|
|
char *name = NULL; |
char *name = NULL; |
|
|
if (key_type_name == NULL) |
if (key_type_name == NULL) |
name = _PATH_SSH_CLIENT_ID_RSA; |
name = _PATH_SSH_CLIENT_ID_ED25519; |
else { |
else { |
switch (sshkey_type_from_name(key_type_name)) { |
switch (sshkey_type_from_name(key_type_name)) { |
|
#ifdef WITH_DSA |
case KEY_DSA_CERT: |
case KEY_DSA_CERT: |
case KEY_DSA: |
case KEY_DSA: |
name = _PATH_SSH_CLIENT_ID_DSA; |
name = _PATH_SSH_CLIENT_ID_DSA; |
break; |
break; |
|
#endif |
case KEY_ECDSA_CERT: |
case KEY_ECDSA_CERT: |
case KEY_ECDSA: |
case KEY_ECDSA: |
name = _PATH_SSH_CLIENT_ID_ECDSA; |
name = _PATH_SSH_CLIENT_ID_ECDSA; |
|
|
if (!PEM_write_RSA_PUBKEY(stdout, k->rsa)) |
if (!PEM_write_RSA_PUBKEY(stdout, k->rsa)) |
fatal("PEM_write_RSA_PUBKEY failed"); |
fatal("PEM_write_RSA_PUBKEY failed"); |
break; |
break; |
|
#ifdef WITH_DSA |
case KEY_DSA: |
case KEY_DSA: |
if (!PEM_write_DSA_PUBKEY(stdout, k->dsa)) |
if (!PEM_write_DSA_PUBKEY(stdout, k->dsa)) |
fatal("PEM_write_DSA_PUBKEY failed"); |
fatal("PEM_write_DSA_PUBKEY failed"); |
break; |
break; |
|
#endif |
case KEY_ECDSA: |
case KEY_ECDSA: |
if (!PEM_write_EC_PUBKEY(stdout, k->ecdsa)) |
if (!PEM_write_EC_PUBKEY(stdout, k->ecdsa)) |
fatal("PEM_write_EC_PUBKEY failed"); |
fatal("PEM_write_EC_PUBKEY failed"); |
|
|
if (!PEM_write_RSAPublicKey(stdout, k->rsa)) |
if (!PEM_write_RSAPublicKey(stdout, k->rsa)) |
fatal("PEM_write_RSAPublicKey failed"); |
fatal("PEM_write_RSAPublicKey failed"); |
break; |
break; |
|
#ifdef WITH_DSA |
case KEY_DSA: |
case KEY_DSA: |
if (!PEM_write_DSA_PUBKEY(stdout, k->dsa)) |
if (!PEM_write_DSA_PUBKEY(stdout, k->dsa)) |
fatal("PEM_write_DSA_PUBKEY failed"); |
fatal("PEM_write_DSA_PUBKEY failed"); |
break; |
break; |
|
#endif |
case KEY_ECDSA: |
case KEY_ECDSA: |
if (!PEM_write_EC_PUBKEY(stdout, k->ecdsa)) |
if (!PEM_write_EC_PUBKEY(stdout, k->ecdsa)) |
fatal("PEM_write_EC_PUBKEY failed"); |
fatal("PEM_write_EC_PUBKEY failed"); |
|
|
{ |
{ |
struct sshkey *key = NULL; |
struct sshkey *key = NULL; |
char *type, *cipher; |
char *type, *cipher; |
|
const char *alg = NULL; |
u_char e1, e2, e3, *sig = NULL, data[] = "abcde12345"; |
u_char e1, e2, e3, *sig = NULL, data[] = "abcde12345"; |
int r, rlen, ktype; |
int r, rlen, ktype; |
u_int magic, i1, i2, i3, i4; |
u_int magic, i1, i2, i3, i4; |
size_t slen; |
size_t slen; |
u_long e; |
u_long e; |
|
#ifdef WITH_DSA |
BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL; |
BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL; |
BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL; |
BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL; |
|
#endif |
BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL; |
BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL; |
BIGNUM *rsa_p = NULL, *rsa_q = NULL, *rsa_iqmp = NULL; |
BIGNUM *rsa_p = NULL, *rsa_q = NULL, *rsa_iqmp = NULL; |
|
|
|
|
} |
} |
free(cipher); |
free(cipher); |
|
|
if (strstr(type, "dsa")) { |
if (strstr(type, "rsa")) { |
ktype = KEY_DSA; |
|
} else if (strstr(type, "rsa")) { |
|
ktype = KEY_RSA; |
ktype = KEY_RSA; |
|
#ifdef WITH_DSA |
|
} else if (strstr(type, "dsa")) { |
|
ktype = KEY_DSA; |
|
#endif |
} else { |
} else { |
free(type); |
free(type); |
return NULL; |
return NULL; |
|
|
free(type); |
free(type); |
|
|
switch (key->type) { |
switch (key->type) { |
|
#ifdef WITH_DSA |
case KEY_DSA: |
case KEY_DSA: |
if ((dsa_p = BN_new()) == NULL || |
if ((dsa_p = BN_new()) == NULL || |
(dsa_q = BN_new()) == NULL || |
(dsa_q = BN_new()) == NULL || |
|
|
fatal_f("DSA_set0_key failed"); |
fatal_f("DSA_set0_key failed"); |
dsa_pub_key = dsa_priv_key = NULL; /* transferred */ |
dsa_pub_key = dsa_priv_key = NULL; /* transferred */ |
break; |
break; |
|
#endif |
case KEY_RSA: |
case KEY_RSA: |
if ((r = sshbuf_get_u8(b, &e1)) != 0 || |
if ((r = sshbuf_get_u8(b, &e1)) != 0 || |
(e1 < 30 && (r = sshbuf_get_u8(b, &e2)) != 0) || |
(e1 < 30 && (r = sshbuf_get_u8(b, &e2)) != 0) || |
|
|
if ((r = ssh_rsa_complete_crt_parameters(key, rsa_iqmp)) != 0) |
if ((r = ssh_rsa_complete_crt_parameters(key, rsa_iqmp)) != 0) |
fatal_fr(r, "generate RSA parameters"); |
fatal_fr(r, "generate RSA parameters"); |
BN_clear_free(rsa_iqmp); |
BN_clear_free(rsa_iqmp); |
|
alg = "rsa-sha2-256"; |
break; |
break; |
} |
} |
rlen = sshbuf_len(b); |
rlen = sshbuf_len(b); |
|
|
error_f("remaining bytes in key blob %d", rlen); |
error_f("remaining bytes in key blob %d", rlen); |
|
|
/* try the key */ |
/* try the key */ |
if (sshkey_sign(key, &sig, &slen, data, sizeof(data), |
if ((r = sshkey_sign(key, &sig, &slen, data, sizeof(data), |
NULL, NULL, NULL, 0) != 0 || |
alg, NULL, NULL, 0)) != 0) |
sshkey_verify(key, sig, slen, data, sizeof(data), |
error_fr(r, "signing with converted key failed"); |
NULL, 0, NULL) != 0) { |
else if ((r = sshkey_verify(key, sig, slen, data, sizeof(data), |
|
alg, 0, NULL)) != 0) |
|
error_fr(r, "verification with converted key failed"); |
|
if (r != 0) { |
sshkey_free(key); |
sshkey_free(key); |
free(sig); |
free(sig); |
return NULL; |
return NULL; |
|
|
(*k)->type = KEY_RSA; |
(*k)->type = KEY_RSA; |
(*k)->rsa = EVP_PKEY_get1_RSA(pubkey); |
(*k)->rsa = EVP_PKEY_get1_RSA(pubkey); |
break; |
break; |
|
#ifdef WITH_DSA |
case EVP_PKEY_DSA: |
case EVP_PKEY_DSA: |
if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) |
if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) |
fatal("sshkey_new failed"); |
fatal("sshkey_new failed"); |
(*k)->type = KEY_DSA; |
(*k)->type = KEY_DSA; |
(*k)->dsa = EVP_PKEY_get1_DSA(pubkey); |
(*k)->dsa = EVP_PKEY_get1_DSA(pubkey); |
break; |
break; |
|
#endif |
case EVP_PKEY_EC: |
case EVP_PKEY_EC: |
if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) |
if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) |
fatal("sshkey_new failed"); |
fatal("sshkey_new failed"); |
|
|
fprintf(stdout, "\n"); |
fprintf(stdout, "\n"); |
} else { |
} else { |
switch (k->type) { |
switch (k->type) { |
|
#ifdef WITH_DSA |
case KEY_DSA: |
case KEY_DSA: |
ok = PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, |
ok = PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, |
NULL, 0, NULL, NULL); |
NULL, 0, NULL, NULL); |
break; |
break; |
|
#endif |
case KEY_ECDSA: |
case KEY_ECDSA: |
ok = PEM_write_ECPrivateKey(stdout, k->ecdsa, NULL, |
ok = PEM_write_ECPrivateKey(stdout, k->ecdsa, NULL, |
NULL, 0, NULL, NULL); |
NULL, 0, NULL, NULL); |
|
|
* accept a public key prefixed with a hostname or options. |
* accept a public key prefixed with a hostname or options. |
* Try a bare key first, otherwise skip the leading stuff. |
* Try a bare key first, otherwise skip the leading stuff. |
*/ |
*/ |
|
comment = NULL; |
if ((public = try_read_key(&cp)) == NULL) { |
if ((public = try_read_key(&cp)) == NULL) { |
i = strtol(cp, &ep, 10); |
i = strtol(cp, &ep, 10); |
if (i == 0 || ep == NULL || |
if (i == 0 || ep == NULL || |
|
|
} key_types[] = { |
} key_types[] = { |
#ifdef WITH_OPENSSL |
#ifdef WITH_OPENSSL |
{ "rsa", "RSA" ,_PATH_HOST_RSA_KEY_FILE }, |
{ "rsa", "RSA" ,_PATH_HOST_RSA_KEY_FILE }, |
{ "dsa", "DSA", _PATH_HOST_DSA_KEY_FILE }, |
|
{ "ecdsa", "ECDSA",_PATH_HOST_ECDSA_KEY_FILE }, |
{ "ecdsa", "ECDSA",_PATH_HOST_ECDSA_KEY_FILE }, |
#endif /* WITH_OPENSSL */ |
#endif /* WITH_OPENSSL */ |
{ "ed25519", "ED25519",_PATH_HOST_ED25519_KEY_FILE }, |
{ "ed25519", "ED25519",_PATH_HOST_ED25519_KEY_FILE }, |
|
|
case HKF_STATUS_OK: |
case HKF_STATUS_OK: |
case HKF_STATUS_MATCHED: |
case HKF_STATUS_MATCHED: |
/* |
/* |
* Don't hash hosts already already hashed, with wildcard |
* Don't hash hosts already hashed, with wildcard |
* characters or a CA/revocation marker. |
* characters or a CA/revocation marker. |
*/ |
*/ |
if (was_hashed || has_wild || l->marker != MRK_NONE) { |
if (was_hashed || has_wild || l->marker != MRK_NONE) { |
|
|
unlink(tmp); |
unlink(tmp); |
fatal("fdopen: %s", strerror(oerrno)); |
fatal("fdopen: %s", strerror(oerrno)); |
} |
} |
fchmod(fd, sb.st_mode & 0644); |
(void)fchmod(fd, sb.st_mode & 0644); |
inplace = 1; |
inplace = 1; |
} |
} |
/* XXX support identity_file == "-" for stdin */ |
/* XXX support identity_file == "-" for stdin */ |
|
|
*/ |
*/ |
static int |
static int |
do_print_resource_record(struct passwd *pw, char *fname, char *hname, |
do_print_resource_record(struct passwd *pw, char *fname, char *hname, |
int print_generic) |
int print_generic, char * const *opts, size_t nopts) |
{ |
{ |
struct sshkey *public; |
struct sshkey *public; |
char *comment = NULL; |
char *comment = NULL; |
struct stat st; |
struct stat st; |
int r; |
int r, hash = -1; |
|
size_t i; |
|
|
|
for (i = 0; i < nopts; i++) { |
|
if (strncasecmp(opts[i], "hashalg=", 8) == 0) { |
|
if ((hash = ssh_digest_alg_by_name(opts[i] + 8)) == -1) |
|
fatal("Unsupported hash algorithm"); |
|
} else { |
|
error("Invalid option \"%s\"", opts[i]); |
|
return SSH_ERR_INVALID_ARGUMENT; |
|
} |
|
} |
if (fname == NULL) |
if (fname == NULL) |
fatal_f("no filename"); |
fatal_f("no filename"); |
if (stat(fname, &st) == -1) { |
if (stat(fname, &st) == -1) { |
|
|
} |
} |
if ((r = sshkey_load_public(fname, &public, &comment)) != 0) |
if ((r = sshkey_load_public(fname, &public, &comment)) != 0) |
fatal_r(r, "Failed to read v2 public key from \"%s\"", fname); |
fatal_r(r, "Failed to read v2 public key from \"%s\"", fname); |
export_dns_rr(hname, public, stdout, print_generic); |
export_dns_rr(hname, public, stdout, print_generic, hash); |
sshkey_free(public); |
sshkey_free(public); |
free(comment); |
free(comment); |
return 1; |
return 1; |
|
|
} |
} |
|
|
static void |
static void |
|
parse_hex_u64(const char *s, uint64_t *up) |
|
{ |
|
char *ep; |
|
unsigned long long ull; |
|
|
|
errno = 0; |
|
ull = strtoull(s, &ep, 16); |
|
if (*s == '\0' || *ep != '\0') |
|
fatal("Invalid certificate time: not a number"); |
|
if (errno == ERANGE && ull == ULONG_MAX) |
|
fatal_fr(SSH_ERR_SYSTEM_ERROR, "Invalid certificate time"); |
|
*up = (uint64_t)ull; |
|
} |
|
|
|
static void |
parse_cert_times(char *timespec) |
parse_cert_times(char *timespec) |
{ |
{ |
char *from, *to; |
char *from, *to; |
|
|
|
|
/* |
/* |
* from:to, where |
* from:to, where |
* from := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | "always" |
* from := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | 0x... | "always" |
* to := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | "forever" |
* to := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | 0x... | "forever" |
*/ |
*/ |
from = xstrdup(timespec); |
from = xstrdup(timespec); |
to = strchr(from, ':'); |
to = strchr(from, ':'); |
|
|
cert_valid_from = parse_relative_time(from, now); |
cert_valid_from = parse_relative_time(from, now); |
else if (strcmp(from, "always") == 0) |
else if (strcmp(from, "always") == 0) |
cert_valid_from = 0; |
cert_valid_from = 0; |
|
else if (strncmp(from, "0x", 2) == 0) |
|
parse_hex_u64(from, &cert_valid_from); |
else if (parse_absolute_time(from, &cert_valid_from) != 0) |
else if (parse_absolute_time(from, &cert_valid_from) != 0) |
fatal("Invalid from time \"%s\"", from); |
fatal("Invalid from time \"%s\"", from); |
|
|
|
|
cert_valid_to = parse_relative_time(to, now); |
cert_valid_to = parse_relative_time(to, now); |
else if (strcmp(to, "forever") == 0) |
else if (strcmp(to, "forever") == 0) |
cert_valid_to = ~(u_int64_t)0; |
cert_valid_to = ~(u_int64_t)0; |
|
else if (strncmp(to, "0x", 2) == 0) |
|
parse_hex_u64(to, &cert_valid_to); |
else if (parse_absolute_time(to, &cert_valid_to) != 0) |
else if (parse_absolute_time(to, &cert_valid_to) != 0) |
fatal("Invalid to time \"%s\"", to); |
fatal("Invalid to time \"%s\"", to); |
|
|
|
|
if ((r = sshbuf_load_file(path, &krlbuf)) != 0) |
if ((r = sshbuf_load_file(path, &krlbuf)) != 0) |
fatal_r(r, "Unable to load KRL %s", path); |
fatal_r(r, "Unable to load KRL %s", path); |
/* XXX check sigs */ |
/* XXX check sigs */ |
if ((r = ssh_krl_from_blob(krlbuf, krlp, NULL, 0)) != 0 || |
if ((r = ssh_krl_from_blob(krlbuf, krlp)) != 0 || |
*krlp == NULL) |
*krlp == NULL) |
fatal_r(r, "Invalid KRL file %s", path); |
fatal_r(r, "Invalid KRL file %s", path); |
sshbuf_free(krlbuf); |
sshbuf_free(krlbuf); |
|
|
* OpenSSH base64 hashes omit trailing '=' |
* OpenSSH base64 hashes omit trailing '=' |
* characters; put them back for decode. |
* characters; put them back for decode. |
*/ |
*/ |
tlen = strlen(cp); |
if ((tlen = strlen(cp)) >= SIZE_MAX - 5) |
|
fatal_f("hash too long: %zu bytes", tlen); |
tmp = xmalloc(tlen + 4 + 1); |
tmp = xmalloc(tlen + 4 + 1); |
strlcpy(tmp, cp, tlen + 1); |
strlcpy(tmp, cp, tlen + 1); |
while ((tlen % 4) != 0) { |
while ((tlen % 4) != 0) { |
|
|
if (!quiet) |
if (!quiet) |
printf("Revoking from %s\n", path); |
printf("Revoking from %s\n", path); |
while (getline(&line, &linesize, krl_spec) != -1) { |
while (getline(&line, &linesize, krl_spec) != -1) { |
|
if (linesize >= INT_MAX) { |
|
fatal_f("%s contains unparsable line, len=%zu", |
|
path, linesize); |
|
} |
lnum++; |
lnum++; |
was_explicit_key = was_sha1 = was_sha256 = was_hash = 0; |
was_explicit_key = was_sha1 = was_sha256 = was_hash = 0; |
cp = line + strspn(line, " \t"); |
cp = line + strspn(line, " \t"); |
|
|
|
|
if ((kbuf = sshbuf_new()) == NULL) |
if ((kbuf = sshbuf_new()) == NULL) |
fatal("sshbuf_new failed"); |
fatal("sshbuf_new failed"); |
if (ssh_krl_to_blob(krl, kbuf, NULL, 0) != 0) |
if (ssh_krl_to_blob(krl, kbuf) != 0) |
fatal("Couldn't generate KRL"); |
fatal("Couldn't generate KRL"); |
if ((r = sshbuf_write_file(identity_file, kbuf)) != 0) |
if ((r = sshbuf_write_file(identity_file, kbuf)) != 0) |
fatal("write %s: %s", identity_file, strerror(errno)); |
fatal("write %s: %s", identity_file, strerror(errno)); |
|
|
} else if (strncmp(opts[i], "start-line=", 11) == 0) { |
} else if (strncmp(opts[i], "start-line=", 11) == 0) { |
start_lineno = strtoul(opts[i]+11, NULL, 10); |
start_lineno = strtoul(opts[i]+11, NULL, 10); |
} else if (strncmp(opts[i], "checkpoint=", 11) == 0) { |
} else if (strncmp(opts[i], "checkpoint=", 11) == 0) { |
|
free(checkpoint); |
checkpoint = xstrdup(opts[i]+11); |
checkpoint = xstrdup(opts[i]+11); |
} else if (strncmp(opts[i], "generator=", 10) == 0) { |
} else if (strncmp(opts[i], "generator=", 10) == 0) { |
generator_wanted = (u_int32_t)strtonum( |
generator_wanted = (u_int32_t)strtonum( |
|
|
generator_wanted, checkpoint, |
generator_wanted, checkpoint, |
start_lineno, lines_to_process) != 0) |
start_lineno, lines_to_process) != 0) |
fatal("modulus screening failed"); |
fatal("modulus screening failed"); |
|
if (in != stdin) |
|
(void)fclose(in); |
|
free(checkpoint); |
#else /* WITH_OPENSSL */ |
#else /* WITH_OPENSSL */ |
fatal("Moduli screening is not supported"); |
fatal("Moduli screening is not supported"); |
#endif /* WITH_OPENSSL */ |
#endif /* WITH_OPENSSL */ |
} |
} |
|
|
|
/* Read and confirm a passphrase */ |
static char * |
static char * |
private_key_passphrase(void) |
read_check_passphrase(const char *prompt1, const char *prompt2, |
|
const char *retry_prompt) |
{ |
{ |
char *passphrase1, *passphrase2; |
char *passphrase1, *passphrase2; |
|
|
/* Ask for a passphrase (twice). */ |
for (;;) { |
if (identity_passphrase) |
passphrase1 = read_passphrase(prompt1, RP_ALLOW_STDIN); |
passphrase1 = xstrdup(identity_passphrase); |
passphrase2 = read_passphrase(prompt2, RP_ALLOW_STDIN); |
else if (identity_new_passphrase) |
if (strcmp(passphrase1, passphrase2) == 0) { |
passphrase1 = xstrdup(identity_new_passphrase); |
|
else { |
|
passphrase_again: |
|
passphrase1 = |
|
read_passphrase("Enter passphrase (empty for no " |
|
"passphrase): ", RP_ALLOW_STDIN); |
|
passphrase2 = read_passphrase("Enter same passphrase again: ", |
|
RP_ALLOW_STDIN); |
|
if (strcmp(passphrase1, passphrase2) != 0) { |
|
/* |
|
* The passphrases do not match. Clear them and |
|
* retry. |
|
*/ |
|
freezero(passphrase1, strlen(passphrase1)); |
|
freezero(passphrase2, strlen(passphrase2)); |
freezero(passphrase2, strlen(passphrase2)); |
printf("Passphrases do not match. Try again.\n"); |
return passphrase1; |
goto passphrase_again; |
|
} |
} |
/* Clear the other copy of the passphrase. */ |
/* The passphrases do not match. Clear them and retry. */ |
|
freezero(passphrase1, strlen(passphrase1)); |
freezero(passphrase2, strlen(passphrase2)); |
freezero(passphrase2, strlen(passphrase2)); |
|
fputs(retry_prompt, stdout); |
|
fputc('\n', stdout); |
|
fflush(stdout); |
} |
} |
return passphrase1; |
/* NOTREACHED */ |
|
return NULL; |
} |
} |
|
|
static char * |
static char * |
|
private_key_passphrase(void) |
|
{ |
|
if (identity_passphrase) |
|
return xstrdup(identity_passphrase); |
|
if (identity_new_passphrase) |
|
return xstrdup(identity_new_passphrase); |
|
|
|
return read_check_passphrase( |
|
"Enter passphrase (empty for no passphrase): ", |
|
"Enter same passphrase again: ", |
|
"Passphrases do not match. Try again."); |
|
} |
|
|
|
static char * |
sk_suffix(const char *application, const uint8_t *user, size_t userlen) |
sk_suffix(const char *application, const uint8_t *user, size_t userlen) |
{ |
{ |
char *ret, *cp; |
char *ret, *cp; |
|
|
"%s\n", path); |
"%s\n", path); |
} |
} |
|
|
|
static int |
|
confirm_sk_overwrite(const char *application, const char *user) |
|
{ |
|
char yesno[3]; |
|
|
|
printf("A resident key scoped to '%s' with user id '%s' already " |
|
"exists.\n", application == NULL ? "ssh:" : application, |
|
user == NULL ? "null" : user); |
|
printf("Overwrite key in token (y/n)? "); |
|
fflush(stdout); |
|
if (fgets(yesno, sizeof(yesno), stdin) == NULL) |
|
return 0; |
|
if (yesno[0] != 'y' && yesno[0] != 'Y') |
|
return 0; |
|
return 1; |
|
} |
|
|
static void |
static void |
usage(void) |
usage(void) |
{ |
{ |
|
|
int |
int |
main(int argc, char **argv) |
main(int argc, char **argv) |
{ |
{ |
char comment[1024], *passphrase; |
char comment[1024], *passphrase = NULL; |
char *rr_hostname = NULL, *ep, *fp, *ra; |
char *rr_hostname = NULL, *ep, *fp, *ra; |
struct sshkey *private, *public; |
struct sshkey *private, *public; |
struct passwd *pw; |
struct passwd *pw; |
|
|
else |
else |
fatal("Unsupported moduli option %s", optarg); |
fatal("Unsupported moduli option %s", optarg); |
break; |
break; |
case '?': |
|
default: |
default: |
usage(); |
usage(); |
} |
} |
|
|
|
|
if (have_identity) { |
if (have_identity) { |
n = do_print_resource_record(pw, identity_file, |
n = do_print_resource_record(pw, identity_file, |
rr_hostname, print_generic); |
rr_hostname, print_generic, opts, nopts); |
if (n == 0) |
if (n == 0) |
fatal("%s: %s", identity_file, strerror(errno)); |
fatal("%s: %s", identity_file, strerror(errno)); |
exit(0); |
exit(0); |
|
|
|
|
n += do_print_resource_record(pw, |
n += do_print_resource_record(pw, |
_PATH_HOST_RSA_KEY_FILE, rr_hostname, |
_PATH_HOST_RSA_KEY_FILE, rr_hostname, |
print_generic); |
print_generic, opts, nopts); |
|
#ifdef WITH_DSA |
n += do_print_resource_record(pw, |
n += do_print_resource_record(pw, |
_PATH_HOST_DSA_KEY_FILE, rr_hostname, |
_PATH_HOST_DSA_KEY_FILE, rr_hostname, |
print_generic); |
print_generic, opts, nopts); |
|
#endif |
n += do_print_resource_record(pw, |
n += do_print_resource_record(pw, |
_PATH_HOST_ECDSA_KEY_FILE, rr_hostname, |
_PATH_HOST_ECDSA_KEY_FILE, rr_hostname, |
print_generic); |
print_generic, opts, nopts); |
n += do_print_resource_record(pw, |
n += do_print_resource_record(pw, |
_PATH_HOST_ED25519_KEY_FILE, rr_hostname, |
_PATH_HOST_ED25519_KEY_FILE, rr_hostname, |
print_generic); |
print_generic, opts, nopts); |
n += do_print_resource_record(pw, |
n += do_print_resource_record(pw, |
_PATH_HOST_XMSS_KEY_FILE, rr_hostname, |
_PATH_HOST_XMSS_KEY_FILE, rr_hostname, |
print_generic); |
print_generic, opts, nopts); |
if (n == 0) |
if (n == 0) |
fatal("no keys found."); |
fatal("no keys found."); |
exit(0); |
exit(0); |
|
|
"FIDO authenticator enrollment", opts[i]); |
"FIDO authenticator enrollment", opts[i]); |
} |
} |
} |
} |
if (!quiet) { |
|
printf("You may need to touch your authenticator " |
|
"to authorize key generation.\n"); |
|
} |
|
if ((attest = sshbuf_new()) == NULL) |
if ((attest = sshbuf_new()) == NULL) |
fatal("sshbuf_new failed"); |
fatal("sshbuf_new failed"); |
if ((sk_flags & |
r = 0; |
(SSH_SK_USER_VERIFICATION_REQD|SSH_SK_RESIDENT_KEY))) { |
for (i = 0 ;;) { |
passphrase = read_passphrase("Enter PIN for " |
if (!quiet) { |
"authenticator: ", RP_ALLOW_STDIN); |
printf("You may need to touch your " |
} else { |
"authenticator%s to authorize key " |
passphrase = NULL; |
"generation.\n", |
} |
r == 0 ? "" : " again"); |
for (i = 0 ; ; i++) { |
} |
fflush(stdout); |
fflush(stdout); |
r = sshsk_enroll(type, sk_provider, sk_device, |
r = sshsk_enroll(type, sk_provider, sk_device, |
sk_application == NULL ? "ssh:" : sk_application, |
sk_application == NULL ? "ssh:" : sk_application, |
|
|
&private, attest); |
&private, attest); |
if (r == 0) |
if (r == 0) |
break; |
break; |
|
if (r == SSH_ERR_KEY_BAD_PERMISSIONS && |
|
(sk_flags & SSH_SK_RESIDENT_KEY) != 0 && |
|
(sk_flags & SSH_SK_FORCE_OPERATION) == 0 && |
|
confirm_sk_overwrite(sk_application, sk_user)) { |
|
sk_flags |= SSH_SK_FORCE_OPERATION; |
|
continue; |
|
} |
if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) |
if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) |
fatal_r(r, "Key enrollment failed"); |
fatal_r(r, "Key enrollment failed"); |
else if (passphrase != NULL) { |
else if (passphrase != NULL) { |
|
|
freezero(passphrase, strlen(passphrase)); |
freezero(passphrase, strlen(passphrase)); |
passphrase = NULL; |
passphrase = NULL; |
} |
} |
if (i >= 3) |
if (++i >= 3) |
fatal("Too many incorrect PINs"); |
fatal("Too many incorrect PINs"); |
passphrase = read_passphrase("Enter PIN for " |
passphrase = read_passphrase("Enter PIN for " |
"authenticator: ", RP_ALLOW_STDIN); |
"authenticator: ", RP_ALLOW_STDIN); |
if (!quiet) { |
|
printf("You may need to touch your " |
|
"authenticator (again) to authorize " |
|
"key generation.\n"); |
|
} |
|
} |
} |
if (passphrase != NULL) { |
if (passphrase != NULL) { |
freezero(passphrase, strlen(passphrase)); |
freezero(passphrase, strlen(passphrase)); |