version 1.330, 2020/10/16 02:37:12 |
version 1.331, 2020/10/18 11:32:02 |
|
|
if (lookup_key_in_hostkeys_by_type(hostkeys, |
if (lookup_key_in_hostkeys_by_type(hostkeys, |
sshkey_type_plain(sshkey_type_from_name(best)), |
sshkey_type_plain(sshkey_type_from_name(best)), |
sshkey_ecdsa_nid_from_name(best), NULL)) { |
sshkey_ecdsa_nid_from_name(best), NULL)) { |
debug3("%s: have matching best-preference key type %s, " |
debug3_f("have matching best-preference key type %s, " |
"using HostkeyAlgorithms verbatim", __func__, best); |
"using HostkeyAlgorithms verbatim", best); |
ret = xstrdup(options.hostkeyalgorithms); |
ret = xstrdup(options.hostkeyalgorithms); |
goto out; |
goto out; |
} |
} |
|
|
|
|
while ((alg = strsep(&avail, ",")) && *alg != '\0') { |
while ((alg = strsep(&avail, ",")) && *alg != '\0') { |
if ((ktype = sshkey_type_from_name(alg)) == KEY_UNSPEC) |
if ((ktype = sshkey_type_from_name(alg)) == KEY_UNSPEC) |
fatal("%s: unknown alg %s", __func__, alg); |
fatal_f("unknown alg %s", alg); |
/* |
/* |
* If we have a @cert-authority marker in known_hosts then |
* If we have a @cert-authority marker in known_hosts then |
* prefer all certificate algorithms. |
* prefer all certificate algorithms. |
|
|
xasprintf(&ret, "%s%s%s", first, |
xasprintf(&ret, "%s%s%s", first, |
(*first == '\0' || *last == '\0') ? "" : ",", last); |
(*first == '\0' || *last == '\0') ? "" : ",", last); |
if (*first != '\0') |
if (*first != '\0') |
debug3("%s: prefer hostkeyalgs: %s", __func__, first); |
debug3_f("prefer hostkeyalgs: %s", first); |
|
|
out: |
out: |
free(best); |
free(best); |
|
|
all_key = sshkey_alg_list(0, 0, 1, ','); |
all_key = sshkey_alg_list(0, 0, 1, ','); |
if (kex_assemble_names(&options.hostkeyalgorithms, |
if (kex_assemble_names(&options.hostkeyalgorithms, |
kex_default_pk_alg(), all_key) != 0) |
kex_default_pk_alg(), all_key) != 0) |
fatal("%s: kex_assemble_namelist", __func__); |
fatal_f("kex_assemble_namelist"); |
free(all_key); |
free(all_key); |
|
|
if ((s = kex_names_cat(options.kex_algorithms, "ext-info-c")) == NULL) |
if ((s = kex_names_cat(options.kex_algorithms, "ext-info-c")) == NULL) |
fatal("%s: kex_names_cat", __func__); |
fatal_f("kex_names_cat"); |
myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(s); |
myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(s); |
myproposal[PROPOSAL_ENC_ALGS_CTOS] = |
myproposal[PROPOSAL_ENC_ALGS_CTOS] = |
compat_cipher_proposal(options.ciphers); |
compat_cipher_proposal(options.ciphers); |
|
|
|
|
/* start key exchange */ |
/* start key exchange */ |
if ((r = kex_setup(ssh, myproposal)) != 0) |
if ((r = kex_setup(ssh, myproposal)) != 0) |
fatal("kex_setup: %s", ssh_err(r)); |
fatal_r(r, "kex_setup"); |
#ifdef WITH_OPENSSL |
#ifdef WITH_OPENSSL |
ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_client; |
ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_client; |
ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_client; |
ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_client; |
|
|
myproposal[PROPOSAL_KEX_ALGS] = |
myproposal[PROPOSAL_KEX_ALGS] = |
compat_kex_proposal(options.kex_algorithms); |
compat_kex_proposal(options.kex_algorithms); |
if ((r = kex_prop2buf(ssh->kex->my, myproposal)) != 0) |
if ((r = kex_prop2buf(ssh->kex->my, myproposal)) != 0) |
fatal("kex_prop2buf: %s", ssh_err(r)); |
fatal_r(r, "kex_prop2buf"); |
|
|
session_id2 = ssh->kex->session_id; |
session_id2 = ssh->kex->session_id; |
session_id2_len = ssh->kex->session_id_len; |
session_id2_len = ssh->kex->session_id_len; |
|
|
(r = sshpkt_put_cstring(ssh, "markus")) != 0 || |
(r = sshpkt_put_cstring(ssh, "markus")) != 0 || |
(r = sshpkt_send(ssh)) != 0 || |
(r = sshpkt_send(ssh)) != 0 || |
(r = ssh_packet_write_wait(ssh)) != 0) |
(r = ssh_packet_write_wait(ssh)) != 0) |
fatal("%s: %s", __func__, ssh_err(r)); |
fatal_fr(r, "send packet"); |
#endif |
#endif |
} |
} |
|
|
|
|
authctxt.agent_fd = -1; |
authctxt.agent_fd = -1; |
pubkey_prepare(&authctxt); |
pubkey_prepare(&authctxt); |
if (authctxt.method == NULL) { |
if (authctxt.method == NULL) { |
fatal("%s: internal error: cannot send userauth none request", |
fatal_f("internal error: cannot send userauth none request"); |
__func__); |
|
} |
} |
|
|
if ((r = sshpkt_start(ssh, SSH2_MSG_SERVICE_REQUEST)) != 0 || |
if ((r = sshpkt_start(ssh, SSH2_MSG_SERVICE_REQUEST)) != 0 || |
(r = sshpkt_put_cstring(ssh, "ssh-userauth")) != 0 || |
(r = sshpkt_put_cstring(ssh, "ssh-userauth")) != 0 || |
(r = sshpkt_send(ssh)) != 0) |
(r = sshpkt_send(ssh)) != 0) |
fatal("%s: %s", __func__, ssh_err(r)); |
fatal_fr(r, "send packet"); |
|
|
ssh->authctxt = &authctxt; |
ssh->authctxt = &authctxt; |
ssh_dispatch_init(ssh, &input_userauth_error); |
ssh_dispatch_init(ssh, &input_userauth_error); |
|
|
static int |
static int |
input_userauth_error(int type, u_int32_t seq, struct ssh *ssh) |
input_userauth_error(int type, u_int32_t seq, struct ssh *ssh) |
{ |
{ |
fatal("%s: bad message during authentication: type %d", __func__, type); |
fatal_f("bad message during authentication: type %d", type); |
return 0; |
return 0; |
} |
} |
|
|
|
|
size_t len; |
size_t len; |
int r; |
int r; |
|
|
debug3("%s", __func__); |
debug3_f("entering"); |
if ((r = sshpkt_get_cstring(ssh, &msg, &len)) != 0 || |
if ((r = sshpkt_get_cstring(ssh, &msg, &len)) != 0 || |
(r = sshpkt_get_cstring(ssh, NULL, NULL)) != 0) |
(r = sshpkt_get_cstring(ssh, NULL, NULL)) != 0) |
goto out; |
goto out; |
|
|
Authctxt *authctxt = ssh->authctxt; |
Authctxt *authctxt = ssh->authctxt; |
|
|
if (authctxt == NULL) |
if (authctxt == NULL) |
fatal("%s: no authentication context", __func__); |
fatal_f("no authentication context"); |
free(authctxt->authlist); |
free(authctxt->authlist); |
authctxt->authlist = NULL; |
authctxt->authlist = NULL; |
if (authctxt->method != NULL && authctxt->method->cleanup != NULL) |
if (authctxt->method != NULL && authctxt->method->cleanup != NULL) |
|
|
Authctxt *authctxt = ssh->authctxt; |
Authctxt *authctxt = ssh->authctxt; |
|
|
if (authctxt == NULL) |
if (authctxt == NULL) |
fatal("%s: no authentication context", __func__); |
fatal_f("no authentication context"); |
|
|
fatal("Unexpected authentication success during %s.", |
fatal("Unexpected authentication success during %s.", |
authctxt->method->name); |
authctxt->method->name); |
|
|
goto done; |
goto done; |
|
|
if ((pktype = sshkey_type_from_name(pkalg)) == KEY_UNSPEC) { |
if ((pktype = sshkey_type_from_name(pkalg)) == KEY_UNSPEC) { |
debug("%s: server sent unknown pkalg %s", __func__, pkalg); |
debug_f("server sent unknown pkalg %s", pkalg); |
goto done; |
goto done; |
} |
} |
if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { |
if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { |
debug("no key from blob. pkalg %s: %s", pkalg, ssh_err(r)); |
debug_r(r, "no key from blob. pkalg %s", pkalg); |
goto done; |
goto done; |
} |
} |
if (key->type != pktype) { |
if (key->type != pktype) { |
|
|
if (!found || id == NULL) { |
if (!found || id == NULL) { |
fp = sshkey_fingerprint(key, options.fingerprint_hash, |
fp = sshkey_fingerprint(key, options.fingerprint_hash, |
SSH_FP_DEFAULT); |
SSH_FP_DEFAULT); |
error("%s: server replied with unknown key: %s %s", __func__, |
error_f("server replied with unknown key: %s %s", |
sshkey_type(key), fp == NULL ? "<ERROR>" : fp); |
sshkey_type(key), fp == NULL ? "<ERROR>" : fp); |
goto done; |
goto done; |
} |
} |
|
|
(r = sshpkt_put_u8(ssh, mech->length)) != 0 || |
(r = sshpkt_put_u8(ssh, mech->length)) != 0 || |
(r = sshpkt_put(ssh, mech->elements, mech->length)) != 0 || |
(r = sshpkt_put(ssh, mech->elements, mech->length)) != 0 || |
(r = sshpkt_send(ssh)) != 0) |
(r = sshpkt_send(ssh)) != 0) |
fatal("%s: %s", __func__, ssh_err(r)); |
fatal_fr(r, "send packet"); |
|
|
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_RESPONSE, &input_gssapi_response); |
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_RESPONSE, &input_gssapi_response); |
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token); |
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token); |
|
|
(r = sshpkt_put_string(ssh, send_tok.value, |
(r = sshpkt_put_string(ssh, send_tok.value, |
send_tok.length)) != 0 || |
send_tok.length)) != 0 || |
(r = sshpkt_send(ssh)) != 0) |
(r = sshpkt_send(ssh)) != 0) |
fatal("%s: %s", __func__, ssh_err(r)); |
fatal_fr(r, "send %u packet", type); |
|
|
gss_release_buffer(&ms, &send_tok); |
gss_release_buffer(&ms, &send_tok); |
} |
} |
|
|
if ((r = sshpkt_start(ssh, |
if ((r = sshpkt_start(ssh, |
SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE)) != 0 || |
SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE)) != 0 || |
(r = sshpkt_send(ssh)) != 0) |
(r = sshpkt_send(ssh)) != 0) |
fatal("%s: %s", __func__, ssh_err(r)); |
fatal_fr(r, "send completion"); |
} else { |
} else { |
struct sshbuf *b; |
struct sshbuf *b; |
|
|
if ((b = sshbuf_new()) == NULL) |
if ((b = sshbuf_new()) == NULL) |
fatal("%s: sshbuf_new failed", __func__); |
fatal_f("sshbuf_new failed"); |
ssh_gssapi_buildmic(b, authctxt->server_user, |
ssh_gssapi_buildmic(b, authctxt->server_user, |
authctxt->service, "gssapi-with-mic"); |
authctxt->service, "gssapi-with-mic"); |
|
|
if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL) |
if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL) |
fatal("%s: sshbuf_mutable_ptr failed", __func__); |
fatal_f("sshbuf_mutable_ptr failed"); |
gssbuf.length = sshbuf_len(b); |
gssbuf.length = sshbuf_len(b); |
|
|
status = ssh_gssapi_sign(gssctxt, &gssbuf, &mic); |
status = ssh_gssapi_sign(gssctxt, &gssbuf, &mic); |
|
|
(r = sshpkt_put_string(ssh, mic.value, |
(r = sshpkt_put_string(ssh, mic.value, |
mic.length)) != 0 || |
mic.length)) != 0 || |
(r = sshpkt_send(ssh)) != 0) |
(r = sshpkt_send(ssh)) != 0) |
fatal("%s: %s", __func__, ssh_err(r)); |
fatal_fr(r, "send MIC"); |
} |
} |
|
|
sshbuf_free(b); |
sshbuf_free(b); |
|
|
(r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || |
(r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || |
(r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || |
(r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || |
(r = sshpkt_send(ssh)) != 0) |
(r = sshpkt_send(ssh)) != 0) |
fatal("%s: %s", __func__, ssh_err(r)); |
fatal_fr(r, "send packet"); |
return 1; |
return 1; |
} |
} |
|
|
|
|
(r = sshpkt_put_cstring(ssh, password)) != 0 || |
(r = sshpkt_put_cstring(ssh, password)) != 0 || |
(r = sshpkt_add_padding(ssh, 64)) != 0 || |
(r = sshpkt_add_padding(ssh, 64)) != 0 || |
(r = sshpkt_send(ssh)) != 0) |
(r = sshpkt_send(ssh)) != 0) |
fatal("%s: %s", __func__, ssh_err(r)); |
fatal_fr(r, "send packet"); |
|
|
free(prompt); |
free(prompt); |
if (password != NULL) |
if (password != NULL) |
|
|
if ((prv = load_identity_file(id)) == NULL) |
if ((prv = load_identity_file(id)) == NULL) |
return SSH_ERR_KEY_NOT_FOUND; |
return SSH_ERR_KEY_NOT_FOUND; |
if (id->key != NULL && !sshkey_equal_public(prv, id->key)) { |
if (id->key != NULL && !sshkey_equal_public(prv, id->key)) { |
error("%s: private key %s contents do not match public", |
error_f("private key %s contents do not match public", |
__func__, id->filename); |
id->filename); |
r = SSH_ERR_KEY_NOT_FOUND; |
r = SSH_ERR_KEY_NOT_FOUND; |
goto out; |
goto out; |
} |
} |
|
|
if ((fp = sshkey_fingerprint(sign_key, |
if ((fp = sshkey_fingerprint(sign_key, |
options.fingerprint_hash, |
options.fingerprint_hash, |
SSH_FP_DEFAULT)) == NULL) |
SSH_FP_DEFAULT)) == NULL) |
fatal("%s: fingerprint", __func__); |
fatal_f("fingerprint failed"); |
notifier = notify_start(options.batch_mode, |
notifier = notify_start(options.batch_mode, |
"Confirm user presence for key %s %s", |
"Confirm user presence for key %s %s", |
sshkey_type(sign_key), fp); |
sshkey_type(sign_key), fp); |
|
|
} |
} |
if ((r = sshkey_sign(sign_key, sigp, lenp, data, datalen, |
if ((r = sshkey_sign(sign_key, sigp, lenp, data, datalen, |
alg, options.sk_provider, pin, compat)) != 0) { |
alg, options.sk_provider, pin, compat)) != 0) { |
debug("%s: sshkey_sign: %s", __func__, ssh_err(r)); |
debug_fr(r, "sshkey_sign"); |
goto out; |
goto out; |
} |
} |
/* |
/* |
|
|
* so check what we get back. |
* so check what we get back. |
*/ |
*/ |
if ((r = sshkey_check_sigtype(*sigp, *lenp, alg)) != 0) { |
if ((r = sshkey_check_sigtype(*sigp, *lenp, alg)) != 0) { |
debug("%s: sshkey_check_sigtype: %s", __func__, ssh_err(r)); |
debug_fr(r, "sshkey_check_sigtype"); |
goto out; |
goto out; |
} |
} |
/* success */ |
/* success */ |
|
|
SSH_FP_DEFAULT)) == NULL) |
SSH_FP_DEFAULT)) == NULL) |
return 0; |
return 0; |
|
|
debug3("%s: %s %s", __func__, sshkey_type(id->key), fp); |
debug3_f("%s %s", sshkey_type(id->key), fp); |
|
|
/* |
/* |
* If the key is an certificate, try to find a matching private key |
* If the key is an certificate, try to find a matching private key |
|
|
} |
} |
} |
} |
if (sign_id != NULL) { |
if (sign_id != NULL) { |
debug2("%s: using private key \"%s\"%s for " |
debug2_f("using private key \"%s\"%s for " |
"certificate", __func__, id->filename, |
"certificate", id->filename, |
id->agent_fd != -1 ? " from agent" : ""); |
id->agent_fd != -1 ? " from agent" : ""); |
} else { |
} else { |
debug("%s: no separate private key for certificate " |
debug_f("no separate private key for certificate " |
"\"%s\"", __func__, id->filename); |
"\"%s\"", id->filename); |
} |
} |
} |
} |
|
|
|
|
signature = NULL; |
signature = NULL; |
if ((alg = key_sig_algorithm(fallback_sigtype ? NULL : ssh, |
if ((alg = key_sig_algorithm(fallback_sigtype ? NULL : ssh, |
id->key)) == NULL) { |
id->key)) == NULL) { |
error("%s: no mutual signature supported", __func__); |
error_f("no mutual signature supported"); |
goto out; |
goto out; |
} |
} |
debug3("%s: signing using %s %s", __func__, alg, fp); |
debug3_f("signing using %s %s", alg, fp); |
|
|
sshbuf_free(b); |
sshbuf_free(b); |
if ((b = sshbuf_new()) == NULL) |
if ((b = sshbuf_new()) == NULL) |
fatal("%s: sshbuf_new failed", __func__); |
fatal_f("sshbuf_new failed"); |
if (datafellows & SSH_OLD_SESSIONID) { |
if (datafellows & SSH_OLD_SESSIONID) { |
if ((r = sshbuf_put(b, session_id2, |
if ((r = sshbuf_put(b, session_id2, |
session_id2_len)) != 0) { |
session_id2_len)) != 0) |
fatal("%s: sshbuf_put: %s", |
fatal_fr(r, "sshbuf_put"); |
__func__, ssh_err(r)); |
|
} |
|
} else { |
} else { |
if ((r = sshbuf_put_string(b, session_id2, |
if ((r = sshbuf_put_string(b, session_id2, |
session_id2_len)) != 0) { |
session_id2_len)) != 0) |
fatal("%s: sshbuf_put_string: %s", |
fatal_fr(r, "sshbuf_put_string"); |
__func__, ssh_err(r)); |
|
} |
|
} |
} |
skip = sshbuf_len(b); |
skip = sshbuf_len(b); |
if ((r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || |
if ((r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || |
|
|
(r = sshbuf_put_u8(b, 1)) != 0 || |
(r = sshbuf_put_u8(b, 1)) != 0 || |
(r = sshbuf_put_cstring(b, alg)) != 0 || |
(r = sshbuf_put_cstring(b, alg)) != 0 || |
(r = sshkey_puts(id->key, b)) != 0) { |
(r = sshkey_puts(id->key, b)) != 0) { |
fatal("%s: assemble signed data: %s", |
fatal_fr(r, "assemble signed data"); |
__func__, ssh_err(r)); |
|
} |
} |
|
|
/* generate signature */ |
/* generate signature */ |
|
|
loc, sshkey_type(id->key), fp); |
loc, sshkey_type(id->key), fp); |
continue; |
continue; |
} |
} |
error("%s: signing failed for %s \"%s\"%s: %s", __func__, |
error_fr(r, "signing failed for %s \"%s\"%s", |
sshkey_type(sign_id->key), sign_id->filename, |
sshkey_type(sign_id->key), sign_id->filename, |
id->agent_fd != -1 ? " from agent" : "", ssh_err(r)); |
id->agent_fd != -1 ? " from agent" : ""); |
goto out; |
goto out; |
} |
} |
if (slen == 0 || signature == NULL) /* shouldn't happen */ |
if (slen == 0 || signature == NULL) /* shouldn't happen */ |
fatal("%s: no signature", __func__); |
fatal_f("no signature"); |
|
|
/* append signature */ |
/* append signature */ |
if ((r = sshbuf_put_string(b, signature, slen)) != 0) |
if ((r = sshbuf_put_string(b, signature, slen)) != 0) |
fatal("%s: append signature: %s", __func__, ssh_err(r)); |
fatal_fr(r, "append signature"); |
|
|
#ifdef DEBUG_PK |
#ifdef DEBUG_PK |
sshbuf_dump(b, stderr); |
sshbuf_dump(b, stderr); |
#endif |
#endif |
/* skip session id and packet type */ |
/* skip session id and packet type */ |
if ((r = sshbuf_consume(b, skip + 1)) != 0) |
if ((r = sshbuf_consume(b, skip + 1)) != 0) |
fatal("%s: consume: %s", __func__, ssh_err(r)); |
fatal_fr(r, "consume"); |
|
|
/* put remaining data from buffer into packet */ |
/* put remaining data from buffer into packet */ |
if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || |
if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || |
(r = sshpkt_putb(ssh, b)) != 0 || |
(r = sshpkt_putb(ssh, b)) != 0 || |
(r = sshpkt_send(ssh)) != 0) |
(r = sshpkt_send(ssh)) != 0) |
fatal("%s: enqueue request: %s", __func__, ssh_err(r)); |
fatal_fr(r, "enqueue request"); |
|
|
/* success */ |
/* success */ |
sent = 1; |
sent = 1; |
|
|
int sent = 0, r; |
int sent = 0, r; |
|
|
if ((alg = key_sig_algorithm(ssh, id->key)) == NULL) { |
if ((alg = key_sig_algorithm(ssh, id->key)) == NULL) { |
debug("%s: no mutual signature algorithm", __func__); |
debug_f("no mutual signature algorithm"); |
goto out; |
goto out; |
} |
} |
|
|
if ((r = sshkey_to_blob(id->key, &blob, &bloblen)) != 0) { |
if ((r = sshkey_to_blob(id->key, &blob, &bloblen)) != 0) { |
/* we cannot handle this key */ |
/* we cannot handle this key */ |
debug3("%s: cannot handle key", __func__); |
debug3_f("cannot handle key"); |
goto out; |
goto out; |
} |
} |
/* register callback for USERAUTH_PK_OK message */ |
/* register callback for USERAUTH_PK_OK message */ |
|
|
(r = sshpkt_put_cstring(ssh, alg)) != 0 || |
(r = sshpkt_put_cstring(ssh, alg)) != 0 || |
(r = sshpkt_put_string(ssh, blob, bloblen)) != 0 || |
(r = sshpkt_put_string(ssh, blob, bloblen)) != 0 || |
(r = sshpkt_send(ssh)) != 0) |
(r = sshpkt_send(ssh)) != 0) |
fatal("%s: %s", __func__, ssh_err(r)); |
fatal_fr(r, "send packet"); |
sent = 1; |
sent = 1; |
|
|
out: |
out: |
|
|
break; |
break; |
case SSH_ERR_SYSTEM_ERROR: |
case SSH_ERR_SYSTEM_ERROR: |
if (errno == ENOENT) { |
if (errno == ENOENT) { |
debug2("Load key \"%s\": %s", |
debug2_r(r, "Load key \"%s\"", id->filename); |
id->filename, ssh_err(r)); |
|
quit = 1; |
quit = 1; |
break; |
break; |
} |
} |
/* FALLTHROUGH */ |
/* FALLTHROUGH */ |
default: |
default: |
error("Load key \"%s\": %s", id->filename, ssh_err(r)); |
error_r(r, "Load key \"%s\"", id->filename); |
quit = 1; |
quit = 1; |
break; |
break; |
} |
} |
|
|
key = options.identity_keys[i]; |
key = options.identity_keys[i]; |
if (key && key->cert && |
if (key && key->cert && |
key->cert->type != SSH2_CERT_TYPE_USER) { |
key->cert->type != SSH2_CERT_TYPE_USER) { |
debug("%s: ignoring certificate %s: not a user " |
debug_f("ignoring certificate %s: not a user " |
"certificate", __func__, |
"certificate", options.identity_files[i]); |
options.identity_files[i]); |
|
continue; |
continue; |
} |
} |
if (key && sshkey_is_sk(key) && options.sk_provider == NULL) { |
if (key && sshkey_is_sk(key) && options.sk_provider == NULL) { |
debug("%s: ignoring authenticator-hosted key %s as no " |
debug_f("ignoring authenticator-hosted key %s as no " |
"SecurityKeyProvider has been specified", |
"SecurityKeyProvider has been specified", |
__func__, options.identity_files[i]); |
options.identity_files[i]); |
continue; |
continue; |
} |
} |
options.identity_keys[i] = NULL; |
options.identity_keys[i] = NULL; |
|
|
key = options.certificates[i]; |
key = options.certificates[i]; |
if (!sshkey_is_cert(key) || key->cert == NULL || |
if (!sshkey_is_cert(key) || key->cert == NULL || |
key->cert->type != SSH2_CERT_TYPE_USER) { |
key->cert->type != SSH2_CERT_TYPE_USER) { |
debug("%s: ignoring certificate %s: not a user " |
debug_f("ignoring certificate %s: not a user " |
"certificate", __func__, |
"certificate", options.identity_files[i]); |
options.identity_files[i]); |
|
continue; |
continue; |
} |
} |
if (key && sshkey_is_sk(key) && options.sk_provider == NULL) { |
if (key && sshkey_is_sk(key) && options.sk_provider == NULL) { |
debug("%s: ignoring authenticator-hosted key " |
debug_f("ignoring authenticator-hosted key " |
"certificate %s as no " |
"certificate %s as no " |
"SecurityKeyProvider has been specified", |
"SecurityKeyProvider has been specified", |
__func__, options.identity_files[i]); |
options.identity_files[i]); |
continue; |
continue; |
} |
} |
id = xcalloc(1, sizeof(*id)); |
id = xcalloc(1, sizeof(*id)); |
|
|
/* list of keys supported by the agent */ |
/* list of keys supported by the agent */ |
if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) { |
if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) { |
if (r != SSH_ERR_AGENT_NOT_PRESENT) |
if (r != SSH_ERR_AGENT_NOT_PRESENT) |
debug("%s: ssh_get_authentication_socket: %s", |
debug_fr(r, "ssh_get_authentication_socket"); |
__func__, ssh_err(r)); |
|
} else if ((r = ssh_fetch_identitylist(agent_fd, &idlist)) != 0) { |
} else if ((r = ssh_fetch_identitylist(agent_fd, &idlist)) != 0) { |
if (r != SSH_ERR_AGENT_NO_IDENTITIES) |
if (r != SSH_ERR_AGENT_NO_IDENTITIES) |
debug("%s: ssh_fetch_identitylist: %s", |
debug_fr(r, "ssh_fetch_identitylist"); |
__func__, ssh_err(r)); |
|
close(agent_fd); |
close(agent_fd); |
} else { |
} else { |
for (j = 0; j < idlist->nkeys; j++) { |
for (j = 0; j < idlist->nkeys; j++) { |
|
|
debug("Will attempt key: %s", ident); |
debug("Will attempt key: %s", ident); |
free(ident); |
free(ident); |
} |
} |
debug2("%s: done", __func__); |
debug2_f("done"); |
} |
} |
|
|
static void |
static void |
|
|
(r = sshpkt_put_cstring(ssh, options.kbd_interactive_devices ? |
(r = sshpkt_put_cstring(ssh, options.kbd_interactive_devices ? |
options.kbd_interactive_devices : "")) != 0 || |
options.kbd_interactive_devices : "")) != 0 || |
(r = sshpkt_send(ssh)) != 0) |
(r = sshpkt_send(ssh)) != 0) |
fatal("%s: %s", __func__, ssh_err(r)); |
fatal_fr(r, "send packet"); |
|
|
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req); |
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req); |
return 1; |
return 1; |
|
|
*lenp = 0; |
*lenp = 0; |
|
|
if (stat(_PATH_SSH_KEY_SIGN, &st) == -1) { |
if (stat(_PATH_SSH_KEY_SIGN, &st) == -1) { |
error("%s: not installed: %s", __func__, strerror(errno)); |
error_f("not installed: %s", strerror(errno)); |
return -1; |
return -1; |
} |
} |
if (fflush(stdout) != 0) { |
if (fflush(stdout) != 0) { |
error("%s: fflush: %s", __func__, strerror(errno)); |
error_f("fflush: %s", strerror(errno)); |
return -1; |
return -1; |
} |
} |
if (pipe(to) == -1) { |
if (pipe(to) == -1) { |
error("%s: pipe: %s", __func__, strerror(errno)); |
error_f("pipe: %s", strerror(errno)); |
return -1; |
return -1; |
} |
} |
if (pipe(from) == -1) { |
if (pipe(from) == -1) { |
error("%s: pipe: %s", __func__, strerror(errno)); |
error_f("pipe: %s", strerror(errno)); |
return -1; |
return -1; |
} |
} |
if ((pid = fork()) == -1) { |
if ((pid = fork()) == -1) { |
error("%s: fork: %s", __func__, strerror(errno)); |
error_f("fork: %s", strerror(errno)); |
return -1; |
return -1; |
} |
} |
osigchld = ssh_signal(SIGCHLD, SIG_DFL); |
osigchld = ssh_signal(SIGCHLD, SIG_DFL); |
if (pid == 0) { |
if (pid == 0) { |
close(from[0]); |
close(from[0]); |
if (dup2(from[1], STDOUT_FILENO) == -1) |
if (dup2(from[1], STDOUT_FILENO) == -1) |
fatal("%s: dup2: %s", __func__, strerror(errno)); |
fatal_f("dup2: %s", strerror(errno)); |
close(to[1]); |
close(to[1]); |
if (dup2(to[0], STDIN_FILENO) == -1) |
if (dup2(to[0], STDIN_FILENO) == -1) |
fatal("%s: dup2: %s", __func__, strerror(errno)); |
fatal_f("dup2: %s", strerror(errno)); |
close(from[1]); |
close(from[1]); |
close(to[0]); |
close(to[0]); |
|
|
if (dup2(sock, STDERR_FILENO + 1) == -1) |
if (dup2(sock, STDERR_FILENO + 1) == -1) |
fatal("%s: dup2: %s", __func__, strerror(errno)); |
fatal_f("dup2: %s", strerror(errno)); |
sock = STDERR_FILENO + 1; |
sock = STDERR_FILENO + 1; |
fcntl(sock, F_SETFD, 0); /* keep the socket on exec */ |
fcntl(sock, F_SETFD, 0); /* keep the socket on exec */ |
closefrom(sock + 1); |
closefrom(sock + 1); |
|
|
debug3("%s: [child] pid=%ld, exec %s", |
debug3_f("[child] pid=%ld, exec %s", |
__func__, (long)getpid(), _PATH_SSH_KEY_SIGN); |
(long)getpid(), _PATH_SSH_KEY_SIGN); |
execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *)NULL); |
execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *)NULL); |
fatal("%s: exec(%s): %s", __func__, _PATH_SSH_KEY_SIGN, |
fatal_f("exec(%s): %s", _PATH_SSH_KEY_SIGN, |
strerror(errno)); |
strerror(errno)); |
} |
} |
close(from[1]); |
close(from[1]); |
|
|
sock = STDERR_FILENO + 1; |
sock = STDERR_FILENO + 1; |
|
|
if ((b = sshbuf_new()) == NULL) |
if ((b = sshbuf_new()) == NULL) |
fatal("%s: sshbuf_new failed", __func__); |
fatal_f("sshbuf_new failed"); |
/* send # of sock, data to be signed */ |
/* send # of sock, data to be signed */ |
if ((r = sshbuf_put_u32(b, sock)) != 0 || |
if ((r = sshbuf_put_u32(b, sock)) != 0 || |
(r = sshbuf_put_string(b, data, datalen)) != 0) |
(r = sshbuf_put_string(b, data, datalen)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "buffer error"); |
if (ssh_msg_send(to[1], version, b) == -1) |
if (ssh_msg_send(to[1], version, b) == -1) |
fatal("%s: couldn't send request", __func__); |
fatal_f("couldn't send request"); |
sshbuf_reset(b); |
sshbuf_reset(b); |
r = ssh_msg_recv(from[0], b); |
r = ssh_msg_recv(from[0], b); |
close(from[0]); |
close(from[0]); |
close(to[1]); |
close(to[1]); |
if (r < 0) { |
if (r < 0) { |
error("%s: no reply", __func__); |
error_f("no reply"); |
goto fail; |
goto fail; |
} |
} |
|
|
errno = 0; |
errno = 0; |
while (waitpid(pid, &status, 0) == -1) { |
while (waitpid(pid, &status, 0) == -1) { |
if (errno != EINTR) { |
if (errno != EINTR) { |
error("%s: waitpid %ld: %s", |
error_f("waitpid %ld: %s", (long)pid, strerror(errno)); |
__func__, (long)pid, strerror(errno)); |
|
goto fail; |
goto fail; |
} |
} |
} |
} |
if (!WIFEXITED(status)) { |
if (!WIFEXITED(status)) { |
error("%s: exited abnormally", __func__); |
error_f("exited abnormally"); |
goto fail; |
goto fail; |
} |
} |
if (WEXITSTATUS(status) != 0) { |
if (WEXITSTATUS(status) != 0) { |
error("%s: exited with status %d", |
error_f("exited with status %d", WEXITSTATUS(status)); |
__func__, WEXITSTATUS(status)); |
|
goto fail; |
goto fail; |
} |
} |
if ((r = sshbuf_get_u8(b, &rversion)) != 0) { |
if ((r = sshbuf_get_u8(b, &rversion)) != 0) { |
error("%s: buffer error: %s", __func__, ssh_err(r)); |
error_fr(r, "buffer error"); |
goto fail; |
goto fail; |
} |
} |
if (rversion != version) { |
if (rversion != version) { |
error("%s: bad version", __func__); |
error_f("bad version"); |
goto fail; |
goto fail; |
} |
} |
if ((r = sshbuf_get_string(b, sigp, lenp)) != 0) { |
if ((r = sshbuf_get_string(b, sigp, lenp)) != 0) { |
error("%s: buffer error: %s", __func__, ssh_err(r)); |
error_fr(r, "buffer error"); |
fail: |
fail: |
ssh_signal(SIGCHLD, osigchld); |
ssh_signal(SIGCHLD, osigchld); |
sshbuf_free(b); |
sshbuf_free(b); |
|
|
if (authctxt->active_ktype == NULL || |
if (authctxt->active_ktype == NULL || |
*authctxt->active_ktype == '\0') |
*authctxt->active_ktype == '\0') |
break; |
break; |
debug3("%s: trying key type %s", __func__, |
debug3_f("trying key type %s", authctxt->active_ktype); |
authctxt->active_ktype); |
|
|
|
/* check for a useful key */ |
/* check for a useful key */ |
private = NULL; |
private = NULL; |
|
|
|
|
if ((fp = sshkey_fingerprint(private, options.fingerprint_hash, |
if ((fp = sshkey_fingerprint(private, options.fingerprint_hash, |
SSH_FP_DEFAULT)) == NULL) { |
SSH_FP_DEFAULT)) == NULL) { |
error("%s: sshkey_fingerprint failed", __func__); |
error_f("sshkey_fingerprint failed"); |
goto out; |
goto out; |
} |
} |
debug("%s: trying hostkey %s %s", |
debug_f("trying hostkey %s %s", sshkey_ssh_name(private), fp); |
__func__, sshkey_ssh_name(private), fp); |
|
|
|
/* figure out a name for the client host */ |
/* figure out a name for the client host */ |
lname = get_local_name(ssh_packet_get_connection_in(ssh)); |
lname = get_local_name(ssh_packet_get_connection_in(ssh)); |
if (lname == NULL) { |
if (lname == NULL) { |
error("%s: cannot get local ipaddr/name", __func__); |
error_f("cannot get local ipaddr/name"); |
goto out; |
goto out; |
} |
} |
|
|
/* XXX sshbuf_put_stringf? */ |
/* XXX sshbuf_put_stringf? */ |
xasprintf(&chost, "%s.", lname); |
xasprintf(&chost, "%s.", lname); |
debug2("%s: chost %s", __func__, chost); |
debug2_f("chost %s", chost); |
|
|
/* construct data */ |
/* construct data */ |
if ((b = sshbuf_new()) == NULL) { |
if ((b = sshbuf_new()) == NULL) { |
error("%s: sshbuf_new failed", __func__); |
error_f("sshbuf_new failed"); |
goto out; |
goto out; |
} |
} |
if ((r = sshkey_to_blob(private, &keyblob, &keylen)) != 0) { |
if ((r = sshkey_to_blob(private, &keyblob, &keylen)) != 0) { |
error("%s: sshkey_to_blob: %s", __func__, ssh_err(r)); |
error_fr(r, "sshkey_to_blob"); |
goto out; |
goto out; |
} |
} |
if ((r = sshbuf_put_string(b, session_id2, session_id2_len)) != 0 || |
if ((r = sshbuf_put_string(b, session_id2, session_id2_len)) != 0 || |
|
|
(r = sshbuf_put_string(b, keyblob, keylen)) != 0 || |
(r = sshbuf_put_string(b, keyblob, keylen)) != 0 || |
(r = sshbuf_put_cstring(b, chost)) != 0 || |
(r = sshbuf_put_cstring(b, chost)) != 0 || |
(r = sshbuf_put_cstring(b, authctxt->local_user)) != 0) { |
(r = sshbuf_put_cstring(b, authctxt->local_user)) != 0) { |
error("%s: buffer error: %s", __func__, ssh_err(r)); |
error_fr(r, "buffer error"); |
goto out; |
goto out; |
} |
} |
|
|
|
|
(r = sshpkt_put_cstring(ssh, authctxt->local_user)) != 0 || |
(r = sshpkt_put_cstring(ssh, authctxt->local_user)) != 0 || |
(r = sshpkt_put_string(ssh, sig, siglen)) != 0 || |
(r = sshpkt_put_string(ssh, sig, siglen)) != 0 || |
(r = sshpkt_send(ssh)) != 0) { |
(r = sshpkt_send(ssh)) != 0) { |
error("%s: packet error: %s", __func__, ssh_err(r)); |
error_fr(r, "packet error"); |
goto out; |
goto out; |
} |
} |
success = 1; |
success = 1; |
|
|
int r; |
int r; |
|
|
if ((b = sshbuf_new()) == NULL) |
if ((b = sshbuf_new()) == NULL) |
fatal("%s: sshbuf_new failed", __func__); |
fatal_f("sshbuf_new failed"); |
for (method = authmethods; method->name != NULL; method++) { |
for (method = authmethods; method->name != NULL; method++) { |
if (authmethod_is_enabled(method)) { |
if (authmethod_is_enabled(method)) { |
if ((r = sshbuf_putf(b, "%s%s", |
if ((r = sshbuf_putf(b, "%s%s", |
sshbuf_len(b) ? "," : "", method->name)) != 0) |
sshbuf_len(b) ? "," : "", method->name)) != 0) |
fatal("%s: buffer error: %s", |
fatal_fr(r, "buffer error"); |
__func__, ssh_err(r)); |
|
} |
} |
} |
} |
if ((list = sshbuf_dup_string(b)) == NULL) |
if ((list = sshbuf_dup_string(b)) == NULL) |
fatal("%s: sshbuf_dup_string failed", __func__); |
fatal_f("sshbuf_dup_string failed"); |
sshbuf_free(b); |
sshbuf_free(b); |
return list; |
return list; |
} |
} |