X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/24436b92e4fe165fe7d6a845c0bd8e841045e787..HEAD:/monitor.c diff --git a/monitor.c b/monitor.c index b3ccde01..ace25c40 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.88 2006/08/12 20:46:46 miod Exp $ */ +/* $OpenBSD: monitor.c,v 1.104 2009/06/12 20:43:22 andreas Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -43,6 +43,7 @@ #include #include #include +#include #ifdef SKEY #include @@ -50,6 +51,7 @@ #include +#include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" #include "key.h" @@ -85,6 +87,8 @@ #include "misc.h" #include "compat.h" #include "ssh2.h" +#include "jpake.h" +#include "roaming.h" #ifdef GSSAPI static Gssctxt *gsscontext = NULL; @@ -97,7 +101,6 @@ extern Newkeys *current_keys[]; extern z_stream incoming_stream; extern z_stream outgoing_stream; extern u_char session_id[]; -extern Buffer input, output; extern Buffer auth_debug; extern int auth_debug_init; extern Buffer loginmsg; @@ -123,6 +126,8 @@ struct { u_int ilen; u_char *output; u_int olen; + u_int64_t sent_bytes; + u_int64_t recv_bytes; } child_state; /* Functions on the monitor that answer unprivileged requests */ @@ -147,6 +152,11 @@ int mm_answer_rsa_challenge(int, Buffer *); int mm_answer_rsa_response(int, Buffer *); int mm_answer_sesskey(int, Buffer *); int mm_answer_sessid(int, Buffer *); +int mm_answer_jpake_get_pwdata(int, Buffer *); +int mm_answer_jpake_step1(int, Buffer *); +int mm_answer_jpake_step2(int, Buffer *); +int mm_answer_jpake_key_confirm(int, Buffer *); +int mm_answer_jpake_check_confirm(int, Buffer *); #ifdef USE_PAM int mm_answer_pam_start(int, Buffer *); @@ -231,6 +241,13 @@ struct mon_table mon_dispatch_proto20[] = { {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx}, {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic}, +#endif +#ifdef JPAKE + {MONITOR_REQ_JPAKE_GET_PWDATA, MON_ONCE, mm_answer_jpake_get_pwdata}, + {MONITOR_REQ_JPAKE_STEP1, MON_ISAUTH, mm_answer_jpake_step1}, + {MONITOR_REQ_JPAKE_STEP2, MON_ONCE, mm_answer_jpake_step2}, + {MONITOR_REQ_JPAKE_KEY_CONFIRM, MON_ONCE, mm_answer_jpake_key_confirm}, + {MONITOR_REQ_JPAKE_CHECK_CONFIRM, MON_AUTH, mm_answer_jpake_check_confirm}, #endif {0, 0, NULL} }; @@ -285,7 +302,7 @@ struct mon_table mon_dispatch_postauth15[] = { {MONITOR_REQ_TERM, 0, mm_answer_term}, #ifdef SSH_AUDIT_EVENTS {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, - {MONITOR_REQ_AUDIT_COMMAND, MON_ONCE, mm_answer_audit_command}, + {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command}, #endif {0, 0, NULL} }; @@ -349,7 +366,7 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) /* The first few requests do not require asynchronous access */ while (!authenticated) { auth_method = "unknown"; - authenticated = monitor_read(pmonitor, mon_dispatch, &ent); + authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1); if (authenticated) { if (!(ent->flags & MON_AUTHDECIDE)) fatal("%s: unexpected authentication from %d", @@ -377,6 +394,15 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) if (!authenticated) authctxt->failures++; } +#ifdef JPAKE + /* Cleanup JPAKE context after authentication */ + if (ent->flags & MON_AUTHDECIDE) { + if (authctxt->jpake_ctx != NULL) { + jpake_free(authctxt->jpake_ctx); + authctxt->jpake_ctx = NULL; + } + } +#endif } if (!authctxt->valid) @@ -408,6 +434,7 @@ monitor_child_postauth(struct monitor *pmonitor) monitor_set_child_handler(pmonitor->m_pid); signal(SIGHUP, &monitor_child_handler); signal(SIGTERM, &monitor_child_handler); + signal(SIGINT, &monitor_child_handler); if (compat20) { mon_dispatch = mon_dispatch_postauth20; @@ -643,6 +670,9 @@ mm_answer_pwnamallow(int sock, Buffer *m) buffer_put_cstring(m, pwent->pw_shell); out: + buffer_put_string(m, &options, sizeof(options)); + if (options.banner != NULL) + buffer_put_cstring(m, options.banner); debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed); mm_request_send(sock, MONITOR_ANS_PWNAM, m); @@ -659,9 +689,6 @@ mm_answer_pwnamallow(int sock, Buffer *m) if (options.use_pam) monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1); #endif -#ifdef SSH_AUDIT_EVENTS - monitor_permit(mon_dispatch, MONITOR_REQ_AUDIT_COMMAND, 1); -#endif return (0); } @@ -1012,6 +1039,8 @@ mm_answer_keyallowed(int sock, Buffer *m) allowed = options.pubkey_authentication && user_key_allowed(authctxt->pw, key); auth_method = "publickey"; + if (options.pubkey_authentication && allowed != 1) + auth_clear_options(); break; case MM_HOSTKEY: allowed = options.hostbased_authentication && @@ -1024,6 +1053,8 @@ mm_answer_keyallowed(int sock, Buffer *m) allowed = options.rhosts_rsa_authentication && auth_rhosts_rsa_key_allowed(authctxt->pw, cuser, chost, key); + if (options.rhosts_rsa_authentication && allowed != 1) + auth_clear_options(); auth_method = "rsa"; break; default: @@ -1053,7 +1084,7 @@ mm_answer_keyallowed(int sock, Buffer *m) } debug3("%s: key %p is %s", - __func__, key, allowed ? "allowed" : "disallowed"); + __func__, key, allowed ? "allowed" : "not allowed"); buffer_clear(m); buffer_put_int(m, allowed); @@ -1219,7 +1250,7 @@ mm_answer_keyverify(int sock, Buffer *m) verified = key_verify(key, signature, signaturelen, data, datalen); debug3("%s: key %p signature %s", - __func__, key, verified ? "verified" : "unverified"); + __func__, key, (verified == 1) ? "verified" : "unverified"); key_free(key); xfree(blob); @@ -1234,7 +1265,7 @@ mm_answer_keyverify(int sock, Buffer *m) buffer_put_int(m, verified); mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); - return (verified); + return (verified == 1); } static void @@ -1270,7 +1301,7 @@ mm_session_close(Session *s) debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd); session_pty_cleanup2(s); } - s->used = 0; + session_unused(s->self); } int @@ -1312,8 +1343,9 @@ mm_answer_pty(int sock, Buffer *m) mm_request_send(sock, MONITOR_ANS_PTY, m); - mm_send_fd(sock, s->ptyfd); - mm_send_fd(sock, s->ttyfd); + if (mm_send_fd(sock, s->ptyfd) == -1 || + mm_send_fd(sock, s->ttyfd) == -1) + fatal("%s: send fds failed", __func__); /* make sure nothing uses fd 0 */ if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0) @@ -1470,7 +1502,9 @@ mm_answer_rsa_challenge(int sock, Buffer *m) fatal("%s: key type mismatch", __func__); if ((key = key_from_blob(blob, blen)) == NULL) fatal("%s: received bad key", __func__); - + if (key->type != KEY_RSA) + fatal("%s: received bad key type %d", __func__, key->type); + key->type = KEY_RSA1; if (ssh1_challenge) BN_clear_free(ssh1_challenge); ssh1_challenge = auth_rsa_generate_challenge(key); @@ -1544,6 +1578,11 @@ mm_answer_term(int sock, Buffer *req) /* The child is terminating */ session_destroy_all(&mm_session_close); +#ifdef USE_PAM + if (options.use_pam) + sshpam_cleanup(); +#endif + while (waitpid(pmonitor->m_pid, &status, 0) == -1) if (errno != EINTR) exit(1); @@ -1633,15 +1672,20 @@ monitor_apply_keystate(struct monitor *pmonitor) /* Network I/O buffers */ /* XXX inefficient for large buffers, need: buffer_init_from_string */ - buffer_clear(&input); - buffer_append(&input, child_state.input, child_state.ilen); + buffer_clear(packet_get_input()); + buffer_append(packet_get_input(), child_state.input, child_state.ilen); memset(child_state.input, 0, child_state.ilen); xfree(child_state.input); - buffer_clear(&output); - buffer_append(&output, child_state.output, child_state.olen); + buffer_clear(packet_get_output()); + buffer_append(packet_get_output(), child_state.output, + child_state.olen); memset(child_state.output, 0, child_state.olen); xfree(child_state.output); + + /* Roaming */ + if (compat20) + roam_set_bytes(child_state.sent_bytes, child_state.recv_bytes); } static Kex * @@ -1692,7 +1736,7 @@ mm_get_keystate(struct monitor *pmonitor) u_char *blob, *p; u_int bloblen, plen; u_int32_t seqnr, packets; - u_int64_t blocks; + u_int64_t blocks, bytes; debug3("%s: Waiting for new keys", __func__); @@ -1725,11 +1769,13 @@ mm_get_keystate(struct monitor *pmonitor) seqnr = buffer_get_int(&m); blocks = buffer_get_int64(&m); packets = buffer_get_int(&m); - packet_set_state(MODE_OUT, seqnr, blocks, packets); + bytes = buffer_get_int64(&m); + packet_set_state(MODE_OUT, seqnr, blocks, packets, bytes); seqnr = buffer_get_int(&m); blocks = buffer_get_int64(&m); packets = buffer_get_int(&m); - packet_set_state(MODE_IN, seqnr, blocks, packets); + bytes = buffer_get_int64(&m); + packet_set_state(MODE_IN, seqnr, blocks, packets, bytes); skip: /* Get the key context */ @@ -1755,6 +1801,12 @@ mm_get_keystate(struct monitor *pmonitor) child_state.input = buffer_get_string(&m, &child_state.ilen); child_state.output = buffer_get_string(&m, &child_state.olen); + /* Roaming */ + if (compat20) { + child_state.sent_bytes = buffer_get_int64(&m); + child_state.recv_bytes = buffer_get_int64(&m); + } + buffer_free(&m); } @@ -1954,3 +2006,206 @@ mm_answer_gss_userok(int sock, Buffer *m) return (authenticated); } #endif /* GSSAPI */ + +#ifdef JPAKE +int +mm_answer_jpake_step1(int sock, Buffer *m) +{ + struct jpake_ctx *pctx; + u_char *x3_proof, *x4_proof; + u_int x3_proof_len, x4_proof_len; + + if (!options.zero_knowledge_password_authentication) + fatal("zero_knowledge_password_authentication disabled"); + + if (authctxt->jpake_ctx != NULL) + fatal("%s: authctxt->jpake_ctx already set (%p)", + __func__, authctxt->jpake_ctx); + authctxt->jpake_ctx = pctx = jpake_new(); + + jpake_step1(pctx->grp, + &pctx->server_id, &pctx->server_id_len, + &pctx->x3, &pctx->x4, &pctx->g_x3, &pctx->g_x4, + &x3_proof, &x3_proof_len, + &x4_proof, &x4_proof_len); + + JPAKE_DEBUG_CTX((pctx, "step1 done in %s", __func__)); + + buffer_clear(m); + + buffer_put_string(m, pctx->server_id, pctx->server_id_len); + buffer_put_bignum2(m, pctx->g_x3); + buffer_put_bignum2(m, pctx->g_x4); + buffer_put_string(m, x3_proof, x3_proof_len); + buffer_put_string(m, x4_proof, x4_proof_len); + + debug3("%s: sending step1", __func__); + mm_request_send(sock, MONITOR_ANS_JPAKE_STEP1, m); + + bzero(x3_proof, x3_proof_len); + bzero(x4_proof, x4_proof_len); + xfree(x3_proof); + xfree(x4_proof); + + monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_GET_PWDATA, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP1, 0); + + return 0; +} + +int +mm_answer_jpake_get_pwdata(int sock, Buffer *m) +{ + struct jpake_ctx *pctx = authctxt->jpake_ctx; + char *hash_scheme, *salt; + + if (pctx == NULL) + fatal("%s: pctx == NULL", __func__); + + auth2_jpake_get_pwdata(authctxt, &pctx->s, &hash_scheme, &salt); + + buffer_clear(m); + /* pctx->s is sensitive, not returned to slave */ + buffer_put_cstring(m, hash_scheme); + buffer_put_cstring(m, salt); + + debug3("%s: sending pwdata", __func__); + mm_request_send(sock, MONITOR_ANS_JPAKE_GET_PWDATA, m); + + bzero(hash_scheme, strlen(hash_scheme)); + bzero(salt, strlen(salt)); + xfree(hash_scheme); + xfree(salt); + + monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP2, 1); + + return 0; +} + +int +mm_answer_jpake_step2(int sock, Buffer *m) +{ + struct jpake_ctx *pctx = authctxt->jpake_ctx; + u_char *x1_proof, *x2_proof, *x4_s_proof; + u_int x1_proof_len, x2_proof_len, x4_s_proof_len; + + if (pctx == NULL) + fatal("%s: pctx == NULL", __func__); + + if ((pctx->g_x1 = BN_new()) == NULL || + (pctx->g_x2 = BN_new()) == NULL) + fatal("%s: BN_new", __func__); + buffer_get_bignum2(m, pctx->g_x1); + buffer_get_bignum2(m, pctx->g_x2); + pctx->client_id = buffer_get_string(m, &pctx->client_id_len); + x1_proof = buffer_get_string(m, &x1_proof_len); + x2_proof = buffer_get_string(m, &x2_proof_len); + + jpake_step2(pctx->grp, pctx->s, pctx->g_x3, + pctx->g_x1, pctx->g_x2, pctx->x4, + pctx->client_id, pctx->client_id_len, + pctx->server_id, pctx->server_id_len, + x1_proof, x1_proof_len, + x2_proof, x2_proof_len, + &pctx->b, + &x4_s_proof, &x4_s_proof_len); + + JPAKE_DEBUG_CTX((pctx, "step2 done in %s", __func__)); + + bzero(x1_proof, x1_proof_len); + bzero(x2_proof, x2_proof_len); + xfree(x1_proof); + xfree(x2_proof); + + buffer_clear(m); + + buffer_put_bignum2(m, pctx->b); + buffer_put_string(m, x4_s_proof, x4_s_proof_len); + + debug3("%s: sending step2", __func__); + mm_request_send(sock, MONITOR_ANS_JPAKE_STEP2, m); + + bzero(x4_s_proof, x4_s_proof_len); + xfree(x4_s_proof); + + monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_KEY_CONFIRM, 1); + + return 0; +} + +int +mm_answer_jpake_key_confirm(int sock, Buffer *m) +{ + struct jpake_ctx *pctx = authctxt->jpake_ctx; + u_char *x2_s_proof; + u_int x2_s_proof_len; + + if (pctx == NULL) + fatal("%s: pctx == NULL", __func__); + + if ((pctx->a = BN_new()) == NULL) + fatal("%s: BN_new", __func__); + buffer_get_bignum2(m, pctx->a); + x2_s_proof = buffer_get_string(m, &x2_s_proof_len); + + jpake_key_confirm(pctx->grp, pctx->s, pctx->a, + pctx->x4, pctx->g_x3, pctx->g_x4, pctx->g_x1, pctx->g_x2, + pctx->server_id, pctx->server_id_len, + pctx->client_id, pctx->client_id_len, + session_id2, session_id2_len, + x2_s_proof, x2_s_proof_len, + &pctx->k, + &pctx->h_k_sid_sessid, &pctx->h_k_sid_sessid_len); + + JPAKE_DEBUG_CTX((pctx, "key_confirm done in %s", __func__)); + + bzero(x2_s_proof, x2_s_proof_len); + buffer_clear(m); + + /* pctx->k is sensitive, not sent */ + buffer_put_string(m, pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len); + + debug3("%s: sending confirmation hash", __func__); + mm_request_send(sock, MONITOR_ANS_JPAKE_KEY_CONFIRM, m); + + monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_CHECK_CONFIRM, 1); + + return 0; +} + +int +mm_answer_jpake_check_confirm(int sock, Buffer *m) +{ + int authenticated = 0; + u_char *peer_confirm_hash; + u_int peer_confirm_hash_len; + struct jpake_ctx *pctx = authctxt->jpake_ctx; + + if (pctx == NULL) + fatal("%s: pctx == NULL", __func__); + + peer_confirm_hash = buffer_get_string(m, &peer_confirm_hash_len); + + authenticated = jpake_check_confirm(pctx->k, + pctx->client_id, pctx->client_id_len, + session_id2, session_id2_len, + peer_confirm_hash, peer_confirm_hash_len) && authctxt->valid; + + JPAKE_DEBUG_CTX((pctx, "check_confirm done in %s", __func__)); + + bzero(peer_confirm_hash, peer_confirm_hash_len); + xfree(peer_confirm_hash); + + buffer_clear(m); + buffer_put_int(m, authenticated); + + debug3("%s: sending result %d", __func__, authenticated); + mm_request_send(sock, MONITOR_ANS_JPAKE_CHECK_CONFIRM, m); + + monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP1, 1); + + auth_method = "jpake-01@openssh.com"; + return authenticated; +} + +#endif /* JPAKE */