version 1.407, 2020/04/20 04:43:57 |
version 1.416, 2020/08/27 01:06:18 |
|
|
static char *certflags_src_addr = NULL; |
static char *certflags_src_addr = NULL; |
|
|
/* Arbitrary extensions specified by user */ |
/* Arbitrary extensions specified by user */ |
struct cert_userext { |
struct cert_ext { |
char *key; |
char *key; |
char *val; |
char *val; |
int crit; |
int crit; |
}; |
}; |
static struct cert_userext *cert_userext; |
static struct cert_ext *cert_ext; |
static size_t ncert_userext; |
static size_t ncert_ext; |
|
|
/* Conversion to/from various formats */ |
/* Conversion to/from various formats */ |
enum { |
enum { |
|
|
|
|
/* try the key */ |
/* try the key */ |
if (sshkey_sign(key, &sig, &slen, data, sizeof(data), |
if (sshkey_sign(key, &sig, &slen, data, sizeof(data), |
NULL, NULL, 0) != 0 || |
NULL, NULL, NULL, 0) != 0 || |
sshkey_verify(key, sig, slen, data, sizeof(data), |
sshkey_verify(key, sig, slen, data, sizeof(data), |
NULL, 0, NULL) != 0) { |
NULL, 0, NULL) != 0) { |
sshkey_free(key); |
sshkey_free(key); |
|
|
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 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 */ |
|
|
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"); |
|
|
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) |
|
|
} |
} |
|
|
static void |
static void |
add_flag_option(struct sshbuf *c, const char *name) |
cert_ext_add(const char *key, const char *value, int iscrit) |
{ |
{ |
int r; |
cert_ext = xreallocarray(cert_ext, ncert_ext + 1, sizeof(*cert_ext)); |
|
cert_ext[ncert_ext].key = xstrdup(key); |
debug3("%s: %s", __func__, name); |
cert_ext[ncert_ext].val = value == NULL ? NULL : xstrdup(value); |
if ((r = sshbuf_put_cstring(c, name)) != 0 || |
cert_ext[ncert_ext].crit = iscrit; |
(r = sshbuf_put_string(c, NULL, 0)) != 0) |
ncert_ext++; |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
|
} |
} |
|
|
static void |
/* qsort(3) comparison function for certificate extensions */ |
add_string_option(struct sshbuf *c, const char *name, const char *value) |
static int |
|
cert_ext_cmp(const void *_a, const void *_b) |
{ |
{ |
struct sshbuf *b; |
const struct cert_ext *a = (const struct cert_ext *)_a; |
|
const struct cert_ext *b = (const struct cert_ext *)_b; |
int r; |
int r; |
|
|
debug3("%s: %s=%s", __func__, name, value); |
if (a->crit != b->crit) |
if ((b = sshbuf_new()) == NULL) |
return (a->crit < b->crit) ? -1 : 1; |
fatal("%s: sshbuf_new failed", __func__); |
if ((r = strcmp(a->key, b->key)) != 0) |
if ((r = sshbuf_put_cstring(b, value)) != 0 || |
return r; |
(r = sshbuf_put_cstring(c, name)) != 0 || |
if ((a->val == NULL) != (b->val == NULL)) |
(r = sshbuf_put_stringb(c, b)) != 0) |
return (a->val == NULL) ? -1 : 1; |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
if (a->val != NULL && (r = strcmp(a->val, b->val)) != 0) |
|
return r; |
sshbuf_free(b); |
return 0; |
} |
} |
|
|
#define OPTIONS_CRITICAL 1 |
#define OPTIONS_CRITICAL 1 |
|
|
static void |
static void |
prepare_options_buf(struct sshbuf *c, int which) |
prepare_options_buf(struct sshbuf *c, int which) |
{ |
{ |
|
struct sshbuf *b; |
size_t i; |
size_t i; |
|
int r; |
|
const struct cert_ext *ext; |
|
|
|
if ((b = sshbuf_new()) == NULL) |
|
fatal("%s: sshbuf_new failed", __func__); |
sshbuf_reset(c); |
sshbuf_reset(c); |
if ((which & OPTIONS_CRITICAL) != 0 && |
for (i = 0; i < ncert_ext; i++) { |
certflags_command != NULL) |
ext = &cert_ext[i]; |
add_string_option(c, "force-command", certflags_command); |
if ((ext->crit && (which & OPTIONS_EXTENSIONS)) || |
if ((which & OPTIONS_EXTENSIONS) != 0 && |
(!ext->crit && (which & OPTIONS_CRITICAL))) |
(certflags_flags & CERTOPT_X_FWD) != 0) |
|
add_flag_option(c, "permit-X11-forwarding"); |
|
if ((which & OPTIONS_EXTENSIONS) != 0 && |
|
(certflags_flags & CERTOPT_AGENT_FWD) != 0) |
|
add_flag_option(c, "permit-agent-forwarding"); |
|
if ((which & OPTIONS_EXTENSIONS) != 0 && |
|
(certflags_flags & CERTOPT_PORT_FWD) != 0) |
|
add_flag_option(c, "permit-port-forwarding"); |
|
if ((which & OPTIONS_EXTENSIONS) != 0 && |
|
(certflags_flags & CERTOPT_PTY) != 0) |
|
add_flag_option(c, "permit-pty"); |
|
if ((which & OPTIONS_EXTENSIONS) != 0 && |
|
(certflags_flags & CERTOPT_USER_RC) != 0) |
|
add_flag_option(c, "permit-user-rc"); |
|
if ((which & OPTIONS_EXTENSIONS) != 0 && |
|
(certflags_flags & CERTOPT_NO_REQUIRE_USER_PRESENCE) != 0) |
|
add_flag_option(c, "no-touch-required"); |
|
if ((which & OPTIONS_CRITICAL) != 0 && |
|
certflags_src_addr != NULL) |
|
add_string_option(c, "source-address", certflags_src_addr); |
|
for (i = 0; i < ncert_userext; i++) { |
|
if ((cert_userext[i].crit && (which & OPTIONS_EXTENSIONS)) || |
|
(!cert_userext[i].crit && (which & OPTIONS_CRITICAL))) |
|
continue; |
continue; |
if (cert_userext[i].val == NULL) |
if (ext->val == NULL) { |
add_flag_option(c, cert_userext[i].key); |
/* flag option */ |
else { |
debug3("%s: %s", __func__, ext->key); |
add_string_option(c, cert_userext[i].key, |
if ((r = sshbuf_put_cstring(c, ext->key)) != 0 || |
cert_userext[i].val); |
(r = sshbuf_put_string(c, NULL, 0)) != 0) |
|
fatal("%s: buffer: %s", __func__, ssh_err(r)); |
|
} else { |
|
/* key/value option */ |
|
debug3("%s: %s=%s", __func__, ext->key, ext->val); |
|
sshbuf_reset(b); |
|
if ((r = sshbuf_put_cstring(c, ext->key)) != 0 || |
|
(r = sshbuf_put_cstring(b, ext->val)) != 0 || |
|
(r = sshbuf_put_stringb(c, b)) != 0) |
|
fatal("%s: buffer: %s", __func__, ssh_err(r)); |
} |
} |
} |
} |
|
sshbuf_free(b); |
} |
} |
|
|
|
static void |
|
finalise_cert_exts(void) |
|
{ |
|
/* critical options */ |
|
if (certflags_command != NULL) |
|
cert_ext_add("force-command", certflags_command, 1); |
|
if (certflags_src_addr != NULL) |
|
cert_ext_add("source-address", certflags_src_addr, 1); |
|
/* extensions */ |
|
if ((certflags_flags & CERTOPT_X_FWD) != 0) |
|
cert_ext_add("permit-X11-forwarding", NULL, 0); |
|
if ((certflags_flags & CERTOPT_AGENT_FWD) != 0) |
|
cert_ext_add("permit-agent-forwarding", NULL, 0); |
|
if ((certflags_flags & CERTOPT_PORT_FWD) != 0) |
|
cert_ext_add("permit-port-forwarding", NULL, 0); |
|
if ((certflags_flags & CERTOPT_PTY) != 0) |
|
cert_ext_add("permit-pty", NULL, 0); |
|
if ((certflags_flags & CERTOPT_USER_RC) != 0) |
|
cert_ext_add("permit-user-rc", NULL, 0); |
|
if ((certflags_flags & CERTOPT_NO_REQUIRE_USER_PRESENCE) != 0) |
|
cert_ext_add("no-touch-required", NULL, 0); |
|
/* order lexically by key */ |
|
if (ncert_ext > 0) |
|
qsort(cert_ext, ncert_ext, sizeof(*cert_ext), cert_ext_cmp); |
|
} |
|
|
static struct sshkey * |
static struct sshkey * |
load_pkcs11_key(char *path) |
load_pkcs11_key(char *path) |
{ |
{ |
|
|
static int |
static int |
agent_signer(struct sshkey *key, u_char **sigp, size_t *lenp, |
agent_signer(struct sshkey *key, u_char **sigp, size_t *lenp, |
const u_char *data, size_t datalen, |
const u_char *data, size_t datalen, |
const char *alg, const char *provider, u_int compat, void *ctx) |
const char *alg, const char *provider, const char *pin, |
|
u_int compat, void *ctx) |
{ |
{ |
int *agent_fdp = (int *)ctx; |
int *agent_fdp = (int *)ctx; |
|
|
|
|
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, *pin = 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; |
|
|
} else { |
} else { |
/* CA key is assumed to be a private key on the filesystem */ |
/* CA key is assumed to be a private key on the filesystem */ |
ca = load_identity(tmp, NULL); |
ca = load_identity(tmp, NULL); |
|
if (sshkey_is_sk(ca) && |
|
(ca->sk_flags & SSH_SK_USER_VERIFICATION_REQD)) { |
|
if ((pin = read_passphrase("Enter PIN for CA key: ", |
|
RP_ALLOW_STDIN)) == NULL) |
|
fatal("%s: couldn't read PIN", __func__); |
|
} |
} |
} |
free(tmp); |
free(tmp); |
|
|
|
|
} |
} |
ca_fp = sshkey_fingerprint(ca, fingerprint_hash, SSH_FP_DEFAULT); |
ca_fp = sshkey_fingerprint(ca, fingerprint_hash, SSH_FP_DEFAULT); |
|
|
|
finalise_cert_exts(); |
for (i = 0; i < argc; i++) { |
for (i = 0; i < argc; i++) { |
/* Split list of principals */ |
/* Split list of principals */ |
n = 0; |
n = 0; |
|
|
|
|
if (agent_fd != -1 && (ca->flags & SSHKEY_FLAG_EXT) != 0) { |
if (agent_fd != -1 && (ca->flags & SSHKEY_FLAG_EXT) != 0) { |
if ((r = sshkey_certify_custom(public, ca, |
if ((r = sshkey_certify_custom(public, ca, |
key_type_name, sk_provider, agent_signer, |
key_type_name, sk_provider, NULL, agent_signer, |
&agent_fd)) != 0) |
&agent_fd)) != 0) |
fatal("Couldn't certify key %s via agent: %s", |
fatal("Couldn't certify key %s via agent: %s", |
tmp, ssh_err(r)); |
tmp, ssh_err(r)); |
|
|
sshkey_type(ca), ca_fp); |
sshkey_type(ca), ca_fp); |
} |
} |
r = sshkey_certify(public, ca, key_type_name, |
r = sshkey_certify(public, ca, key_type_name, |
sk_provider); |
sk_provider, pin); |
notify_complete(notifier); |
notify_complete(notifier); |
if (r != 0) |
if (r != 0) |
fatal("Couldn't certify key %s: %s", |
fatal("Couldn't certify key %s: %s", |
|
|
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, |
|
|
if (cert_serial_autoinc) |
if (cert_serial_autoinc) |
cert_serial++; |
cert_serial++; |
} |
} |
|
if (pin != NULL) |
|
freezero(pin, strlen(pin)); |
free(ca_fp); |
free(ca_fp); |
#ifdef ENABLE_PKCS11 |
#ifdef ENABLE_PKCS11 |
pkcs11_terminate(); |
pkcs11_terminate(); |
|
|
val = xstrdup(strchr(opt, ':') + 1); |
val = xstrdup(strchr(opt, ':') + 1); |
if ((cp = strchr(val, '=')) != NULL) |
if ((cp = strchr(val, '=')) != NULL) |
*cp++ = '\0'; |
*cp++ = '\0'; |
cert_userext = xreallocarray(cert_userext, ncert_userext + 1, |
cert_ext_add(val, cp, iscrit); |
sizeof(*cert_userext)); |
free(val); |
cert_userext[ncert_userext].key = val; |
|
cert_userext[ncert_userext].val = cp == NULL ? |
|
NULL : xstrdup(cp); |
|
cert_userext[ncert_userext].crit = iscrit; |
|
ncert_userext++; |
|
} else |
} else |
fatal("Unsupported certificate option \"%s\"", opt); |
fatal("Unsupported certificate option \"%s\"", opt); |
} |
} |
|
|
static void |
static void |
show_options(struct sshbuf *optbuf, int in_critical) |
show_options(struct sshbuf *optbuf, int in_critical) |
{ |
{ |
char *name, *arg; |
char *name, *arg, *hex; |
struct sshbuf *options, *option = NULL; |
struct sshbuf *options, *option = NULL; |
int r; |
int r; |
|
|
|
|
__func__, ssh_err(r)); |
__func__, ssh_err(r)); |
printf(" %s\n", arg); |
printf(" %s\n", arg); |
free(arg); |
free(arg); |
} else { |
} else if (sshbuf_len(option) > 0) { |
printf(" UNKNOWN OPTION (len %zu)\n", |
hex = sshbuf_dtob16(option); |
sshbuf_len(option)); |
printf(" UNKNOWN OPTION: %s (len %zu)\n", |
|
hex, sshbuf_len(option)); |
sshbuf_reset(option); |
sshbuf_reset(option); |
} |
free(hex); |
|
} else |
|
printf(" UNKNOWN FLAG OPTION\n"); |
free(name); |
free(name); |
if (sshbuf_len(option) != 0) |
if (sshbuf_len(option) != 0) |
fatal("Option corrupt: extra data at end"); |
fatal("Option corrupt: extra data at end"); |
|
|
struct sshbuf *sigbuf = NULL, *abuf = NULL; |
struct sshbuf *sigbuf = NULL, *abuf = NULL; |
int r = SSH_ERR_INTERNAL_ERROR, wfd = -1, oerrno; |
int r = SSH_ERR_INTERNAL_ERROR, wfd = -1, oerrno; |
char *wfile = NULL, *asig = NULL, *fp = NULL; |
char *wfile = NULL, *asig = NULL, *fp = NULL; |
|
char *pin = NULL, *prompt = NULL; |
|
|
if (!quiet) { |
if (!quiet) { |
if (fd == STDIN_FILENO) |
if (fd == STDIN_FILENO) |
|
|
else |
else |
fprintf(stderr, "Signing file %s\n", filename); |
fprintf(stderr, "Signing file %s\n", filename); |
} |
} |
if (signer == NULL && sshkey_is_sk(signkey) && |
if (signer == NULL && sshkey_is_sk(signkey)) { |
(signkey->sk_flags & SSH_SK_USER_PRESENCE_REQD)) { |
if ((signkey->sk_flags & SSH_SK_USER_VERIFICATION_REQD)) { |
if ((fp = sshkey_fingerprint(signkey, fingerprint_hash, |
xasprintf(&prompt, "Enter PIN for %s key: ", |
SSH_FP_DEFAULT)) == NULL) |
sshkey_type(signkey)); |
fatal("%s: sshkey_fingerprint failed", __func__); |
if ((pin = read_passphrase(prompt, |
fprintf(stderr, "Confirm user presence for key %s %s\n", |
RP_ALLOW_STDIN)) == NULL) |
sshkey_type(signkey), fp); |
fatal("%s: couldn't read PIN", __func__); |
free(fp); |
} |
|
if ((signkey->sk_flags & SSH_SK_USER_PRESENCE_REQD)) { |
|
if ((fp = sshkey_fingerprint(signkey, fingerprint_hash, |
|
SSH_FP_DEFAULT)) == NULL) |
|
fatal("%s: fingerprint failed", __func__); |
|
fprintf(stderr, "Confirm user presence for key %s %s\n", |
|
sshkey_type(signkey), fp); |
|
free(fp); |
|
} |
} |
} |
if ((r = sshsig_sign_fd(signkey, NULL, sk_provider, fd, sig_namespace, |
if ((r = sshsig_sign_fd(signkey, NULL, sk_provider, pin, |
&sigbuf, signer, signer_ctx)) != 0) { |
fd, sig_namespace, &sigbuf, signer, signer_ctx)) != 0) { |
error("Signing %s failed: %s", filename, ssh_err(r)); |
error("Signing %s failed: %s", filename, ssh_err(r)); |
goto out; |
goto out; |
} |
} |
|
|
r = 0; |
r = 0; |
out: |
out: |
free(wfile); |
free(wfile); |
|
free(prompt); |
free(asig); |
free(asig); |
|
if (pin != NULL) |
|
freezero(pin, strlen(pin)); |
sshbuf_free(abuf); |
sshbuf_free(abuf); |
sshbuf_free(sigbuf); |
sshbuf_free(sigbuf); |
if (wfd != -1) |
if (wfd != -1) |
|
|
{ |
{ |
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 = NULL, *pass = NULL, *path, *pubpath; |
char *fp, *pin = NULL, *pass = NULL, *path, *pubpath; |
const char *ext; |
const char *ext; |
|
|
|
|
&keys, &nkeys)) != 0) { |
&keys, &nkeys)) != 0) { |
if (i == 0 && r == SSH_ERR_KEY_WRONG_PASSPHRASE) |
if (i == 0 && r == SSH_ERR_KEY_WRONG_PASSPHRASE) |
continue; |
continue; |
freezero(pin, strlen(pin)); |
if (pin != NULL) |
|
freezero(pin, strlen(pin)); |
error("Unable to load resident keys: %s", ssh_err(r)); |
error("Unable to load resident keys: %s", ssh_err(r)); |
return -1; |
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 && |
|
|
} |
} |
|
|
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 |
usage(void) |
usage(void) |
{ |
{ |
fprintf(stderr, |
fprintf(stderr, |
"usage: ssh-keygen [-q] [-b bits] [-C comment] [-f output_keyfile] [-m format]\n" |
"usage: ssh-keygen [-q] [-a rounds] [-b bits] [-C comment] [-f output_keyfile]\n" |
|
" [-m format] [-N new_passphrase] [-O option]\n" |
" [-t dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa]\n" |
" [-t dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa]\n" |
" [-N new_passphrase] [-O option] [-w provider]\n" |
" [-w provider]\n" |
" ssh-keygen -p [-f keyfile] [-m format] [-N new_passphrase]\n" |
" ssh-keygen -p [-a rounds] [-f keyfile] [-m format] [-N new_passphrase]\n" |
" [-P old_passphrase]\n" |
" [-P old_passphrase]\n" |
" ssh-keygen -i [-f input_keyfile] [-m key_format]\n" |
" ssh-keygen -i [-f input_keyfile] [-m key_format]\n" |
" ssh-keygen -e [-f input_keyfile] [-m key_format]\n" |
" ssh-keygen -e [-f input_keyfile] [-m key_format]\n" |
" ssh-keygen -y [-f input_keyfile]\n" |
" ssh-keygen -y [-f input_keyfile]\n" |
" ssh-keygen -c [-C comment] [-f keyfile] [-P passphrase]\n" |
" ssh-keygen -c [-a rounds] [-C comment] [-f keyfile] [-P passphrase]\n" |
" ssh-keygen -l [-v] [-E fingerprint_hash] [-f input_keyfile]\n" |
" ssh-keygen -l [-v] [-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, |
" ssh-keygen -F hostname [-lv] [-f known_hosts_file]\n" |
" ssh-keygen -F hostname [-lv] [-f known_hosts_file]\n" |
" ssh-keygen -H [-f known_hosts_file]\n" |
" ssh-keygen -H [-f known_hosts_file]\n" |
" ssh-keygen -K [-w provider]\n" |
" ssh-keygen -K [-a rounds] [-w provider]\n" |
" ssh-keygen -R hostname [-f known_hosts_file]\n" |
" ssh-keygen -R hostname [-f known_hosts_file]\n" |
" ssh-keygen -r hostname [-g] [-f input_keyfile]\n" |
" ssh-keygen -r hostname [-g] [-f input_keyfile]\n" |
#ifdef WITH_OPENSSL |
#ifdef WITH_OPENSSL |
|
|
" [-n principals] [-O option] [-V validity_interval]\n" |
" [-n principals] [-O option] [-V validity_interval]\n" |
" [-z serial_number] file ...\n" |
" [-z serial_number] file ...\n" |
" ssh-keygen -L [-f input_keyfile]\n" |
" ssh-keygen -L [-f input_keyfile]\n" |
" ssh-keygen -A [-f prefix_path]\n" |
" ssh-keygen -A [-a rounds] [-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 [-l] -f krl_file [file ...]\n" |
" ssh-keygen -Q [-l] -f krl_file [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; |
|
|
for (i = 0; i < nopts; i++) { |
for (i = 0; i < nopts; i++) { |
if (strcasecmp(opts[i], "no-touch-required") == 0) { |
if (strcasecmp(opts[i], "no-touch-required") == 0) { |
sk_flags &= ~SSH_SK_USER_PRESENCE_REQD; |
sk_flags &= ~SSH_SK_USER_PRESENCE_REQD; |
|
} else if (strcasecmp(opts[i], "verify-required") == 0) { |
|
sk_flags |= SSH_SK_USER_VERIFICATION_REQD; |
} else if (strcasecmp(opts[i], "resident") == 0) { |
} else if (strcasecmp(opts[i], "resident") == 0) { |
sk_flags |= SSH_SK_RESIDENT_KEY; |
sk_flags |= SSH_SK_RESIDENT_KEY; |
} else if (strncasecmp(opts[i], "device=", 7) == 0) { |
} else if (strncasecmp(opts[i], "device=", 7) == 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) { |