version 1.216, 2020/10/18 11:21:59 |
version 1.217, 2020/10/18 11:32:01 |
|
|
if (authenticated && |
if (authenticated && |
!auth2_update_methods_lists(authctxt, |
!auth2_update_methods_lists(authctxt, |
auth_method, auth_submethod)) { |
auth_method, auth_submethod)) { |
debug3("%s: method %s: partial", __func__, |
debug3_f("method %s: partial", auth_method); |
auth_method); |
|
authenticated = 0; |
authenticated = 0; |
partial = 1; |
partial = 1; |
} |
} |
|
|
|
|
if (authenticated) { |
if (authenticated) { |
if (!(ent->flags & MON_AUTHDECIDE)) |
if (!(ent->flags & MON_AUTHDECIDE)) |
fatal("%s: unexpected authentication from %d", |
fatal_f("unexpected authentication from %d", |
__func__, ent->type); |
ent->type); |
if (authctxt->pw->pw_uid == 0 && |
if (authctxt->pw->pw_uid == 0 && |
!auth_root_allowed(ssh, auth_method)) |
!auth_root_allowed(ssh, auth_method)) |
authenticated = 0; |
authenticated = 0; |
|
|
} |
} |
|
|
if (!authctxt->valid) |
if (!authctxt->valid) |
fatal("%s: authenticated invalid user", __func__); |
fatal_f("authenticated invalid user"); |
if (strcmp(auth_method, "unknown") == 0) |
if (strcmp(auth_method, "unknown") == 0) |
fatal("%s: authentication method name unknown", __func__); |
fatal_f("authentication method name unknown"); |
|
|
debug("%s: %s has been authenticated by privileged process", |
debug_f("user %s authenticated by privileged process", authctxt->user); |
__func__, authctxt->user); |
|
ssh->authctxt = NULL; |
ssh->authctxt = NULL; |
ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user); |
ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user); |
|
|
|
|
int r; |
int r; |
|
|
if ((logmsg = sshbuf_new()) == NULL) |
if ((logmsg = sshbuf_new()) == NULL) |
fatal("%s: sshbuf_new", __func__); |
fatal_f("sshbuf_new"); |
|
|
/* Read length */ |
/* Read length */ |
if ((r = sshbuf_reserve(logmsg, 4, &p)) != 0) |
if ((r = sshbuf_reserve(logmsg, 4, &p)) != 0) |
fatal("%s: reserve: %s", __func__, ssh_err(r)); |
fatal_fr(r, "reserve len"); |
if (atomicio(read, pmonitor->m_log_recvfd, p, 4) != 4) { |
if (atomicio(read, pmonitor->m_log_recvfd, p, 4) != 4) { |
if (errno == EPIPE) { |
if (errno == EPIPE) { |
sshbuf_free(logmsg); |
sshbuf_free(logmsg); |
debug("%s: child log fd closed", __func__); |
debug_f("child log fd closed"); |
close(pmonitor->m_log_recvfd); |
close(pmonitor->m_log_recvfd); |
pmonitor->m_log_recvfd = -1; |
pmonitor->m_log_recvfd = -1; |
return -1; |
return -1; |
} |
} |
fatal("%s: log fd read: %s", __func__, strerror(errno)); |
fatal_f("log fd read: %s", strerror(errno)); |
} |
} |
if ((r = sshbuf_get_u32(logmsg, &len)) != 0) |
if ((r = sshbuf_get_u32(logmsg, &len)) != 0) |
fatal("%s: get len: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse len"); |
if (len <= 4 || len > 8192) |
if (len <= 4 || len > 8192) |
fatal("%s: invalid log message length %u", __func__, len); |
fatal_f("invalid log message length %u", len); |
|
|
/* Read severity, message */ |
/* Read severity, message */ |
sshbuf_reset(logmsg); |
sshbuf_reset(logmsg); |
if ((r = sshbuf_reserve(logmsg, len, &p)) != 0) |
if ((r = sshbuf_reserve(logmsg, len, &p)) != 0) |
fatal("%s: reserve: %s", __func__, ssh_err(r)); |
fatal_fr(r, "reserve msg"); |
if (atomicio(read, pmonitor->m_log_recvfd, p, len) != len) |
if (atomicio(read, pmonitor->m_log_recvfd, p, len) != len) |
fatal("%s: log fd read: %s", __func__, strerror(errno)); |
fatal_f("log fd read: %s", strerror(errno)); |
if ((r = sshbuf_get_cstring(logmsg, &file, NULL)) != 0 || |
if ((r = sshbuf_get_cstring(logmsg, &file, NULL)) != 0 || |
(r = sshbuf_get_cstring(logmsg, &func, NULL)) != 0 || |
(r = sshbuf_get_cstring(logmsg, &func, NULL)) != 0 || |
(r = sshbuf_get_u32(logmsg, &line)) != 0 || |
(r = sshbuf_get_u32(logmsg, &line)) != 0 || |
(r = sshbuf_get_u32(logmsg, &level)) != 0 || |
(r = sshbuf_get_u32(logmsg, &level)) != 0 || |
(r = sshbuf_get_cstring(logmsg, &msg, NULL)) != 0) |
(r = sshbuf_get_cstring(logmsg, &msg, NULL)) != 0) |
fatal("%s: decode: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse"); |
|
|
/* Log it */ |
/* Log it */ |
if (log_level_name(level) == NULL) |
if (log_level_name(level) == NULL) |
|
|
if (poll(pfd, pfd[1].fd == -1 ? 1 : 2, -1) == -1) { |
if (poll(pfd, pfd[1].fd == -1 ? 1 : 2, -1) == -1) { |
if (errno == EINTR || errno == EAGAIN) |
if (errno == EINTR || errno == EAGAIN) |
continue; |
continue; |
fatal("%s: poll: %s", __func__, strerror(errno)); |
fatal_f("poll: %s", strerror(errno)); |
} |
} |
if (pfd[1].revents) { |
if (pfd[1].revents) { |
/* |
/* |
|
|
} |
} |
|
|
if ((m = sshbuf_new()) == NULL) |
if ((m = sshbuf_new()) == NULL) |
fatal("%s: sshbuf_new", __func__); |
fatal_f("sshbuf_new"); |
|
|
mm_request_receive(pmonitor->m_sendfd, m); |
mm_request_receive(pmonitor->m_sendfd, m); |
if ((r = sshbuf_get_u8(m, &type)) != 0) |
if ((r = sshbuf_get_u8(m, &type)) != 0) |
fatal("%s: decode: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse type"); |
|
|
debug3("%s: checking request %d", __func__, type); |
debug3_f("checking request %d", type); |
|
|
while (ent->f != NULL) { |
while (ent->f != NULL) { |
if (ent->type == type) |
if (ent->type == type) |
|
|
|
|
if (ent->f != NULL) { |
if (ent->f != NULL) { |
if (!(ent->flags & MON_PERMIT)) |
if (!(ent->flags & MON_PERMIT)) |
fatal("%s: unpermitted request %d", __func__, |
fatal_f("unpermitted request %d", type); |
type); |
|
ret = (*ent->f)(ssh, pmonitor->m_sendfd, m); |
ret = (*ent->f)(ssh, pmonitor->m_sendfd, m); |
sshbuf_free(m); |
sshbuf_free(m); |
|
|
/* The child may use this request only once, disable it */ |
/* The child may use this request only once, disable it */ |
if (ent->flags & MON_ONCE) { |
if (ent->flags & MON_ONCE) { |
debug2("%s: %d used once, disabling now", __func__, |
debug2_f("%d used once, disabling now", type); |
type); |
|
ent->flags &= ~MON_PERMIT; |
ent->flags &= ~MON_PERMIT; |
} |
} |
|
|
|
|
return ret; |
return ret; |
} |
} |
|
|
fatal("%s: unsupported request: %d", __func__, type); |
fatal_f("unsupported request: %d", type); |
|
|
/* NOTREACHED */ |
/* NOTREACHED */ |
return (-1); |
return (-1); |
|
|
if ((r = sshbuf_get_u32(m, &min)) != 0 || |
if ((r = sshbuf_get_u32(m, &min)) != 0 || |
(r = sshbuf_get_u32(m, &want)) != 0 || |
(r = sshbuf_get_u32(m, &want)) != 0 || |
(r = sshbuf_get_u32(m, &max)) != 0) |
(r = sshbuf_get_u32(m, &max)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse"); |
|
|
debug3("%s: got parameters: %d %d %d", |
debug3_f("got parameters: %d %d %d", min, want, max); |
__func__, min, want, max); |
|
/* We need to check here, too, in case the child got corrupted */ |
/* We need to check here, too, in case the child got corrupted */ |
if (max < min || want < min || max < want) |
if (max < min || want < min || max < want) |
fatal("%s: bad parameters: %d %d %d", |
fatal_f("bad parameters: %d %d %d", min, want, max); |
__func__, min, want, max); |
|
|
|
sshbuf_reset(m); |
sshbuf_reset(m); |
|
|
dh = choose_dh(min, want, max); |
dh = choose_dh(min, want, max); |
if (dh == NULL) { |
if (dh == NULL) { |
if ((r = sshbuf_put_u8(m, 0)) != 0) |
if ((r = sshbuf_put_u8(m, 0)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "assemble empty"); |
return (0); |
return (0); |
} else { |
} else { |
/* Send first bignum */ |
/* Send first bignum */ |
|
|
if ((r = sshbuf_put_u8(m, 1)) != 0 || |
if ((r = sshbuf_put_u8(m, 1)) != 0 || |
(r = sshbuf_put_bignum2(m, dh_p)) != 0 || |
(r = sshbuf_put_bignum2(m, dh_p)) != 0 || |
(r = sshbuf_put_bignum2(m, dh_g)) != 0) |
(r = sshbuf_put_bignum2(m, dh_g)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "assemble"); |
|
|
DH_free(dh); |
DH_free(dh); |
} |
} |
|
|
u_int keyid, compat; |
u_int keyid, compat; |
const char proof_req[] = "hostkeys-prove-00@openssh.com"; |
const char proof_req[] = "hostkeys-prove-00@openssh.com"; |
|
|
debug3("%s", __func__); |
debug3_f("entering"); |
|
|
if ((r = sshbuf_get_u32(m, &keyid)) != 0 || |
if ((r = sshbuf_get_u32(m, &keyid)) != 0 || |
(r = sshbuf_get_string(m, &p, &datlen)) != 0 || |
(r = sshbuf_get_string(m, &p, &datlen)) != 0 || |
(r = sshbuf_get_cstring(m, &alg, &alglen)) != 0 || |
(r = sshbuf_get_cstring(m, &alg, &alglen)) != 0 || |
(r = sshbuf_get_u32(m, &compat)) != 0) |
(r = sshbuf_get_u32(m, &compat)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse"); |
if (keyid > INT_MAX) |
if (keyid > INT_MAX) |
fatal("%s: invalid key ID", __func__); |
fatal_f("invalid key ID"); |
|
|
/* |
/* |
* Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes), |
* Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes), |
|
|
* the client sent us. |
* the client sent us. |
*/ |
*/ |
if (session_id2_len == 0) /* hostkeys is never first */ |
if (session_id2_len == 0) /* hostkeys is never first */ |
fatal("%s: bad data length: %zu", __func__, datlen); |
fatal_f("bad data length: %zu", datlen); |
if ((key = get_hostkey_public_by_index(keyid, ssh)) == NULL) |
if ((key = get_hostkey_public_by_index(keyid, ssh)) == NULL) |
fatal("%s: no hostkey for index %d", __func__, keyid); |
fatal_f("no hostkey for index %d", keyid); |
if ((sigbuf = sshbuf_new()) == NULL) |
if ((sigbuf = sshbuf_new()) == NULL) |
fatal("%s: sshbuf_new", __func__); |
fatal_f("sshbuf_new"); |
if ((r = sshbuf_put_cstring(sigbuf, proof_req)) != 0 || |
if ((r = sshbuf_put_cstring(sigbuf, proof_req)) != 0 || |
(r = sshbuf_put_string(sigbuf, session_id2, |
(r = sshbuf_put_string(sigbuf, session_id2, |
session_id2_len)) != 0 || |
session_id2_len)) != 0 || |
(r = sshkey_puts(key, sigbuf)) != 0) |
(r = sshkey_puts(key, sigbuf)) != 0) |
fatal("%s: couldn't prepare private key " |
fatal_fr(r, "assemble private key proof"); |
"proof buffer: %s", __func__, ssh_err(r)); |
|
if (datlen != sshbuf_len(sigbuf) || |
if (datlen != sshbuf_len(sigbuf) || |
memcmp(p, sshbuf_ptr(sigbuf), sshbuf_len(sigbuf)) != 0) |
memcmp(p, sshbuf_ptr(sigbuf), sshbuf_len(sigbuf)) != 0) |
fatal("%s: bad data length: %zu, hostkey proof len %zu", |
fatal_f("bad data length: %zu, hostkey proof len %zu", |
__func__, datlen, sshbuf_len(sigbuf)); |
datlen, sshbuf_len(sigbuf)); |
sshbuf_free(sigbuf); |
sshbuf_free(sigbuf); |
is_proof = 1; |
is_proof = 1; |
} |
} |
|
|
if ((key = get_hostkey_by_index(keyid)) != NULL) { |
if ((key = get_hostkey_by_index(keyid)) != NULL) { |
if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, alg, |
if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, alg, |
options.sk_provider, NULL, compat)) != 0) |
options.sk_provider, NULL, compat)) != 0) |
fatal("%s: sshkey_sign failed: %s", |
fatal_fr(r, "sign"); |
__func__, ssh_err(r)); |
|
} else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL && |
} else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL && |
auth_sock > 0) { |
auth_sock > 0) { |
if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen, |
if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen, |
p, datlen, alg, compat)) != 0) { |
p, datlen, alg, compat)) != 0) |
fatal("%s: ssh_agent_sign failed: %s", |
fatal_fr(r, "agent sign"); |
__func__, ssh_err(r)); |
|
} |
|
} else |
} else |
fatal("%s: no hostkey from index %d", __func__, keyid); |
fatal_f("no hostkey from index %d", keyid); |
|
|
debug3("%s: %s signature %p(%zu)", __func__, |
debug3_f("%s signature %p(%zu)", is_proof ? "hostkey proof" : "KEX", |
is_proof ? "hostkey proof" : "KEX", signature, siglen); |
signature, siglen); |
|
|
sshbuf_reset(m); |
sshbuf_reset(m); |
if ((r = sshbuf_put_string(m, signature, siglen)) != 0) |
if ((r = sshbuf_put_string(m, signature, siglen)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "assemble"); |
|
|
free(alg); |
free(alg); |
free(p); |
free(p); |
|
|
int r, allowed = 0; |
int r, allowed = 0; |
u_int i; |
u_int i; |
|
|
debug3("%s", __func__); |
debug3_f("entering"); |
|
|
if (authctxt->attempt++ != 0) |
if (authctxt->attempt++ != 0) |
fatal("%s: multiple attempts for getpwnam", __func__); |
fatal_f("multiple attempts for getpwnam"); |
|
|
if ((r = sshbuf_get_cstring(m, &username, NULL)) != 0) |
if ((r = sshbuf_get_cstring(m, &username, NULL)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse"); |
|
|
pwent = getpwnamallow(ssh, username); |
pwent = getpwnamallow(ssh, username); |
|
|
|
|
|
|
if (pwent == NULL) { |
if (pwent == NULL) { |
if ((r = sshbuf_put_u8(m, 0)) != 0) |
if ((r = sshbuf_put_u8(m, 0)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "assemble fakepw"); |
authctxt->pw = fakepw(); |
authctxt->pw = fakepw(); |
goto out; |
goto out; |
} |
} |
|
|
(r = sshbuf_put_cstring(m, pwent->pw_class)) != 0 || |
(r = sshbuf_put_cstring(m, pwent->pw_class)) != 0 || |
(r = sshbuf_put_cstring(m, pwent->pw_dir)) != 0 || |
(r = sshbuf_put_cstring(m, pwent->pw_dir)) != 0 || |
(r = sshbuf_put_cstring(m, pwent->pw_shell)) != 0) |
(r = sshbuf_put_cstring(m, pwent->pw_shell)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "assemble pw"); |
|
|
out: |
out: |
ssh_packet_set_log_preamble(ssh, "%suser %s", |
ssh_packet_set_log_preamble(ssh, "%suser %s", |
authctxt->valid ? "authenticating" : "invalid ", authctxt->user); |
authctxt->valid ? "authenticating" : "invalid ", authctxt->user); |
if ((r = sshbuf_put_string(m, &options, sizeof(options))) != 0) |
if ((r = sshbuf_put_string(m, &options, sizeof(options))) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "assemble options"); |
|
|
#define M_CP_STROPT(x) do { \ |
#define M_CP_STROPT(x) do { \ |
if (options.x != NULL) { \ |
if (options.x != NULL && \ |
if ((r = sshbuf_put_cstring(m, options.x)) != 0) \ |
(r = sshbuf_put_cstring(m, options.x)) != 0) \ |
fatal("%s: buffer error: %s", \ |
fatal_fr(r, "assemble %s", #x); \ |
__func__, ssh_err(r)); \ |
|
} \ |
|
} while (0) |
} while (0) |
#define M_CP_STRARRAYOPT(x, nx) do { \ |
#define M_CP_STRARRAYOPT(x, nx) do { \ |
for (i = 0; i < options.nx; i++) { \ |
for (i = 0; i < options.nx; i++) { \ |
if ((r = sshbuf_put_cstring(m, options.x[i])) != 0) \ |
if ((r = sshbuf_put_cstring(m, options.x[i])) != 0) \ |
fatal("%s: buffer error: %s", \ |
fatal_fr(r, "assemble %s", #x); \ |
__func__, ssh_err(r)); \ |
|
} \ |
} \ |
} while (0) |
} while (0) |
/* See comment in servconf.h */ |
/* See comment in servconf.h */ |
|
|
* run to it's packet_disconnect(), but it must not allow any |
* run to it's packet_disconnect(), but it must not allow any |
* authentication to succeed. |
* authentication to succeed. |
*/ |
*/ |
debug("%s: no valid authentication method lists", __func__); |
debug_f("no valid authentication method lists"); |
} |
} |
|
|
debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed); |
debug3_f("sending MONITOR_ANS_PWNAM: %d", allowed); |
mm_request_send(sock, MONITOR_ANS_PWNAM, m); |
mm_request_send(sock, MONITOR_ANS_PWNAM, m); |
|
|
/* Allow service/style information on the auth context */ |
/* Allow service/style information on the auth context */ |
|
|
sshbuf_reset(m); |
sshbuf_reset(m); |
banner = auth2_read_banner(); |
banner = auth2_read_banner(); |
if ((r = sshbuf_put_cstring(m, banner != NULL ? banner : "")) != 0) |
if ((r = sshbuf_put_cstring(m, banner != NULL ? banner : "")) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "assemble"); |
mm_request_send(sock, MONITOR_ANS_AUTH2_READ_BANNER, m); |
mm_request_send(sock, MONITOR_ANS_AUTH2_READ_BANNER, m); |
free(banner); |
free(banner); |
|
|
|
|
|
|
if ((r = sshbuf_get_cstring(m, &authctxt->service, NULL)) != 0 || |
if ((r = sshbuf_get_cstring(m, &authctxt->service, NULL)) != 0 || |
(r = sshbuf_get_cstring(m, &authctxt->style, NULL)) != 0) |
(r = sshbuf_get_cstring(m, &authctxt->style, NULL)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse"); |
debug3("%s: service=%s, style=%s", |
debug3_f("service=%s, style=%s", authctxt->service, authctxt->style); |
__func__, authctxt->service, authctxt->style); |
|
|
|
if (strlen(authctxt->style) == 0) { |
if (strlen(authctxt->style) == 0) { |
free(authctxt->style); |
free(authctxt->style); |
|
|
size_t plen; |
size_t plen; |
|
|
if (!options.password_authentication) |
if (!options.password_authentication) |
fatal("%s: password authentication not enabled", __func__); |
fatal_f("password authentication not enabled"); |
if ((r = sshbuf_get_cstring(m, &passwd, &plen)) != 0) |
if ((r = sshbuf_get_cstring(m, &passwd, &plen)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse"); |
/* Only authenticate if the context is valid */ |
/* Only authenticate if the context is valid */ |
authenticated = options.password_authentication && |
authenticated = options.password_authentication && |
auth_password(ssh, passwd); |
auth_password(ssh, passwd); |
|
|
|
|
sshbuf_reset(m); |
sshbuf_reset(m); |
if ((r = sshbuf_put_u32(m, authenticated)) != 0) |
if ((r = sshbuf_put_u32(m, authenticated)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "assemble"); |
|
|
debug3("%s: sending result %d", __func__, authenticated); |
debug3_f("sending result %d", authenticated); |
mm_request_send(sock, MONITOR_ANS_AUTHPASSWORD, m); |
mm_request_send(sock, MONITOR_ANS_AUTHPASSWORD, m); |
|
|
call_count++; |
call_count++; |
|
|
int r; |
int r; |
|
|
if (!options.kbd_interactive_authentication) |
if (!options.kbd_interactive_authentication) |
fatal("%s: kbd-int authentication not enabled", __func__); |
fatal_f("kbd-int authentication not enabled"); |
success = bsdauth_query(authctxt, &name, &infotxt, &numprompts, |
success = bsdauth_query(authctxt, &name, &infotxt, &numprompts, |
&prompts, &echo_on) < 0 ? 0 : 1; |
&prompts, &echo_on) < 0 ? 0 : 1; |
|
|
sshbuf_reset(m); |
sshbuf_reset(m); |
if ((r = sshbuf_put_u32(m, success)) != 0) |
if ((r = sshbuf_put_u32(m, success)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "assemble"); |
if (success) { |
if (success) { |
if ((r = sshbuf_put_cstring(m, prompts[0])) != 0) |
if ((r = sshbuf_put_cstring(m, prompts[0])) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "assemble prompt"); |
} |
} |
|
|
debug3("%s: sending challenge success: %u", __func__, success); |
debug3_f("sending challenge success: %u", success); |
mm_request_send(sock, MONITOR_ANS_BSDAUTHQUERY, m); |
mm_request_send(sock, MONITOR_ANS_BSDAUTHQUERY, m); |
|
|
if (success) { |
if (success) { |
|
|
int r, authok; |
int r, authok; |
|
|
if (!options.kbd_interactive_authentication) |
if (!options.kbd_interactive_authentication) |
fatal("%s: kbd-int authentication not enabled", __func__); |
fatal_f("kbd-int authentication not enabled"); |
if (authctxt->as == NULL) |
if (authctxt->as == NULL) |
fatal("%s: no bsd auth session", __func__); |
fatal_f("no bsd auth session"); |
|
|
if ((r = sshbuf_get_cstring(m, &response, NULL)) != 0) |
if ((r = sshbuf_get_cstring(m, &response, NULL)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse"); |
authok = options.challenge_response_authentication && |
authok = options.challenge_response_authentication && |
auth_userresponse(authctxt->as, response, 0); |
auth_userresponse(authctxt->as, response, 0); |
authctxt->as = NULL; |
authctxt->as = NULL; |
debug3("%s: <%s> = <%d>", __func__, response, authok); |
debug3_f("<%s> = <%d>", response, authok); |
free(response); |
free(response); |
|
|
sshbuf_reset(m); |
sshbuf_reset(m); |
if ((r = sshbuf_put_u32(m, authok)) != 0) |
if ((r = sshbuf_put_u32(m, authok)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "assemble"); |
|
|
debug3("%s: sending authenticated: %d", __func__, authok); |
debug3_f("sending authenticated: %d", authok); |
mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m); |
mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m); |
|
|
auth_method = "keyboard-interactive"; |
auth_method = "keyboard-interactive"; |
|
|
int r, allowed = 0; |
int r, allowed = 0; |
struct sshauthopt *opts = NULL; |
struct sshauthopt *opts = NULL; |
|
|
debug3("%s entering", __func__); |
debug3_f("entering"); |
if ((r = sshbuf_get_u32(m, &type)) != 0 || |
if ((r = sshbuf_get_u32(m, &type)) != 0 || |
(r = sshbuf_get_cstring(m, &cuser, NULL)) != 0 || |
(r = sshbuf_get_cstring(m, &cuser, NULL)) != 0 || |
(r = sshbuf_get_cstring(m, &chost, NULL)) != 0 || |
(r = sshbuf_get_cstring(m, &chost, NULL)) != 0 || |
(r = sshkey_froms(m, &key)) != 0 || |
(r = sshkey_froms(m, &key)) != 0 || |
(r = sshbuf_get_u32(m, &pubkey_auth_attempt)) != 0) |
(r = sshbuf_get_u32(m, &pubkey_auth_attempt)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse"); |
|
|
debug3("%s: key_from_blob: %p", __func__, key); |
debug3_f("key_from_blob: %p", key); |
|
|
if (key != NULL && authctxt->valid) { |
if (key != NULL && authctxt->valid) { |
/* These should not make it past the privsep child */ |
/* These should not make it past the privsep child */ |
if (sshkey_type_plain(key->type) == KEY_RSA && |
if (sshkey_type_plain(key->type) == KEY_RSA && |
(datafellows & SSH_BUG_RSASIGMD5) != 0) |
(datafellows & SSH_BUG_RSASIGMD5) != 0) |
fatal("%s: passed a SSH_BUG_RSASIGMD5 key", __func__); |
fatal_f("passed a SSH_BUG_RSASIGMD5 key"); |
|
|
switch (type) { |
switch (type) { |
case MM_USERKEY: |
case MM_USERKEY: |
|
|
cuser, chost); |
cuser, chost); |
break; |
break; |
default: |
default: |
fatal("%s: unknown key type %d", __func__, type); |
fatal_f("unknown key type %d", type); |
break; |
break; |
} |
} |
} |
} |
|
|
debug3("%s: %s authentication%s: %s key is %s", __func__, |
debug3_f("%s authentication%s: %s key is %s", auth_method, |
auth_method, pubkey_auth_attempt ? "" : " test", |
pubkey_auth_attempt ? "" : " test", |
(key == NULL || !authctxt->valid) ? "invalid" : sshkey_type(key), |
(key == NULL || !authctxt->valid) ? "invalid" : sshkey_type(key), |
allowed ? "allowed" : "not allowed"); |
allowed ? "allowed" : "not allowed"); |
|
|
|
|
if (allowed) { |
if (allowed) { |
/* Save temporarily for comparison in verify */ |
/* Save temporarily for comparison in verify */ |
if ((r = sshkey_to_blob(key, &key_blob, &key_bloblen)) != 0) |
if ((r = sshkey_to_blob(key, &key_blob, &key_bloblen)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "sshkey_to_blob"); |
key_blobtype = type; |
key_blobtype = type; |
key_opts = opts; |
key_opts = opts; |
hostbased_cuser = cuser; |
hostbased_cuser = cuser; |
|
|
|
|
sshbuf_reset(m); |
sshbuf_reset(m); |
if ((r = sshbuf_put_u32(m, allowed)) != 0) |
if ((r = sshbuf_put_u32(m, allowed)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "assemble"); |
if (opts != NULL && (r = sshauthopt_serialise(opts, m, 1)) != 0) |
if (opts != NULL && (r = sshauthopt_serialise(opts, m, 1)) != 0) |
fatal("%s: sshauthopt_serialise: %s", __func__, ssh_err(r)); |
fatal_fr(r, "sshauthopt_serialise"); |
mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m); |
mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m); |
|
|
if (!allowed) |
if (!allowed) |
|
|
int r, fail = 0; |
int r, fail = 0; |
|
|
if ((b = sshbuf_from(data, datalen)) == NULL) |
if ((b = sshbuf_from(data, datalen)) == NULL) |
fatal("%s: sshbuf_from", __func__); |
fatal_f("sshbuf_from"); |
|
|
if (datafellows & SSH_OLD_SESSIONID) { |
if (datafellows & SSH_OLD_SESSIONID) { |
p = sshbuf_ptr(b); |
p = sshbuf_ptr(b); |
|
|
(timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) |
(timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) |
fail++; |
fail++; |
if ((r = sshbuf_consume(b, session_id2_len)) != 0) |
if ((r = sshbuf_consume(b, session_id2_len)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "consume"); |
} else { |
} else { |
if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0) |
if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse sessionid"); |
if ((session_id2 == NULL) || |
if ((session_id2 == NULL) || |
(len != session_id2_len) || |
(len != session_id2_len) || |
(timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) |
(timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) |
fail++; |
fail++; |
} |
} |
if ((r = sshbuf_get_u8(b, &type)) != 0) |
if ((r = sshbuf_get_u8(b, &type)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse type"); |
if (type != SSH2_MSG_USERAUTH_REQUEST) |
if (type != SSH2_MSG_USERAUTH_REQUEST) |
fail++; |
fail++; |
if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) |
if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse userstyle"); |
xasprintf(&userstyle, "%s%s%s", authctxt->user, |
xasprintf(&userstyle, "%s%s%s", authctxt->user, |
authctxt->style ? ":" : "", |
authctxt->style ? ":" : "", |
authctxt->style ? authctxt->style : ""); |
authctxt->style ? authctxt->style : ""); |
|
|
free(cp); |
free(cp); |
if ((r = sshbuf_skip_string(b)) != 0 || /* service */ |
if ((r = sshbuf_skip_string(b)) != 0 || /* service */ |
(r = sshbuf_get_cstring(b, &cp, NULL)) != 0) |
(r = sshbuf_get_cstring(b, &cp, NULL)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse method"); |
if (strcmp("publickey", cp) != 0) |
if (strcmp("publickey", cp) != 0) |
fail++; |
fail++; |
free(cp); |
free(cp); |
if ((r = sshbuf_get_u8(b, &type)) != 0) |
if ((r = sshbuf_get_u8(b, &type)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse pktype"); |
if (type == 0) |
if (type == 0) |
fail++; |
fail++; |
if ((r = sshbuf_skip_string(b)) != 0 || /* pkalg */ |
if ((r = sshbuf_skip_string(b)) != 0 || /* pkalg */ |
(r = sshbuf_skip_string(b)) != 0) /* pkblob */ |
(r = sshbuf_skip_string(b)) != 0) /* pkblob */ |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse pk"); |
if (sshbuf_len(b) != 0) |
if (sshbuf_len(b) != 0) |
fail++; |
fail++; |
sshbuf_free(b); |
sshbuf_free(b); |
|
|
u_char type; |
u_char type; |
|
|
if ((b = sshbuf_from(data, datalen)) == NULL) |
if ((b = sshbuf_from(data, datalen)) == NULL) |
fatal("%s: sshbuf_new", __func__); |
fatal_f("sshbuf_new"); |
if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0) |
if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse sessionid"); |
|
|
if ((session_id2 == NULL) || |
if ((session_id2 == NULL) || |
(len != session_id2_len) || |
(len != session_id2_len) || |
|
|
fail++; |
fail++; |
|
|
if ((r = sshbuf_get_u8(b, &type)) != 0) |
if ((r = sshbuf_get_u8(b, &type)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse type"); |
if (type != SSH2_MSG_USERAUTH_REQUEST) |
if (type != SSH2_MSG_USERAUTH_REQUEST) |
fail++; |
fail++; |
if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) |
if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse userstyle"); |
xasprintf(&userstyle, "%s%s%s", authctxt->user, |
xasprintf(&userstyle, "%s%s%s", authctxt->user, |
authctxt->style ? ":" : "", |
authctxt->style ? ":" : "", |
authctxt->style ? authctxt->style : ""); |
authctxt->style ? authctxt->style : ""); |
|
|
free(cp); |
free(cp); |
if ((r = sshbuf_skip_string(b)) != 0 || /* service */ |
if ((r = sshbuf_skip_string(b)) != 0 || /* service */ |
(r = sshbuf_get_cstring(b, &cp, NULL)) != 0) |
(r = sshbuf_get_cstring(b, &cp, NULL)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse method"); |
if (strcmp(cp, "hostbased") != 0) |
if (strcmp(cp, "hostbased") != 0) |
fail++; |
fail++; |
free(cp); |
free(cp); |
if ((r = sshbuf_skip_string(b)) != 0 || /* pkalg */ |
if ((r = sshbuf_skip_string(b)) != 0 || /* pkalg */ |
(r = sshbuf_skip_string(b)) != 0) /* pkblob */ |
(r = sshbuf_skip_string(b)) != 0) /* pkblob */ |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse pk"); |
|
|
/* verify client host, strip trailing dot if necessary */ |
/* verify client host, strip trailing dot if necessary */ |
if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) |
if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse host"); |
if (((len = strlen(cp)) > 0) && cp[len - 1] == '.') |
if (((len = strlen(cp)) > 0) && cp[len - 1] == '.') |
cp[len - 1] = '\0'; |
cp[len - 1] = '\0'; |
if (strcmp(cp, chost) != 0) |
if (strcmp(cp, chost) != 0) |
|
|
|
|
/* verify client user */ |
/* verify client user */ |
if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) |
if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse ruser"); |
if (strcmp(cp, cuser) != 0) |
if (strcmp(cp, cuser) != 0) |
fail++; |
fail++; |
free(cp); |
free(cp); |
|
|
(r = sshbuf_get_string_direct(m, &signature, &signaturelen)) != 0 || |
(r = sshbuf_get_string_direct(m, &signature, &signaturelen)) != 0 || |
(r = sshbuf_get_string_direct(m, &data, &datalen)) != 0 || |
(r = sshbuf_get_string_direct(m, &data, &datalen)) != 0 || |
(r = sshbuf_get_cstring(m, &sigalg, NULL)) != 0) |
(r = sshbuf_get_cstring(m, &sigalg, NULL)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse"); |
|
|
if (hostbased_cuser == NULL || hostbased_chost == NULL || |
if (hostbased_cuser == NULL || hostbased_chost == NULL || |
!monitor_allowed_key(blob, bloblen)) |
!monitor_allowed_key(blob, bloblen)) |
fatal("%s: bad key, not previously allowed", __func__); |
fatal_f("bad key, not previously allowed"); |
|
|
/* Empty signature algorithm means NULL. */ |
/* Empty signature algorithm means NULL. */ |
if (*sigalg == '\0') { |
if (*sigalg == '\0') { |
|
|
|
|
/* XXX use sshkey_froms here; need to change key_blob, etc. */ |
/* XXX use sshkey_froms here; need to change key_blob, etc. */ |
if ((r = sshkey_from_blob(blob, bloblen, &key)) != 0) |
if ((r = sshkey_from_blob(blob, bloblen, &key)) != 0) |
fatal("%s: bad public key blob: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse key"); |
|
|
switch (key_blobtype) { |
switch (key_blobtype) { |
case MM_USERKEY: |
case MM_USERKEY: |
|
|
break; |
break; |
} |
} |
if (!valid_data) |
if (!valid_data) |
fatal("%s: bad signature data blob", __func__); |
fatal_f("bad signature data blob"); |
|
|
if ((fp = sshkey_fingerprint(key, options.fingerprint_hash, |
if ((fp = sshkey_fingerprint(key, options.fingerprint_hash, |
SSH_FP_DEFAULT)) == NULL) |
SSH_FP_DEFAULT)) == NULL) |
fatal("%s: sshkey_fingerprint failed", __func__); |
fatal_f("sshkey_fingerprint failed"); |
|
|
ret = sshkey_verify(key, signature, signaturelen, data, datalen, |
ret = sshkey_verify(key, signature, signaturelen, data, datalen, |
sigalg, ssh->compat, &sig_details); |
sigalg, ssh->compat, &sig_details); |
debug3("%s: %s %p signature %s%s%s", __func__, auth_method, key, |
debug3_f("%s %p signature %s%s%s", auth_method, key, |
(ret == 0) ? "verified" : "unverified", |
(ret == 0) ? "verified" : "unverified", |
(ret != 0) ? ": " : "", (ret != 0) ? ssh_err(ret) : ""); |
(ret != 0) ? ": " : "", (ret != 0) ? ssh_err(ret) : ""); |
|
|
|
|
encoded_ret = (ret != 0); |
encoded_ret = (ret != 0); |
if ((r = sshbuf_put_u32(m, encoded_ret)) != 0 || |
if ((r = sshbuf_put_u32(m, encoded_ret)) != 0 || |
(r = sshbuf_put_u8(m, sig_details != NULL)) != 0) |
(r = sshbuf_put_u8(m, sig_details != NULL)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "assemble"); |
if (sig_details != NULL) { |
if (sig_details != NULL) { |
if ((r = sshbuf_put_u32(m, sig_details->sk_counter)) != 0 || |
if ((r = sshbuf_put_u32(m, sig_details->sk_counter)) != 0 || |
(r = sshbuf_put_u8(m, sig_details->sk_flags)) != 0) |
(r = sshbuf_put_u8(m, sig_details->sk_flags)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "assemble sk"); |
} |
} |
sshkey_sig_details_free(sig_details); |
sshkey_sig_details_free(sig_details); |
mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); |
mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); |
|
|
static void |
static void |
mm_session_close(Session *s) |
mm_session_close(Session *s) |
{ |
{ |
debug3("%s: session %d pid %ld", __func__, s->self, (long)s->pid); |
debug3_f("session %d pid %ld", s->self, (long)s->pid); |
if (s->ttyfd != -1) { |
if (s->ttyfd != -1) { |
debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd); |
debug3_f("tty %s ptyfd %d", s->tty, s->ptyfd); |
session_pty_cleanup2(s); |
session_pty_cleanup2(s); |
} |
} |
session_unused(s->self); |
session_unused(s->self); |
|
|
Session *s; |
Session *s; |
int r, res, fd0; |
int r, res, fd0; |
|
|
debug3("%s entering", __func__); |
debug3_f("entering"); |
|
|
sshbuf_reset(m); |
sshbuf_reset(m); |
s = session_new(); |
s = session_new(); |
|
|
|
|
if ((r = sshbuf_put_u32(m, 1)) != 0 || |
if ((r = sshbuf_put_u32(m, 1)) != 0 || |
(r = sshbuf_put_cstring(m, s->tty)) != 0) |
(r = sshbuf_put_cstring(m, s->tty)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "assemble"); |
|
|
/* We need to trick ttyslot */ |
/* We need to trick ttyslot */ |
if (dup2(s->ttyfd, 0) == -1) |
if (dup2(s->ttyfd, 0) == -1) |
fatal("%s: dup2", __func__); |
fatal_f("dup2"); |
|
|
mm_record_login(ssh, s, authctxt->pw); |
mm_record_login(ssh, s, authctxt->pw); |
|
|
|
|
|
|
/* send messages generated by record_login */ |
/* send messages generated by record_login */ |
if ((r = sshbuf_put_stringb(m, loginmsg)) != 0) |
if ((r = sshbuf_put_stringb(m, loginmsg)) != 0) |
fatal("%s: put login message: %s", __func__, ssh_err(r)); |
fatal_fr(r, "assemble loginmsg"); |
sshbuf_reset(loginmsg); |
sshbuf_reset(loginmsg); |
|
|
mm_request_send(sock, MONITOR_ANS_PTY, m); |
mm_request_send(sock, MONITOR_ANS_PTY, m); |
|
|
if (mm_send_fd(sock, s->ptyfd) == -1 || |
if (mm_send_fd(sock, s->ptyfd) == -1 || |
mm_send_fd(sock, s->ttyfd) == -1) |
mm_send_fd(sock, s->ttyfd) == -1) |
fatal("%s: send fds failed", __func__); |
fatal_f("send fds failed"); |
|
|
/* make sure nothing uses fd 0 */ |
/* make sure nothing uses fd 0 */ |
if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) == -1) |
if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) == -1) |
fatal("%s: open(/dev/null): %s", __func__, strerror(errno)); |
fatal_f("open(/dev/null): %s", strerror(errno)); |
if (fd0 != 0) |
if (fd0 != 0) |
error("%s: fd0 %d != 0", __func__, fd0); |
error_f("fd0 %d != 0", fd0); |
|
|
/* slave side of pty is not needed */ |
/* slave side of pty is not needed */ |
close(s->ttyfd); |
close(s->ttyfd); |
|
|
/* no need to dup() because nobody closes ptyfd */ |
/* no need to dup() because nobody closes ptyfd */ |
s->ptymaster = s->ptyfd; |
s->ptymaster = s->ptyfd; |
|
|
debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ttyfd); |
debug3_f("tty %s ptyfd %d", s->tty, s->ttyfd); |
|
|
return (0); |
return (0); |
|
|
|
|
if (s != NULL) |
if (s != NULL) |
mm_session_close(s); |
mm_session_close(s); |
if ((r = sshbuf_put_u32(m, 0)) != 0) |
if ((r = sshbuf_put_u32(m, 0)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "assemble 0"); |
mm_request_send(sock, MONITOR_ANS_PTY, m); |
mm_request_send(sock, MONITOR_ANS_PTY, m); |
return (0); |
return (0); |
} |
} |
|
|
char *tty; |
char *tty; |
int r; |
int r; |
|
|
debug3("%s entering", __func__); |
debug3_f("entering"); |
|
|
if ((r = sshbuf_get_cstring(m, &tty, NULL)) != 0) |
if ((r = sshbuf_get_cstring(m, &tty, NULL)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse tty"); |
if ((s = session_by_tty(tty)) != NULL) |
if ((s = session_by_tty(tty)) != NULL) |
mm_session_close(s); |
mm_session_close(s); |
sshbuf_reset(m); |
sshbuf_reset(m); |
|
|
extern struct monitor *pmonitor; |
extern struct monitor *pmonitor; |
int res, status; |
int res, status; |
|
|
debug3("%s: tearing down sessions", __func__); |
debug3_f("tearing down sessions"); |
|
|
/* The child is terminating */ |
/* The child is terminating */ |
session_destroy_all(ssh, &mm_session_close); |
session_destroy_all(ssh, &mm_session_close); |
|
|
struct kex *kex; |
struct kex *kex; |
int r; |
int r; |
|
|
debug3("%s: packet_set_state", __func__); |
debug3_f("packet_set_state"); |
if ((r = ssh_packet_set_state(ssh, child_state)) != 0) |
if ((r = ssh_packet_set_state(ssh, child_state)) != 0) |
fatal("%s: packet_set_state: %s", __func__, ssh_err(r)); |
fatal_fr(r, "packet_set_state"); |
sshbuf_free(child_state); |
sshbuf_free(child_state); |
child_state = NULL; |
child_state = NULL; |
|
|
|
|
void |
void |
mm_get_keystate(struct ssh *ssh, struct monitor *pmonitor) |
mm_get_keystate(struct ssh *ssh, struct monitor *pmonitor) |
{ |
{ |
debug3("%s: Waiting for new keys", __func__); |
debug3_f("Waiting for new keys"); |
|
|
if ((child_state = sshbuf_new()) == NULL) |
if ((child_state = sshbuf_new()) == NULL) |
fatal("%s: sshbuf_new failed", __func__); |
fatal_f("sshbuf_new failed"); |
mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, |
mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, |
child_state); |
child_state); |
debug3("%s: GOT new keys", __func__); |
debug3_f("GOT new keys"); |
} |
} |
|
|
|
|
|
|
#endif |
#endif |
|
|
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) |
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) |
fatal("%s: socketpair: %s", __func__, strerror(errno)); |
fatal_f("socketpair: %s", strerror(errno)); |
#ifdef SO_ZEROIZE |
#ifdef SO_ZEROIZE |
if (setsockopt(pair[0], SOL_SOCKET, SO_ZEROIZE, &on, sizeof(on)) == -1) |
if (setsockopt(pair[0], SOL_SOCKET, SO_ZEROIZE, &on, sizeof(on)) == -1) |
error("setsockopt SO_ZEROIZE(0): %.100s", strerror(errno)); |
error("setsockopt SO_ZEROIZE(0): %.100s", strerror(errno)); |
|
|
|
|
if (do_logfds) { |
if (do_logfds) { |
if (pipe(pair) == -1) |
if (pipe(pair) == -1) |
fatal("%s: pipe: %s", __func__, strerror(errno)); |
fatal_f("pipe: %s", strerror(errno)); |
FD_CLOSEONEXEC(pair[0]); |
FD_CLOSEONEXEC(pair[0]); |
FD_CLOSEONEXEC(pair[1]); |
FD_CLOSEONEXEC(pair[1]); |
mon->m_log_recvfd = pair[0]; |
mon->m_log_recvfd = pair[0]; |
|
|
int r; |
int r; |
|
|
if (!options.gss_authentication) |
if (!options.gss_authentication) |
fatal("%s: GSSAPI authentication not enabled", __func__); |
fatal_f("GSSAPI authentication not enabled"); |
|
|
if ((r = sshbuf_get_string(m, &p, &len)) != 0) |
if ((r = sshbuf_get_string(m, &p, &len)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "parse"); |
goid.elements = p; |
goid.elements = p; |
goid.length = len; |
goid.length = len; |
|
|
|
|
|
|
sshbuf_reset(m); |
sshbuf_reset(m); |
if ((r = sshbuf_put_u32(m, major)) != 0) |
if ((r = sshbuf_put_u32(m, major)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "assemble"); |
|
|
mm_request_send(sock, MONITOR_ANS_GSSSETUP, m); |
mm_request_send(sock, MONITOR_ANS_GSSSETUP, m); |
|
|
|
|
int r; |
int r; |
|
|
if (!options.gss_authentication) |
if (!options.gss_authentication) |
fatal("%s: GSSAPI authentication not enabled", __func__); |
fatal_f("GSSAPI authentication not enabled"); |
|
|
if ((r = ssh_gssapi_get_buffer_desc(m, &in)) != 0) |
if ((r = ssh_gssapi_get_buffer_desc(m, &in)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "ssh_gssapi_get_buffer_desc"); |
major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags); |
major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags); |
free(in.value); |
free(in.value); |
|
|
|
|
if ((r = sshbuf_put_u32(m, major)) != 0 || |
if ((r = sshbuf_put_u32(m, major)) != 0 || |
(r = sshbuf_put_string(m, out.value, out.length)) != 0 || |
(r = sshbuf_put_string(m, out.value, out.length)) != 0 || |
(r = sshbuf_put_u32(m, flags)) != 0) |
(r = sshbuf_put_u32(m, flags)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "assemble"); |
mm_request_send(sock, MONITOR_ANS_GSSSTEP, m); |
mm_request_send(sock, MONITOR_ANS_GSSSTEP, m); |
|
|
gss_release_buffer(&minor, &out); |
gss_release_buffer(&minor, &out); |
|
|
int r; |
int r; |
|
|
if (!options.gss_authentication) |
if (!options.gss_authentication) |
fatal("%s: GSSAPI authentication not enabled", __func__); |
fatal_f("GSSAPI authentication not enabled"); |
|
|
if ((r = ssh_gssapi_get_buffer_desc(m, &gssbuf)) != 0 || |
if ((r = ssh_gssapi_get_buffer_desc(m, &gssbuf)) != 0 || |
(r = ssh_gssapi_get_buffer_desc(m, &mic)) != 0) |
(r = ssh_gssapi_get_buffer_desc(m, &mic)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "ssh_gssapi_get_buffer_desc"); |
|
|
ret = ssh_gssapi_checkmic(gsscontext, &gssbuf, &mic); |
ret = ssh_gssapi_checkmic(gsscontext, &gssbuf, &mic); |
|
|
|
|
|
|
sshbuf_reset(m); |
sshbuf_reset(m); |
if ((r = sshbuf_put_u32(m, ret)) != 0) |
if ((r = sshbuf_put_u32(m, ret)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "assemble"); |
|
|
mm_request_send(sock, MONITOR_ANS_GSSCHECKMIC, m); |
mm_request_send(sock, MONITOR_ANS_GSSCHECKMIC, m); |
|
|
|
|
const char *displayname; |
const char *displayname; |
|
|
if (!options.gss_authentication) |
if (!options.gss_authentication) |
fatal("%s: GSSAPI authentication not enabled", __func__); |
fatal_f("GSSAPI authentication not enabled"); |
|
|
authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); |
authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); |
|
|
sshbuf_reset(m); |
sshbuf_reset(m); |
if ((r = sshbuf_put_u32(m, authenticated)) != 0) |
if ((r = sshbuf_put_u32(m, authenticated)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal_fr(r, "assemble"); |
|
|
debug3("%s: sending result %d", __func__, authenticated); |
debug3_f("sending result %d", authenticated); |
mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m); |
mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m); |
|
|
auth_method = "gssapi-with-mic"; |
auth_method = "gssapi-with-mic"; |