📄 monitor.c
字号:
mm_request_send(sock, MONITOR_ANS_RSACHALLENGE, m); monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 1); xfree(blob); key_free(key); return (0);}intmm_answer_rsa_response(int sock, Buffer *m){ Key *key = NULL; u_char *blob, *response; u_int blen, len; int success; debug3("%s entering", __func__); if (!authctxt->valid) fatal("%s: authctxt not valid", __func__); if (ssh1_challenge == NULL) fatal("%s: no ssh1_challenge", __func__); blob = buffer_get_string(m, &blen); if (!monitor_allowed_key(blob, blen)) fatal("%s: bad key, not previously allowed", __func__); if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY) fatal("%s: key type mismatch: %d", __func__, key_blobtype); if ((key = key_from_blob(blob, blen)) == NULL) fatal("%s: received bad key", __func__); response = buffer_get_string(m, &len); if (len != 16) fatal("%s: received bad response to challenge", __func__); success = auth_rsa_verify_response(key, ssh1_challenge, response); xfree(blob); key_free(key); xfree(response); auth_method = key_blobtype == MM_RSAUSERKEY ? "rsa" : "rhosts-rsa"; /* reset state */ BN_clear_free(ssh1_challenge); ssh1_challenge = NULL; monitor_reset_key_state(); buffer_clear(m); buffer_put_int(m, success); mm_request_send(sock, MONITOR_ANS_RSARESPONSE, m); return (success);}intmm_answer_term(int sock, Buffer *req){ extern struct monitor *pmonitor; int res, status; debug3("%s: tearing down sessions", __func__); /* The child is terminating */ session_destroy_all(&mm_session_close); while (waitpid(pmonitor->m_pid, &status, 0) == -1) if (errno != EINTR) exit(1); res = WIFEXITED(status) ? WEXITSTATUS(status) : 1; /* Terminate process */ exit(res);}#ifdef SSH_AUDIT_EVENTS/* Report that an audit event occurred */intmm_answer_audit_event(int socket, Buffer *m){ ssh_audit_event_t event; debug3("%s entering", __func__); event = buffer_get_int(m); buffer_free(m); switch(event) { case SSH_AUTH_FAIL_PUBKEY: case SSH_AUTH_FAIL_HOSTBASED: case SSH_AUTH_FAIL_GSSAPI: case SSH_LOGIN_EXCEED_MAXTRIES: case SSH_LOGIN_ROOT_DENIED: case SSH_CONNECTION_CLOSE: case SSH_INVALID_USER: audit_event(event); break; default: fatal("Audit event type %d not permitted", event); } return (0);}intmm_answer_audit_command(int socket, Buffer *m){ u_int len; char *cmd; debug3("%s entering", __func__); cmd = buffer_get_string(m, &len); /* sanity check command, if so how? */ audit_run_command(cmd); xfree(cmd); buffer_free(m); return (0);}#endif /* SSH_AUDIT_EVENTS */voidmonitor_apply_keystate(struct monitor *pmonitor){ if (compat20) { set_newkeys(MODE_IN); set_newkeys(MODE_OUT); } else { packet_set_protocol_flags(child_state.ssh1protoflags); packet_set_encryption_key(child_state.ssh1key, child_state.ssh1keylen, child_state.ssh1cipher); xfree(child_state.ssh1key); } /* for rc4 and other stateful ciphers */ packet_set_keycontext(MODE_OUT, child_state.keyout); xfree(child_state.keyout); packet_set_keycontext(MODE_IN, child_state.keyin); xfree(child_state.keyin); if (!compat20) { packet_set_iv(MODE_OUT, child_state.ivout); xfree(child_state.ivout); packet_set_iv(MODE_IN, child_state.ivin); xfree(child_state.ivin); } memcpy(&incoming_stream, &child_state.incoming, sizeof(incoming_stream)); memcpy(&outgoing_stream, &child_state.outgoing, sizeof(outgoing_stream)); /* Update with new address */ if (options.compression) mm_init_compression(pmonitor->m_zlib); /* 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); memset(child_state.input, 0, child_state.ilen); xfree(child_state.input); buffer_clear(&output); buffer_append(&output, child_state.output, child_state.olen); memset(child_state.output, 0, child_state.olen); xfree(child_state.output);}static Kex *mm_get_kex(Buffer *m){ Kex *kex; void *blob; u_int bloblen; kex = xmalloc(sizeof(*kex)); memset(kex, 0, sizeof(*kex)); kex->session_id = buffer_get_string(m, &kex->session_id_len); if ((session_id2 == NULL) || (kex->session_id_len != session_id2_len) || (memcmp(kex->session_id, session_id2, session_id2_len) != 0)) fatal("mm_get_get: internal error: bad session id"); kex->we_need = buffer_get_int(m); kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; kex->server = 1; kex->hostkey_type = buffer_get_int(m); kex->kex_type = buffer_get_int(m); blob = buffer_get_string(m, &bloblen); buffer_init(&kex->my); buffer_append(&kex->my, blob, bloblen); xfree(blob); blob = buffer_get_string(m, &bloblen); buffer_init(&kex->peer); buffer_append(&kex->peer, blob, bloblen); xfree(blob); kex->done = 1; kex->flags = buffer_get_int(m); kex->client_version_string = buffer_get_string(m, NULL); kex->server_version_string = buffer_get_string(m, NULL); kex->load_host_key=&get_hostkey_by_type; kex->host_key_index=&get_hostkey_index; return (kex);}/* This function requries careful sanity checking */voidmm_get_keystate(struct monitor *pmonitor){ Buffer m; u_char *blob, *p; u_int bloblen, plen; u_int32_t seqnr, packets; u_int64_t blocks; debug3("%s: Waiting for new keys", __func__); buffer_init(&m); mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, &m); if (!compat20) { child_state.ssh1protoflags = buffer_get_int(&m); child_state.ssh1cipher = buffer_get_int(&m); child_state.ssh1key = buffer_get_string(&m, &child_state.ssh1keylen); child_state.ivout = buffer_get_string(&m, &child_state.ivoutlen); child_state.ivin = buffer_get_string(&m, &child_state.ivinlen); goto skip; } else { /* Get the Kex for rekeying */ *pmonitor->m_pkex = mm_get_kex(&m); } blob = buffer_get_string(&m, &bloblen); current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen); xfree(blob); debug3("%s: Waiting for second key", __func__); blob = buffer_get_string(&m, &bloblen); current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen); xfree(blob); /* Now get sequence numbers for the packets */ seqnr = buffer_get_int(&m); blocks = buffer_get_int64(&m); packets = buffer_get_int(&m); packet_set_state(MODE_OUT, seqnr, blocks, packets); seqnr = buffer_get_int(&m); blocks = buffer_get_int64(&m); packets = buffer_get_int(&m); packet_set_state(MODE_IN, seqnr, blocks, packets); skip: /* Get the key context */ child_state.keyout = buffer_get_string(&m, &child_state.keyoutlen); child_state.keyin = buffer_get_string(&m, &child_state.keyinlen); debug3("%s: Getting compression state", __func__); /* Get compression state */ p = buffer_get_string(&m, &plen); if (plen != sizeof(child_state.outgoing)) fatal("%s: bad request size", __func__); memcpy(&child_state.outgoing, p, sizeof(child_state.outgoing)); xfree(p); p = buffer_get_string(&m, &plen); if (plen != sizeof(child_state.incoming)) fatal("%s: bad request size", __func__); memcpy(&child_state.incoming, p, sizeof(child_state.incoming)); xfree(p); /* Network I/O buffers */ debug3("%s: Getting Network I/O buffers", __func__); child_state.input = buffer_get_string(&m, &child_state.ilen); child_state.output = buffer_get_string(&m, &child_state.olen); buffer_free(&m);}/* Allocation functions for zlib */void *mm_zalloc(struct mm_master *mm, u_int ncount, u_int size){ size_t len = (size_t) size * ncount; void *address; if (len == 0 || ncount > SIZE_T_MAX / size) fatal("%s: mm_zalloc(%u, %u)", __func__, ncount, size); address = mm_malloc(mm, len); return (address);}voidmm_zfree(struct mm_master *mm, void *address){ mm_free(mm, address);}voidmm_init_compression(struct mm_master *mm){ outgoing_stream.zalloc = (alloc_func)mm_zalloc; outgoing_stream.zfree = (free_func)mm_zfree; outgoing_stream.opaque = mm; incoming_stream.zalloc = (alloc_func)mm_zalloc; incoming_stream.zfree = (free_func)mm_zfree; incoming_stream.opaque = mm;}/* XXX */#define FD_CLOSEONEXEC(x) do { \ if (fcntl(x, F_SETFD, 1) == -1) \ fatal("fcntl(%d, F_SETFD)", x); \} while (0)static voidmonitor_socketpair(int *pair){#ifdef HAVE_SOCKETPAIR if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) fatal("%s: socketpair", __func__);#else fatal("%s: UsePrivilegeSeparation=yes not supported", __func__);#endif FD_CLOSEONEXEC(pair[0]); FD_CLOSEONEXEC(pair[1]);}#define MM_MEMSIZE 65536struct monitor *monitor_init(void){ struct monitor *mon; int pair[2]; mon = xmalloc(sizeof(*mon)); mon->m_pid = 0; monitor_socketpair(pair); mon->m_recvfd = pair[0]; mon->m_sendfd = pair[1]; /* Used to share zlib space across processes */ if (options.compression) { mon->m_zback = mm_create(NULL, MM_MEMSIZE); mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE); /* Compression needs to share state across borders */ mm_init_compression(mon->m_zlib); } return mon;}voidmonitor_reinit(struct monitor *mon){ int pair[2]; monitor_socketpair(pair); mon->m_recvfd = pair[0]; mon->m_sendfd = pair[1];}#ifdef GSSAPIintmm_answer_gss_setup_ctx(int sock, Buffer *m){ gss_OID_desc goid; OM_uint32 major; u_int len; goid.elements = buffer_get_string(m, &len); goid.length = len; major = ssh_gssapi_server_ctx(&gsscontext, &goid); xfree(goid.elements); buffer_clear(m); buffer_put_int(m, major); mm_request_send(sock,MONITOR_ANS_GSSSETUP, m); /* Now we have a context, enable the step */ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 1); return (0);}intmm_answer_gss_accept_ctx(int sock, Buffer *m){ gss_buffer_desc in; gss_buffer_desc out = GSS_C_EMPTY_BUFFER; OM_uint32 major,minor; OM_uint32 flags = 0; /* GSI needs this */ u_int len; in.value = buffer_get_string(m, &len); in.length = len; major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags); xfree(in.value); buffer_clear(m); buffer_put_int(m, major); buffer_put_string(m, out.value, out.length); buffer_put_int(m, flags); mm_request_send(sock, MONITOR_ANS_GSSSTEP, m); gss_release_buffer(&minor, &out); if (major==GSS_S_COMPLETE) { monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); } return (0);}intmm_answer_gss_checkmic(int sock, Buffer *m){ gss_buffer_desc gssbuf, mic; OM_uint32 ret; u_int len; gssbuf.value = buffer_get_string(m, &len); gssbuf.length = len; mic.value = buffer_get_string(m, &len); mic.length = len; ret = ssh_gssapi_checkmic(gsscontext, &gssbuf, &mic); xfree(gssbuf.value); xfree(mic.value); buffer_clear(m); buffer_put_int(m, ret); mm_request_send(sock, MONITOR_ANS_GSSCHECKMIC, m); if (!GSS_ERROR(ret)) monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); return (0);}intmm_answer_gss_userok(int sock, Buffer *m){ int authenticated; authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); buffer_clear(m); buffer_put_int(m, authenticated); debug3("%s: sending result %d", __func__, authenticated); mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m); auth_method="gssapi-with-mic"; /* Monitor loop will terminate if authenticated */ return (authenticated);}#endif /* GSSAPI */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -