version 1.393, 2020/01/25 23:02:13 |
version 1.413, 2020/06/26 05:02:03 |
|
|
else |
else |
pass = read_passphrase("Enter passphrase: ", RP_ALLOW_STDIN); |
pass = read_passphrase("Enter passphrase: ", RP_ALLOW_STDIN); |
r = sshkey_load_private(filename, pass, &prv, commentp); |
r = sshkey_load_private(filename, pass, &prv, commentp); |
explicit_bzero(pass, strlen(pass)); |
freezero(pass, strlen(pass)); |
free(pass); |
|
if (r != 0) |
if (r != 0) |
fatal("Load key \"%s\": %s", filename, ssh_err(r)); |
fatal("Load key \"%s\": %s", filename, ssh_err(r)); |
return prv; |
return prv; |
|
|
encoded[len-3] = '\0'; |
encoded[len-3] = '\0'; |
if ((r = sshbuf_b64tod(buf, encoded)) != 0) |
if ((r = sshbuf_b64tod(buf, encoded)) != 0) |
fatal("%s: base64 decoding failed: %s", __func__, ssh_err(r)); |
fatal("%s: base64 decoding failed: %s", __func__, ssh_err(r)); |
if (*private) |
if (*private) { |
*k = do_convert_private_ssh2(buf); |
if ((*k = do_convert_private_ssh2(buf)) == NULL) |
else if ((r = sshkey_fromb(buf, k)) != 0) |
fatal("%s: private key conversion failed", __func__); |
|
} else if ((r = sshkey_fromb(buf, k)) != 0) |
fatal("decode blob failed: %s", ssh_err(r)); |
fatal("decode blob failed: %s", ssh_err(r)); |
sshbuf_free(buf); |
sshbuf_free(buf); |
fclose(fp); |
fclose(fp); |
|
|
{ |
{ |
struct stat st; |
struct stat st; |
char *comment = NULL; |
char *comment = NULL; |
struct sshkey *public = NULL; |
struct sshkey *privkey = NULL, *pubkey = NULL; |
int r; |
int r; |
|
|
if (stat(identity_file, &st) == -1) |
if (stat(identity_file, &st) == -1) |
fatal("%s: %s", path, strerror(errno)); |
fatal("%s: %s", path, strerror(errno)); |
if ((r = sshkey_load_public(path, &public, &comment)) != 0) { |
if ((r = sshkey_load_public(path, &pubkey, &comment)) != 0) |
debug("load public \"%s\": %s", path, ssh_err(r)); |
debug("load public \"%s\": %s", path, ssh_err(r)); |
|
if (pubkey == NULL || comment == NULL || *comment == '\0') { |
|
free(comment); |
if ((r = sshkey_load_private(path, NULL, |
if ((r = sshkey_load_private(path, NULL, |
&public, &comment)) != 0) { |
&privkey, &comment)) != 0) |
debug("load private \"%s\": %s", path, ssh_err(r)); |
debug("load private \"%s\": %s", path, ssh_err(r)); |
fatal("%s is not a key file.", path); |
|
} |
|
} |
} |
|
if (pubkey == NULL && privkey == NULL) |
|
fatal("%s is not a key file.", path); |
|
|
fingerprint_one_key(public, comment); |
fingerprint_one_key(pubkey == NULL ? privkey : pubkey, comment); |
sshkey_free(public); |
sshkey_free(pubkey); |
|
sshkey_free(privkey); |
free(comment); |
free(comment); |
} |
} |
|
|
|
|
struct sshkey *private, *public; |
struct sshkey *private, *public; |
char comment[1024], *prv_tmp, *pub_tmp, *prv_file, *pub_file; |
char comment[1024], *prv_tmp, *pub_tmp, *prv_file, *pub_file; |
int i, type, fd, r; |
int i, type, fd, r; |
FILE *f; |
|
|
|
for (i = 0; key_types[i].key_type; i++) { |
for (i = 0; key_types[i].key_type; i++) { |
public = private = NULL; |
public = private = NULL; |
|
|
fflush(stdout); |
fflush(stdout); |
type = sshkey_type_from_name(key_types[i].key_type); |
type = sshkey_type_from_name(key_types[i].key_type); |
if ((fd = mkstemp(prv_tmp)) == -1) { |
if ((fd = mkstemp(prv_tmp)) == -1) { |
error("Could not save your public key in %s: %s", |
error("Could not save your private key in %s: %s", |
prv_tmp, strerror(errno)); |
prv_tmp, strerror(errno)); |
goto failnext; |
goto failnext; |
} |
} |
close(fd); /* just using mkstemp() to generate/reserve a name */ |
(void)close(fd); /* just using mkstemp() to reserve a name */ |
bits = 0; |
bits = 0; |
type_bits_valid(type, NULL, &bits); |
type_bits_valid(type, NULL, &bits); |
if ((r = sshkey_generate(type, bits, &private)) != 0) { |
if ((r = sshkey_generate(type, bits, &private)) != 0) { |
|
|
goto failnext; |
goto failnext; |
} |
} |
(void)fchmod(fd, 0644); |
(void)fchmod(fd, 0644); |
f = fdopen(fd, "w"); |
(void)close(fd); |
if (f == NULL) { |
if ((r = sshkey_save_public(public, pub_tmp, comment)) != 0) { |
error("fdopen %s failed: %s", pub_tmp, strerror(errno)); |
fatal("Unable to save public key to %s: %s", |
close(fd); |
identity_file, ssh_err(r)); |
goto failnext; |
goto failnext; |
} |
} |
if ((r = sshkey_write(public, f)) != 0) { |
|
error("write key failed: %s", ssh_err(r)); |
|
fclose(f); |
|
goto failnext; |
|
} |
|
fprintf(f, " %s\n", comment); |
|
if (ferror(f) != 0) { |
|
error("write key failed: %s", strerror(errno)); |
|
fclose(f); |
|
goto failnext; |
|
} |
|
if (fclose(f) != 0) { |
|
error("key close failed: %s", strerror(errno)); |
|
goto failnext; |
|
} |
|
|
|
/* Rename temporary files to their permanent locations. */ |
/* Rename temporary files to their permanent locations. */ |
if (rename(pub_tmp, pub_file) != 0) { |
if (rename(pub_tmp, pub_file) != 0) { |
|
|
int r, fd, oerrno, inplace = 0; |
int r, fd, oerrno, inplace = 0; |
struct known_hosts_ctx ctx; |
struct known_hosts_ctx ctx; |
u_int foreach_options; |
u_int foreach_options; |
|
struct stat sb; |
|
|
if (!have_identity) { |
if (!have_identity) { |
cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid); |
cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid); |
|
|
free(cp); |
free(cp); |
have_identity = 1; |
have_identity = 1; |
} |
} |
|
if (stat(identity_file, &sb) != 0) |
|
fatal("Cannot stat %s: %s", identity_file, strerror(errno)); |
|
|
memset(&ctx, 0, sizeof(ctx)); |
memset(&ctx, 0, sizeof(ctx)); |
ctx.out = stdout; |
ctx.out = stdout; |
|
|
unlink(tmp); |
unlink(tmp); |
fatal("fdopen: %s", strerror(oerrno)); |
fatal("fdopen: %s", strerror(oerrno)); |
} |
} |
|
fchmod(fd, sb.st_mode & 0644); |
inplace = 1; |
inplace = 1; |
} |
} |
/* XXX support identity_file == "-" for stdin */ |
/* XXX support identity_file == "-" for stdin */ |
|
|
RP_ALLOW_STDIN); |
RP_ALLOW_STDIN); |
r = sshkey_load_private(identity_file, old_passphrase, |
r = sshkey_load_private(identity_file, old_passphrase, |
&private, &comment); |
&private, &comment); |
explicit_bzero(old_passphrase, strlen(old_passphrase)); |
freezero(old_passphrase, strlen(old_passphrase)); |
free(old_passphrase); |
|
if (r != 0) |
if (r != 0) |
goto badkey; |
goto badkey; |
} else if (r != 0) { |
} else if (r != 0) { |
|
|
exit(1); |
exit(1); |
} |
} |
/* Destroy the other copy. */ |
/* Destroy the other copy. */ |
explicit_bzero(passphrase2, strlen(passphrase2)); |
freezero(passphrase2, strlen(passphrase2)); |
free(passphrase2); |
|
} |
} |
|
|
/* Save the file using the new passphrase. */ |
/* Save the file using the new passphrase. */ |
|
|
comment, private_key_format, openssh_format_cipher, rounds)) != 0) { |
comment, private_key_format, openssh_format_cipher, rounds)) != 0) { |
error("Saving key \"%s\" failed: %s.", |
error("Saving key \"%s\" failed: %s.", |
identity_file, ssh_err(r)); |
identity_file, ssh_err(r)); |
explicit_bzero(passphrase1, strlen(passphrase1)); |
freezero(passphrase1, strlen(passphrase1)); |
free(passphrase1); |
|
sshkey_free(private); |
sshkey_free(private); |
free(comment); |
free(comment); |
exit(1); |
exit(1); |
} |
} |
/* Destroy the passphrase and the copy of the key in memory. */ |
/* Destroy the passphrase and the copy of the key in memory. */ |
explicit_bzero(passphrase1, strlen(passphrase1)); |
freezero(passphrase1, strlen(passphrase1)); |
free(passphrase1); |
|
sshkey_free(private); /* Destroys contents */ |
sshkey_free(private); /* Destroys contents */ |
free(comment); |
free(comment); |
|
|
|
|
struct sshkey *private; |
struct sshkey *private; |
struct sshkey *public; |
struct sshkey *public; |
struct stat st; |
struct stat st; |
FILE *f; |
int r; |
int r, fd; |
|
|
|
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"); |
|
|
/* Try to load using the passphrase. */ |
/* Try to load using the passphrase. */ |
if ((r = sshkey_load_private(identity_file, passphrase, |
if ((r = sshkey_load_private(identity_file, passphrase, |
&private, &comment)) != 0) { |
&private, &comment)) != 0) { |
explicit_bzero(passphrase, strlen(passphrase)); |
freezero(passphrase, strlen(passphrase)); |
free(passphrase); |
|
fatal("Cannot load private key \"%s\": %s.", |
fatal("Cannot load private key \"%s\": %s.", |
identity_file, ssh_err(r)); |
identity_file, ssh_err(r)); |
} |
} |
|
|
rounds)) != 0) { |
rounds)) != 0) { |
error("Saving key \"%s\" failed: %s", |
error("Saving key \"%s\" failed: %s", |
identity_file, ssh_err(r)); |
identity_file, ssh_err(r)); |
explicit_bzero(passphrase, strlen(passphrase)); |
freezero(passphrase, strlen(passphrase)); |
free(passphrase); |
|
sshkey_free(private); |
sshkey_free(private); |
free(comment); |
free(comment); |
exit(1); |
exit(1); |
} |
} |
explicit_bzero(passphrase, strlen(passphrase)); |
freezero(passphrase, strlen(passphrase)); |
free(passphrase); |
|
if ((r = sshkey_from_private(private, &public)) != 0) |
if ((r = sshkey_from_private(private, &public)) != 0) |
fatal("sshkey_from_private failed: %s", ssh_err(r)); |
fatal("sshkey_from_private failed: %s", ssh_err(r)); |
sshkey_free(private); |
sshkey_free(private); |
|
|
strlcat(identity_file, ".pub", sizeof(identity_file)); |
strlcat(identity_file, ".pub", sizeof(identity_file)); |
fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); |
if ((r = sshkey_save_public(public, identity_file, new_comment)) != 0) { |
if (fd == -1) |
fatal("Unable to save public key to %s: %s", |
fatal("Could not save your public key in %s", identity_file); |
identity_file, ssh_err(r)); |
f = fdopen(fd, "w"); |
} |
if (f == NULL) |
|
fatal("fdopen %s failed: %s", identity_file, strerror(errno)); |
|
if ((r = sshkey_write(public, f)) != 0) |
|
fatal("write key failed: %s", ssh_err(r)); |
|
sshkey_free(public); |
sshkey_free(public); |
fprintf(f, " %s\n", new_comment); |
|
fclose(f); |
|
|
|
free(comment); |
free(comment); |
|
|
if (strlen(new_comment) > 0) |
if (strlen(new_comment) > 0) |
|
|
if ((which & OPTIONS_EXTENSIONS) != 0 && |
if ((which & OPTIONS_EXTENSIONS) != 0 && |
(certflags_flags & CERTOPT_USER_RC) != 0) |
(certflags_flags & CERTOPT_USER_RC) != 0) |
add_flag_option(c, "permit-user-rc"); |
add_flag_option(c, "permit-user-rc"); |
if ((which & OPTIONS_CRITICAL) != 0 && |
if ((which & OPTIONS_EXTENSIONS) != 0 && |
(certflags_flags & CERTOPT_NO_REQUIRE_USER_PRESENCE) != 0) |
(certflags_flags & CERTOPT_NO_REQUIRE_USER_PRESENCE) != 0) |
add_flag_option(c, "no-touch-required"); |
add_flag_option(c, "no-touch-required"); |
if ((which & OPTIONS_CRITICAL) != 0 && |
if ((which & OPTIONS_CRITICAL) != 0 && |
|
|
unsigned long long cert_serial, int cert_serial_autoinc, |
unsigned long long cert_serial, int cert_serial_autoinc, |
int argc, char **argv) |
int argc, char **argv) |
{ |
{ |
int r, i, fd, found, agent_fd = -1; |
int r, i, found, agent_fd = -1; |
u_int n; |
u_int n; |
struct sshkey *ca, *public; |
struct sshkey *ca, *public; |
char valid[64], *otmp, *tmp, *cp, *out, *comment; |
char valid[64], *otmp, *tmp, *cp, *out, *comment; |
char *ca_fp = NULL, **plist = NULL; |
char *ca_fp = NULL, **plist = NULL; |
FILE *f; |
|
struct ssh_identitylist *agent_ids; |
struct ssh_identitylist *agent_ids; |
size_t j; |
size_t j; |
struct notifier_ctx *notifier = NULL; |
struct notifier_ctx *notifier = NULL; |
|
|
xasprintf(&out, "%s-cert.pub", tmp); |
xasprintf(&out, "%s-cert.pub", tmp); |
free(tmp); |
free(tmp); |
|
|
if ((fd = open(out, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) |
if ((r = sshkey_save_public(public, out, comment)) != 0) { |
fatal("Could not open \"%s\" for writing: %s", out, |
fatal("Unable to save public key to %s: %s", |
strerror(errno)); |
identity_file, ssh_err(r)); |
if ((f = fdopen(fd, "w")) == NULL) |
} |
fatal("%s: fdopen: %s", __func__, strerror(errno)); |
|
if ((r = sshkey_write(public, f)) != 0) |
|
fatal("Could not write certified key to %s: %s", |
|
out, ssh_err(r)); |
|
fprintf(f, " %s\n", comment); |
|
fclose(f); |
|
|
|
if (!quiet) { |
if (!quiet) { |
sshkey_format_cert_validity(public->cert, |
sshkey_format_cert_validity(public->cert, |
|
|
cp = cp + strspn(cp, " \t"); |
cp = cp + strspn(cp, " \t"); |
hash_to_blob(cp, &blob, &blen, file, lnum); |
hash_to_blob(cp, &blob, &blen, file, lnum); |
r = ssh_krl_revoke_key_sha256(krl, blob, blen); |
r = ssh_krl_revoke_key_sha256(krl, blob, blen); |
|
if (r != 0) |
|
fatal("%s: revoke key failed: %s", |
|
__func__, ssh_err(r)); |
} else { |
} else { |
if (strncasecmp(cp, "key:", 4) == 0) { |
if (strncasecmp(cp, "key:", 4) == 0) { |
cp += 4; |
cp += 4; |
|
|
} |
} |
|
|
static void |
static void |
do_check_krl(struct passwd *pw, int argc, char **argv) |
do_check_krl(struct passwd *pw, int print_krl, int argc, char **argv) |
{ |
{ |
int i, r, ret = 0; |
int i, r, ret = 0; |
char *comment; |
char *comment; |
|
|
if (*identity_file == '\0') |
if (*identity_file == '\0') |
fatal("KRL checking requires an input file"); |
fatal("KRL checking requires an input file"); |
load_krl(identity_file, &krl); |
load_krl(identity_file, &krl); |
|
if (print_krl) |
|
krl_dump(krl, stdout); |
for (i = 0; i < argc; i++) { |
for (i = 0; i < argc; i++) { |
if ((r = sshkey_load_public(argv[i], &k, &comment)) != 0) |
if ((r = sshkey_load_public(argv[i], &k, &comment)) != 0) |
fatal("Cannot load public key %s: %s", |
fatal("Cannot load public key %s: %s", |
|
|
int r; |
int r; |
|
|
/* |
/* |
* If passed a public key filename, then try to locate the correponding |
* If passed a public key filename, then try to locate the corresponding |
* private key. This lets us specify certificates on the command-line |
* private key. This lets us specify certificates on the command-line |
* and have ssh-keygen find the appropriate private key. |
* and have ssh-keygen find the appropriate private key. |
*/ |
*/ |
|
|
{ |
{ |
struct sshkey **keys; |
struct sshkey **keys; |
size_t nkeys, i; |
size_t nkeys, i; |
int r, ok = -1; |
int r, ret = -1; |
char *fp, *pin, *pass = NULL, *path, *pubpath; |
char *fp, *pin = NULL, *pass = NULL, *path, *pubpath; |
const char *ext; |
const char *ext; |
|
|
if (skprovider == NULL) |
if (skprovider == NULL) |
fatal("Cannot download keys without provider"); |
fatal("Cannot download keys without provider"); |
|
|
pin = read_passphrase("Enter PIN for security key: ", RP_ALLOW_STDIN); |
for (i = 0; i < 2; i++) { |
if ((r = sshsk_load_resident(skprovider, device, pin, |
if (i == 1) { |
&keys, &nkeys)) != 0) { |
pin = read_passphrase("Enter PIN for authenticator: ", |
freezero(pin, strlen(pin)); |
RP_ALLOW_STDIN); |
error("Unable to load resident keys: %s", ssh_err(r)); |
} |
return -1; |
if ((r = sshsk_load_resident(skprovider, device, pin, |
|
&keys, &nkeys)) != 0) { |
|
if (i == 0 && r == SSH_ERR_KEY_WRONG_PASSPHRASE) |
|
continue; |
|
if (pin != NULL) |
|
freezero(pin, strlen(pin)); |
|
error("Unable to load resident keys: %s", ssh_err(r)); |
|
return -1; |
|
} |
} |
} |
if (nkeys == 0) |
if (nkeys == 0) |
logit("No keys to download"); |
logit("No keys to download"); |
freezero(pin, strlen(pin)); |
if (pin != NULL) |
|
freezero(pin, strlen(pin)); |
|
|
for (i = 0; i < nkeys; i++) { |
for (i = 0; i < nkeys; i++) { |
if (keys[i]->type != KEY_ECDSA_SK && |
if (keys[i]->type != KEY_ECDSA_SK && |
|
|
free(path); |
free(path); |
if ((r = sshkey_save_public(keys[i], pubpath, |
if ((r = sshkey_save_public(keys[i], pubpath, |
keys[i]->sk_application)) != 0) { |
keys[i]->sk_application)) != 0) { |
free(pubpath); |
|
error("Saving public key \"%s\" failed: %s", |
error("Saving public key \"%s\" failed: %s", |
pubpath, ssh_err(r)); |
pubpath, ssh_err(r)); |
|
free(pubpath); |
break; |
break; |
} |
} |
free(pubpath); |
free(pubpath); |
} |
} |
|
|
if (i >= nkeys) |
if (i >= nkeys) |
ok = 0; /* success */ |
ret = 0; /* success */ |
if (pass != NULL) |
if (pass != NULL) |
freezero(pass, strlen(pass)); |
freezero(pass, strlen(pass)); |
for (i = 0; i < nkeys; i++) |
for (i = 0; i < nkeys; i++) |
sshkey_free(keys[i]); |
sshkey_free(keys[i]); |
free(keys); |
free(keys); |
return ok ? 0 : -1; |
return ret; |
} |
} |
|
|
static void |
static void |
|
|
" ssh-keygen -A [-f prefix_path]\n" |
" ssh-keygen -A [-f prefix_path]\n" |
" ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]\n" |
" ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]\n" |
" file ...\n" |
" file ...\n" |
" ssh-keygen -Q -f krl_file file ...\n" |
" ssh-keygen -Q [-l] -f krl_file [file ...]\n" |
" ssh-keygen -Y find-principals -s signature_file -f allowed_signers_file\n" |
" ssh-keygen -Y find-principals -s signature_file -f allowed_signers_file\n" |
" ssh-keygen -Y check-novalidate -n namespace -s signature_file\n" |
" ssh-keygen -Y check-novalidate -n namespace -s signature_file\n" |
" ssh-keygen -Y sign -f key_file -n namespace file ...\n" |
" ssh-keygen -Y sign -f key_file -n namespace file ...\n" |
|
|
int |
int |
main(int argc, char **argv) |
main(int argc, char **argv) |
{ |
{ |
char dotsshdir[PATH_MAX], comment[1024], *passphrase; |
char comment[1024], *passphrase; |
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; |
struct stat st; |
|
int r, opt, type; |
int r, opt, type; |
int change_passphrase = 0, change_comment = 0, show_cert = 0; |
int change_passphrase = 0, change_comment = 0, show_cert = 0; |
int find_host = 0, delete_host = 0, hash_hosts = 0; |
int find_host = 0, delete_host = 0, hash_hosts = 0; |
|
|
unsigned long long cert_serial = 0; |
unsigned long long cert_serial = 0; |
char *identity_comment = NULL, *ca_key_path = NULL, **opts = NULL; |
char *identity_comment = NULL, *ca_key_path = NULL, **opts = NULL; |
char *sk_application = NULL, *sk_device = NULL, *sk_user = NULL; |
char *sk_application = NULL, *sk_device = NULL, *sk_user = NULL; |
|
char *sk_attestaion_path = NULL; |
|
struct sshbuf *challenge = NULL, *attest = NULL; |
size_t i, nopts = 0; |
size_t i, nopts = 0; |
u_int32_t bits = 0; |
u_int32_t bits = 0; |
uint8_t sk_flags = SSH_SK_USER_PRESENCE_REQD; |
uint8_t sk_flags = SSH_SK_USER_PRESENCE_REQD; |
|
|
return (0); |
return (0); |
} |
} |
if (check_krl) { |
if (check_krl) { |
do_check_krl(pw, argc, argv); |
do_check_krl(pw, print_fingerprint, argc, argv); |
return (0); |
return (0); |
} |
} |
if (ca_key_path != NULL) { |
if (ca_key_path != NULL) { |
|
|
sk_device = xstrdup(opts[i] + 7); |
sk_device = xstrdup(opts[i] + 7); |
} else if (strncasecmp(opts[i], "user=", 5) == 0) { |
} else if (strncasecmp(opts[i], "user=", 5) == 0) { |
sk_user = xstrdup(opts[i] + 5); |
sk_user = xstrdup(opts[i] + 5); |
|
} else if (strncasecmp(opts[i], "challenge=", 10) == 0) { |
|
if ((r = sshbuf_load_file(opts[i] + 10, |
|
&challenge)) != 0) { |
|
fatal("Unable to load FIDO enrollment " |
|
"challenge \"%s\": %s", |
|
opts[i] + 10, ssh_err(r)); |
|
} |
} else if (strncasecmp(opts[i], |
} else if (strncasecmp(opts[i], |
|
"write-attestation=", 18) == 0) { |
|
sk_attestaion_path = opts[i] + 18; |
|
} else if (strncasecmp(opts[i], |
"application=", 12) == 0) { |
"application=", 12) == 0) { |
sk_application = xstrdup(opts[i] + 12); |
sk_application = xstrdup(opts[i] + 12); |
|
if (strncmp(sk_application, "ssh:", 4) != 0) { |
|
fatal("FIDO application string must " |
|
"begin with \"ssh:\""); |
|
} |
} else { |
} else { |
fatal("Option \"%s\" is unsupported for " |
fatal("Option \"%s\" is unsupported for " |
"FIDO authenticator enrollment", opts[i]); |
"FIDO authenticator enrollment", opts[i]); |
} |
} |
} |
} |
if (!quiet) { |
if (!quiet) { |
printf("You may need to touch your security key " |
printf("You may need to touch your authenticator " |
"to authorize key generation.\n"); |
"to authorize key generation.\n"); |
} |
} |
passphrase = NULL; |
passphrase = NULL; |
for (i = 0 ; i < 3; i++) { |
if ((attest = sshbuf_new()) == NULL) |
|
fatal("sshbuf_new failed"); |
|
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, |
sk_user, sk_flags, passphrase, NULL, |
sk_user, sk_flags, passphrase, challenge, |
&private, NULL); |
&private, attest); |
if (r == 0) |
if (r == 0) |
break; |
break; |
if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) |
if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) |
exit(1); /* error message already printed */ |
fatal("Key enrollment failed: %s", ssh_err(r)); |
if (passphrase != NULL) |
else if (i > 0) |
|
error("PIN incorrect"); |
|
if (passphrase != NULL) { |
freezero(passphrase, strlen(passphrase)); |
freezero(passphrase, strlen(passphrase)); |
passphrase = read_passphrase("Enter PIN for security " |
passphrase = NULL; |
"key: ", RP_ALLOW_STDIN); |
} |
|
if (i >= 3) |
|
fatal("Too many incorrect PINs"); |
|
passphrase = read_passphrase("Enter PIN for " |
|
"authenticator: ", RP_ALLOW_STDIN); |
} |
} |
if (passphrase != NULL) |
if (passphrase != NULL) { |
freezero(passphrase, strlen(passphrase)); |
freezero(passphrase, strlen(passphrase)); |
if (i > 3) |
passphrase = NULL; |
fatal("Too many incorrect PINs"); |
} |
break; |
break; |
default: |
default: |
if ((r = sshkey_generate(type, bits, &private)) != 0) |
if ((r = sshkey_generate(type, bits, &private)) != 0) |
|
|
ask_filename(pw, "Enter file in which to save the key"); |
ask_filename(pw, "Enter file in which to save the key"); |
|
|
/* Create ~/.ssh directory if it doesn't already exist. */ |
/* Create ~/.ssh directory if it doesn't already exist. */ |
snprintf(dotsshdir, sizeof dotsshdir, "%s/%s", |
hostfile_create_user_ssh_dir(identity_file, !quiet); |
pw->pw_dir, _PATH_SSH_USER_DIR); |
|
if (strstr(identity_file, dotsshdir) != NULL) { |
|
if (stat(dotsshdir, &st) == -1) { |
|
if (errno != ENOENT) { |
|
error("Could not stat %s: %s", dotsshdir, |
|
strerror(errno)); |
|
} else if (mkdir(dotsshdir, 0700) == -1) { |
|
error("Could not create directory '%s': %s", |
|
dotsshdir, strerror(errno)); |
|
} else if (!quiet) |
|
printf("Created directory '%s'.\n", dotsshdir); |
|
} |
|
} |
|
/* If the file already exists, ask the user to confirm. */ |
/* If the file already exists, ask the user to confirm. */ |
if (!confirm_overwrite(identity_file)) |
if (!confirm_overwrite(identity_file)) |
exit(1); |
exit(1); |
|
|
strlcat(identity_file, ".pub", sizeof(identity_file)); |
strlcat(identity_file, ".pub", sizeof(identity_file)); |
if ((r = sshkey_save_public(public, identity_file, comment)) != 0) { |
if ((r = sshkey_save_public(public, identity_file, comment)) != 0) { |
fatal("Unable to save public key to %s: %s", |
fatal("Unable to save public key to %s: %s", |
identity_file, strerror(errno)); |
identity_file, ssh_err(r)); |
} |
} |
|
|
if (!quiet) { |
if (!quiet) { |
|
|
free(fp); |
free(fp); |
} |
} |
|
|
|
if (sk_attestaion_path != NULL) { |
|
if (attest == NULL || sshbuf_len(attest) == 0) { |
|
fatal("Enrollment did not return attestation " |
|
"certificate"); |
|
} |
|
if ((r = sshbuf_write_file(sk_attestaion_path, attest)) != 0) { |
|
fatal("Unable to write attestation certificate " |
|
"\"%s\": %s", sk_attestaion_path, ssh_err(r)); |
|
} |
|
if (!quiet) { |
|
printf("Your FIDO attestation certificate has been " |
|
"saved in %s\n", sk_attestaion_path); |
|
} |
|
} |
|
sshbuf_free(attest); |
sshkey_free(public); |
sshkey_free(public); |
|
|
exit(0); |
exit(0); |
} |
} |