version 1.270, 2021/01/26 00:53:31 |
version 1.271, 2021/01/26 00:54:49 |
|
|
return (deadline - now); |
return (deadline - now); |
} |
} |
|
|
static void |
static int |
process_add_identity(SocketEntry *e) |
parse_key_constraints(struct sshbuf *m, struct sshkey *k, time_t *deathp, |
|
u_int *secondsp, int *confirmp, char **sk_providerp) |
{ |
{ |
Identity *id; |
|
int success = 0, confirm = 0; |
|
u_int seconds = 0, maxsign; |
|
char *fp, *comment = NULL, *ext_name = NULL, *sk_provider = NULL; |
|
char canonical_provider[PATH_MAX]; |
|
time_t death = 0; |
|
struct sshkey *k = NULL; |
|
u_char ctype; |
u_char ctype; |
int r = SSH_ERR_INTERNAL_ERROR; |
int r; |
|
u_int seconds, maxsign = 0; |
|
char *ext_name = NULL, *sk_provider = NULL; |
|
size_t pos; |
|
struct sshbuf *b = NULL; |
|
|
debug2_f("entering"); |
while (sshbuf_len(m)) { |
if ((r = sshkey_private_deserialize(e->request, &k)) != 0 || |
if ((r = sshbuf_get_u8(m, &ctype)) != 0) { |
k == NULL || |
|
(r = sshbuf_get_cstring(e->request, &comment, NULL)) != 0) { |
|
error_fr(r, "parse"); |
|
goto err; |
|
} |
|
while (sshbuf_len(e->request)) { |
|
if ((r = sshbuf_get_u8(e->request, &ctype)) != 0) { |
|
error_fr(r, "parse constraint type"); |
error_fr(r, "parse constraint type"); |
goto err; |
goto err; |
} |
} |
switch (ctype) { |
switch (ctype) { |
case SSH_AGENT_CONSTRAIN_LIFETIME: |
case SSH_AGENT_CONSTRAIN_LIFETIME: |
if ((r = sshbuf_get_u32(e->request, &seconds)) != 0) { |
if (*deathp != 0) { |
|
error_f("lifetime already set"); |
|
goto err; |
|
} |
|
if ((r = sshbuf_get_u32(m, &seconds)) != 0) { |
error_fr(r, "parse lifetime constraint"); |
error_fr(r, "parse lifetime constraint"); |
goto err; |
goto err; |
} |
} |
death = monotime() + seconds; |
*deathp = monotime() + seconds; |
|
*secondsp = seconds; |
break; |
break; |
case SSH_AGENT_CONSTRAIN_CONFIRM: |
case SSH_AGENT_CONSTRAIN_CONFIRM: |
confirm = 1; |
if (*confirmp != 0) { |
|
error_f("confirm already set"); |
|
goto err; |
|
} |
|
*confirmp = 1; |
break; |
break; |
case SSH_AGENT_CONSTRAIN_MAXSIGN: |
case SSH_AGENT_CONSTRAIN_MAXSIGN: |
if ((r = sshbuf_get_u32(e->request, &maxsign)) != 0) { |
if (k == NULL) { |
|
error_f("maxsign not valid here"); |
|
goto err; |
|
} |
|
if (maxsign != 0) { |
|
error_f("maxsign already set"); |
|
goto err; |
|
} |
|
if ((r = sshbuf_get_u32(m, &maxsign)) != 0) { |
error_fr(r, "parse maxsign constraint"); |
error_fr(r, "parse maxsign constraint"); |
goto err; |
goto err; |
} |
} |
|
|
} |
} |
break; |
break; |
case SSH_AGENT_CONSTRAIN_EXTENSION: |
case SSH_AGENT_CONSTRAIN_EXTENSION: |
if ((r = sshbuf_get_cstring(e->request, |
if ((r = sshbuf_get_cstring(m, &ext_name, NULL)) != 0) { |
&ext_name, NULL)) != 0) { |
|
error_fr(r, "parse constraint extension"); |
error_fr(r, "parse constraint extension"); |
goto err; |
goto err; |
} |
} |
debug_f("constraint ext %s", ext_name); |
debug_f("constraint ext %s", ext_name); |
if (strcmp(ext_name, "sk-provider@openssh.com") == 0) { |
if (strcmp(ext_name, "sk-provider@openssh.com") == 0) { |
if (sk_provider != NULL) { |
if (sk_providerp == NULL) { |
error("%s already set", ext_name); |
error_f("%s not valid here", ext_name); |
goto err; |
goto err; |
} |
} |
if ((r = sshbuf_get_cstring(e->request, |
if (*sk_providerp != NULL) { |
&sk_provider, NULL)) != 0) { |
error_f("%s already set", ext_name); |
|
goto err; |
|
} |
|
if ((r = sshbuf_get_cstring(m, |
|
sk_providerp, NULL)) != 0) { |
error_fr(r, "parse %s", ext_name); |
error_fr(r, "parse %s", ext_name); |
goto err; |
goto err; |
} |
} |
|
|
default: |
default: |
error_f("Unknown constraint %d", ctype); |
error_f("Unknown constraint %d", ctype); |
err: |
err: |
free(sk_provider); |
|
free(ext_name); |
free(ext_name); |
sshbuf_reset(e->request); |
sshbuf_free(b); |
free(comment); |
return -1; |
sshkey_free(k); |
|
goto send; |
|
} |
} |
} |
} |
|
/* success */ |
|
return 0; |
|
} |
|
|
|
static void |
|
process_add_identity(SocketEntry *e) |
|
{ |
|
Identity *id; |
|
int success = 0, confirm = 0; |
|
char *fp, *comment = NULL, *ext_name = NULL, *sk_provider = NULL; |
|
char canonical_provider[PATH_MAX]; |
|
time_t death = 0; |
|
u_int seconds = 0; |
|
struct sshkey *k = NULL; |
|
int r = SSH_ERR_INTERNAL_ERROR; |
|
|
|
debug2_f("entering"); |
|
if ((r = sshkey_private_deserialize(e->request, &k)) != 0 || |
|
k == NULL || |
|
(r = sshbuf_get_cstring(e->request, &comment, NULL)) != 0) { |
|
error_fr(r, "parse"); |
|
goto out; |
|
} |
|
if (parse_key_constraints(e->request, k, &death, &seconds, &confirm, |
|
&sk_provider) != 0) { |
|
error_f("failed to parse constraints"); |
|
sshbuf_reset(e->request); |
|
goto out; |
|
} |
|
|
if (sk_provider != NULL) { |
if (sk_provider != NULL) { |
if (!sshkey_is_sk(k)) { |
if (!sshkey_is_sk(k)) { |
error("Cannot add provider: %s is not an " |
error("Cannot add provider: %s is not an " |
"authenticator-hosted key", sshkey_type(k)); |
"authenticator-hosted key", sshkey_type(k)); |
free(sk_provider); |
goto out; |
goto send; |
|
} |
} |
if (strcasecmp(sk_provider, "internal") == 0) { |
if (strcasecmp(sk_provider, "internal") == 0) { |
debug_f("internal provider"); |
debug_f("internal provider"); |
|
|
verbose("failed provider \"%.100s\": " |
verbose("failed provider \"%.100s\": " |
"realpath: %s", sk_provider, |
"realpath: %s", sk_provider, |
strerror(errno)); |
strerror(errno)); |
free(sk_provider); |
goto out; |
goto send; |
|
} |
} |
free(sk_provider); |
free(sk_provider); |
sk_provider = xstrdup(canonical_provider); |
sk_provider = xstrdup(canonical_provider); |
|
|
allowed_providers, 0) != 1) { |
allowed_providers, 0) != 1) { |
error("Refusing add key: " |
error("Refusing add key: " |
"provider %s not allowed", sk_provider); |
"provider %s not allowed", sk_provider); |
free(sk_provider); |
goto out; |
goto send; |
|
} |
} |
} |
} |
} |
} |
if ((r = sshkey_shield_private(k)) != 0) { |
if ((r = sshkey_shield_private(k)) != 0) { |
error_fr(r, "shield private"); |
error_fr(r, "shield private"); |
goto err; |
goto out; |
} |
} |
|
|
success = 1; |
|
if (lifetime && !death) |
if (lifetime && !death) |
death = monotime() + lifetime; |
death = monotime() + lifetime; |
if ((id = lookup_identity(k)) == NULL) { |
if ((id = lookup_identity(k)) == NULL) { |
|
|
free(id->comment); |
free(id->comment); |
free(id->sk_provider); |
free(id->sk_provider); |
} |
} |
|
/* success */ |
id->key = k; |
id->key = k; |
id->comment = comment; |
id->comment = comment; |
id->death = death; |
id->death = death; |
|
|
SSH_FP_DEFAULT)) == NULL) |
SSH_FP_DEFAULT)) == NULL) |
fatal_f("sshkey_fingerprint failed"); |
fatal_f("sshkey_fingerprint failed"); |
debug_f("add %s %s \"%.100s\" (life: %u) (confirm: %u) " |
debug_f("add %s %s \"%.100s\" (life: %u) (confirm: %u) " |
"(provider: %s)", sshkey_ssh_name(k), fp, comment, |
"(provider: %s)", sshkey_ssh_name(k), fp, comment, seconds, |
seconds, confirm, sk_provider == NULL ? "none" : sk_provider); |
confirm, sk_provider == NULL ? "none" : sk_provider); |
free(fp); |
free(fp); |
send: |
/* transferred */ |
|
k = NULL; |
|
comment = NULL; |
|
sk_provider = NULL; |
|
success = 1; |
|
out: |
|
free(sk_provider); |
|
free(comment); |
|
sshkey_free(k); |
send_status(e, success); |
send_status(e, success); |
} |
} |
|
|
|
|
char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX]; |
char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX]; |
char **comments = NULL; |
char **comments = NULL; |
int r, i, count = 0, success = 0, confirm = 0; |
int r, i, count = 0, success = 0, confirm = 0; |
u_int seconds; |
u_int seconds = 0; |
time_t death = 0; |
time_t death = 0; |
u_char type; |
u_char type; |
struct sshkey **keys = NULL, *k; |
struct sshkey **keys = NULL, *k; |
|
|
error_fr(r, "parse"); |
error_fr(r, "parse"); |
goto send; |
goto send; |
} |
} |
|
if (parse_key_constraints(e->request, NULL, &death, &seconds, &confirm, |
while (sshbuf_len(e->request)) { |
NULL) != 0) { |
if ((r = sshbuf_get_u8(e->request, &type)) != 0) { |
error_f("failed to parse constraints"); |
error_fr(r, "parse type"); |
goto send; |
goto send; |
|
} |
|
switch (type) { |
|
case SSH_AGENT_CONSTRAIN_LIFETIME: |
|
if ((r = sshbuf_get_u32(e->request, &seconds)) != 0) { |
|
error_fr(r, "parse lifetime"); |
|
goto send; |
|
} |
|
death = monotime() + seconds; |
|
break; |
|
case SSH_AGENT_CONSTRAIN_CONFIRM: |
|
confirm = 1; |
|
break; |
|
default: |
|
error_f("Unknown constraint type %d", type); |
|
goto send; |
|
} |
|
} |
} |
if (realpath(provider, canonical_provider) == NULL) { |
if (realpath(provider, canonical_provider) == NULL) { |
verbose("failed PKCS#11 add of \"%.100s\": realpath: %s", |
verbose("failed PKCS#11 add of \"%.100s\": realpath: %s", |
|
|
idtab->nentries++; |
idtab->nentries++; |
success = 1; |
success = 1; |
} |
} |
|
/* XXX update constraints for existing keys */ |
sshkey_free(keys[i]); |
sshkey_free(keys[i]); |
free(comments[i]); |
free(comments[i]); |
} |
} |