📄 srv_pipe.c
字号:
goto err_exit; } /* * Now add the RPC_HDR_BA and any auth needed. */ if(!prs_append_prs_data( &outgoing_rpc, &out_hdr_ba)) { DEBUG(0,("api_pipe_alter_context: append of RPC_HDR_BA failed.\n")); goto err_exit; } if (auth_len && !prs_append_prs_data( &outgoing_rpc, &out_auth)) { DEBUG(0,("api_pipe_alter_context: append of auth info failed.\n")); goto err_exit; } /* * Setup the lengths for the initial reply. */ p->out_data.data_sent_length = 0; p->out_data.current_pdu_len = prs_offset(&outgoing_rpc); p->out_data.current_pdu_sent = 0; prs_mem_free(&out_hdr_ba); prs_mem_free(&out_auth); return True; err_exit: prs_mem_free(&outgoing_rpc); prs_mem_free(&out_hdr_ba); prs_mem_free(&out_auth); return setup_bind_nak(p);}/**************************************************************************** Deal with NTLMSSP sign & seal processing on an RPC request.****************************************************************************/BOOL api_pipe_ntlmssp_auth_process(pipes_struct *p, prs_struct *rpc_in, uint32 *p_ss_padding_len, NTSTATUS *pstatus){ RPC_HDR_AUTH auth_info; uint32 auth_len = p->hdr.auth_len; uint32 save_offset = prs_offset(rpc_in); AUTH_NTLMSSP_STATE *a = p->auth.a_u.auth_ntlmssp_state; unsigned char *data = NULL; size_t data_len; unsigned char *full_packet_data = NULL; size_t full_packet_data_len; DATA_BLOB auth_blob; *pstatus = NT_STATUS_OK; if (p->auth.auth_level == PIPE_AUTH_LEVEL_NONE || p->auth.auth_level == PIPE_AUTH_LEVEL_CONNECT) { return True; } if (!a) { *pstatus = NT_STATUS_INVALID_PARAMETER; return False; } /* Ensure there's enough data for an authenticated request. */ if ((auth_len > RPC_MAX_SIGN_SIZE) || (RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_HDR_AUTH_LEN + auth_len > p->hdr.frag_len)) { DEBUG(0,("api_pipe_ntlmssp_auth_process: auth_len %u is too large.\n", (unsigned int)auth_len )); *pstatus = NT_STATUS_INVALID_PARAMETER; return False; } /* * We need the full packet data + length (minus auth stuff) as well as the packet data + length * after the RPC header. * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal * functions as NTLMv2 checks the rpc headers also. */ data = (unsigned char *)(prs_data_p(rpc_in) + RPC_HDR_REQ_LEN); data_len = (size_t)(p->hdr.frag_len - RPC_HEADER_LEN - RPC_HDR_REQ_LEN - RPC_HDR_AUTH_LEN - auth_len); full_packet_data = p->in_data.current_in_pdu; full_packet_data_len = p->hdr.frag_len - auth_len; /* Pull the auth header and the following data into a blob. */ if(!prs_set_offset(rpc_in, RPC_HDR_REQ_LEN + data_len)) { DEBUG(0,("api_pipe_ntlmssp_auth_process: cannot move offset to %u.\n", (unsigned int)RPC_HDR_REQ_LEN + (unsigned int)data_len )); *pstatus = NT_STATUS_INVALID_PARAMETER; return False; } if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, rpc_in, 0)) { DEBUG(0,("api_pipe_ntlmssp_auth_process: failed to unmarshall RPC_HDR_AUTH.\n")); *pstatus = NT_STATUS_INVALID_PARAMETER; return False; } auth_blob.data = (unsigned char *)prs_data_p(rpc_in) + prs_offset(rpc_in); auth_blob.length = auth_len; switch (p->auth.auth_level) { case PIPE_AUTH_LEVEL_PRIVACY: /* Data is encrypted. */ *pstatus = ntlmssp_unseal_packet(a->ntlmssp_state, data, data_len, full_packet_data, full_packet_data_len, &auth_blob); if (!NT_STATUS_IS_OK(*pstatus)) { return False; } break; case PIPE_AUTH_LEVEL_INTEGRITY: /* Data is signed. */ *pstatus = ntlmssp_check_packet(a->ntlmssp_state, data, data_len, full_packet_data, full_packet_data_len, &auth_blob); if (!NT_STATUS_IS_OK(*pstatus)) { return False; } break; default: *pstatus = NT_STATUS_INVALID_PARAMETER; return False; } /* * Return the current pointer to the data offset. */ if(!prs_set_offset(rpc_in, save_offset)) { DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n", (unsigned int)save_offset )); *pstatus = NT_STATUS_INVALID_PARAMETER; return False; } /* * Remember the padding length. We must remove it from the real data * stream once the sign/seal is done. */ *p_ss_padding_len = auth_info.auth_pad_len; return True;}/**************************************************************************** Deal with schannel processing on an RPC request.****************************************************************************/BOOL api_pipe_schannel_process(pipes_struct *p, prs_struct *rpc_in, uint32 *p_ss_padding_len){ uint32 data_len; uint32 auth_len; uint32 save_offset = prs_offset(rpc_in); RPC_HDR_AUTH auth_info; RPC_AUTH_SCHANNEL_CHK schannel_chk; auth_len = p->hdr.auth_len; if (auth_len != RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN) { DEBUG(0,("Incorrect auth_len %u.\n", (unsigned int)auth_len )); return False; } /* * The following is that length of the data we must verify or unseal. * This doesn't include the RPC headers or the auth_len or the RPC_HDR_AUTH_LEN * preceeding the auth_data. */ if (p->hdr.frag_len < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_HDR_AUTH_LEN + auth_len) { DEBUG(0,("Incorrect frag %u, auth %u.\n", (unsigned int)p->hdr.frag_len, (unsigned int)auth_len )); return False; } data_len = p->hdr.frag_len - RPC_HEADER_LEN - RPC_HDR_REQ_LEN - RPC_HDR_AUTH_LEN - auth_len; DEBUG(5,("data %d auth %d\n", data_len, auth_len)); if(!prs_set_offset(rpc_in, RPC_HDR_REQ_LEN + data_len)) { DEBUG(0,("cannot move offset to %u.\n", (unsigned int)RPC_HDR_REQ_LEN + data_len )); return False; } if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, rpc_in, 0)) { DEBUG(0,("failed to unmarshall RPC_HDR_AUTH.\n")); return False; } if (auth_info.auth_type != RPC_SCHANNEL_AUTH_TYPE) { DEBUG(0,("Invalid auth info %d on schannel\n", auth_info.auth_type)); return False; } if(!smb_io_rpc_auth_schannel_chk("", RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN, &schannel_chk, rpc_in, 0)) { DEBUG(0,("failed to unmarshal RPC_AUTH_SCHANNEL_CHK.\n")); return False; } if (!schannel_decode(p->auth.a_u.schannel_auth, p->auth.auth_level, SENDER_IS_INITIATOR, &schannel_chk, prs_data_p(rpc_in)+RPC_HDR_REQ_LEN, data_len)) { DEBUG(3,("failed to decode PDU\n")); return False; } /* * Return the current pointer to the data offset. */ if(!prs_set_offset(rpc_in, save_offset)) { DEBUG(0,("failed to set offset back to %u\n", (unsigned int)save_offset )); return False; } /* The sequence number gets incremented on both send and receive. */ p->auth.a_u.schannel_auth->seq_num++; /* * Remember the padding length. We must remove it from the real data * stream once the sign/seal is done. */ *p_ss_padding_len = auth_info.auth_pad_len; return True;}/**************************************************************************** Return a user struct for a pipe user.****************************************************************************/struct current_user *get_current_user(struct current_user *user, pipes_struct *p){ if (p->pipe_bound && (p->auth.auth_type == PIPE_AUTH_TYPE_NTLMSSP || (p->auth.auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP))) { memcpy(user, &p->pipe_user, sizeof(struct current_user)); } else { memcpy(user, ¤t_user, sizeof(struct current_user)); } return user;}/**************************************************************************** Find the set of RPC functions associated with this context_id****************************************************************************/static PIPE_RPC_FNS* find_pipe_fns_by_context( PIPE_RPC_FNS *list, uint32 context_id ){ PIPE_RPC_FNS *fns = NULL; PIPE_RPC_FNS *tmp = NULL; if ( !list ) { DEBUG(0,("find_pipe_fns_by_context: ERROR! No context list for pipe!\n")); return NULL; } for (tmp=list; tmp; tmp=tmp->next ) { if ( tmp->context_id == context_id ) break; } fns = tmp; return fns;}/**************************************************************************** Memory cleanup.****************************************************************************/void free_pipe_rpc_context( PIPE_RPC_FNS *list ){ PIPE_RPC_FNS *tmp = list; PIPE_RPC_FNS *tmp2; while (tmp) { tmp2 = tmp->next; SAFE_FREE(tmp); tmp = tmp2; } return; }/**************************************************************************** Find the correct RPC function to call for this request. If the pipe is authenticated then become the correct UNIX user before doing the call.****************************************************************************/BOOL api_pipe_request(pipes_struct *p){ BOOL ret = False; BOOL changed_user = False; PIPE_RPC_FNS *pipe_fns; if (p->pipe_bound && ((p->auth.auth_type == PIPE_AUTH_TYPE_NTLMSSP) || (p->auth.auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP))) { if(!become_authenticated_pipe_user(p)) { prs_mem_free(&p->out_data.rdata); return False; } changed_user = True; } DEBUG(5, ("Requested \\PIPE\\%s\n", p->name)); /* get the set of RPC functions for this context */ pipe_fns = find_pipe_fns_by_context(p->contexts, p->hdr_req.context_id); if ( pipe_fns ) { set_current_rpc_talloc(p->mem_ctx); ret = api_rpcTNP(p, p->name, pipe_fns->cmds, pipe_fns->n_cmds); set_current_rpc_talloc(NULL); } else { DEBUG(0,("api_pipe_request: No rpc function table associated with context [%d] on pipe [%s]\n", p->hdr_req.context_id, p->name)); } if (changed_user) { unbecome_authenticated_pipe_user(); } return ret;}/******************************************************************* Calls the underlying RPC function for a named pipe. ********************************************************************/BOOL api_rpcTNP(pipes_struct *p, const char *rpc_name, const struct api_struct *api_rpc_cmds, int n_cmds){ int fn_num; fstring name; uint32 offset1, offset2; /* interpret the command */ DEBUG(4,("api_rpcTNP: %s op 0x%x - ", rpc_name, p->hdr_req.opnum)); slprintf(name, sizeof(name)-1, "in_%s", rpc_name); prs_dump(name, p->hdr_req.opnum, &p->in_data.data); for (fn_num = 0; fn_num < n_cmds; fn_num++) { if (api_rpc_cmds[fn_num].opnum == p->hdr_req.opnum && api_rpc_cmds[fn_num].fn != NULL) { DEBUG(3,("api_rpcTNP: rpc command: %s\n", api_rpc_cmds[fn_num].name)); break; } } if (fn_num == n_cmds) { /* * For an unknown RPC just return a fault PDU but * return True to allow RPC's on the pipe to continue * and not put the pipe into fault state. JRA. */ DEBUG(4, ("unknown\n")); setup_fault_pdu(p, NT_STATUS(0x1c010002)); return True; } offset1 = prs_offset(&p->out_data.rdata); DEBUG(6, ("api_rpc_cmds[%d].fn == %p\n", fn_num, api_rpc_cmds[fn_num].fn)); /* do the actual command */ if(!api_rpc_cmds[fn_num].fn(p)) { DEBUG(0,("api_rpcTNP: %s: %s failed.\n", rpc_name, api_rpc_cmds[fn_num].name)); prs_mem_free(&p->out_data.rdata); return False; } if (p->bad_handle_fault_state) { DEBUG(4,("api_rpcTNP: bad handle fault return.\n")); p->bad_handle_fault_state = False; setup_fault_pdu(p, NT_STATUS(0x1C00001A)); return True; } slprintf(name, sizeof(name)-1, "out_%s", rpc_name); offset2 = prs_offset(&p->out_data.rdata); prs_set_offset(&p->out_data.rdata, offset1); prs_dump(name, p->hdr_req.opnum, &p->out_data.rdata); prs_set_offset(&p->out_data.rdata, offset2); DEBUG(5,("api_rpcTNP: called %s successfully\n", rpc_name)); /* Check for buffer underflow in rpc parsing */ if ((DEBUGLEVEL >= 10) && (prs_offset(&p->in_data.data) != prs_data_size(&p->in_data.data))) { size_t data_len = prs_data_size(&p->in_data.data) - prs_offset(&p->in_data.data); char *data = SMB_MALLOC(data_len); DEBUG(10, ("api_rpcTNP: rpc input buffer underflow (parse error?)\n")); if (data) { prs_uint8s(False, "", &p->in_data.data, 0, (unsigned char *)data, (uint32)data_len); SAFE_FREE(data); } } return True;}/**************************************************************************************************************************************/void get_pipe_fns( int idx, struct api_struct **fns, int *n_fns ){ struct api_struct *cmds = NULL; int n_cmds = 0; switch ( idx ) { case PI_LSARPC: lsa_get_pipe_fns( &cmds, &n_cmds ); break; case PI_LSARPC_DS: lsa_ds_get_pipe_fns( &cmds, &n_cmds ); break; case PI_SAMR: samr_get_pipe_fns( &cmds, &n_cmds ); break; case PI_NETLOGON: netlog_get_pipe_fns( &cmds, &n_cmds ); break; case PI_SRVSVC: srvsvc_get_pipe_fns( &cmds, &n_cmds ); break; case PI_WKSSVC: wkssvc_get_pipe_fns( &cmds, &n_cmds ); break; case PI_WINREG: reg_get_pipe_fns( &cmds, &n_cmds ); break; case PI_SPOOLSS: spoolss_get_pipe_fns( &cmds, &n_cmds ); break; case PI_NETDFS: netdfs_get_pipe_fns( &cmds, &n_cmds );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -