📄 srv_pipe.c
字号:
/* Change the incoming request header to a response. */ p->hdr.pkt_type = RPC_RESPONSE; /* Set up rpc header flags. */ if (p->out_data.data_sent_length == 0) { p->hdr.flags = RPC_FLG_FIRST; } else { p->hdr.flags = 0; } /* * Work out how much we can fit in a single PDU. */ data_len_left = prs_offset(&p->out_data.rdata) - p->out_data.data_sent_length; /* * Ensure there really is data left to send. */ if(!data_len_left) { DEBUG(0,("create_next_pdu_noath: no data left to send !\n")); return False; } data_space_available = sizeof(p->out_data.current_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN; /* * The amount we send is the minimum of the available * space and the amount left to send. */ data_len = MIN(data_len_left, data_space_available); /* * Set up the alloc hint. This should be the data left to * send. */ hdr_resp.alloc_hint = data_len_left; /* * Work out if this PDU will be the last. */ if(p->out_data.data_sent_length + data_len >= prs_offset(&p->out_data.rdata)) { p->hdr.flags |= RPC_FLG_LAST; } /* * Set up the header lengths. */ p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len; p->hdr.auth_len = 0; /* * Init the parse struct to point at the outgoing * data. */ prs_init( &outgoing_pdu, 0, p->mem_ctx, MARSHALL); prs_give_memory( &outgoing_pdu, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False); /* Store the header in the data stream. */ if(!smb_io_rpc_hdr("hdr", &p->hdr, &outgoing_pdu, 0)) { DEBUG(0,("create_next_pdu_noath: failed to marshall RPC_HDR.\n")); prs_mem_free(&outgoing_pdu); return False; } if(!smb_io_rpc_hdr_resp("resp", &hdr_resp, &outgoing_pdu, 0)) { DEBUG(0,("create_next_pdu_noath: failed to marshall RPC_HDR_RESP.\n")); prs_mem_free(&outgoing_pdu); return False; } /* Copy the data into the PDU. */ if(!prs_append_some_prs_data(&outgoing_pdu, &p->out_data.rdata, p->out_data.data_sent_length, data_len)) { DEBUG(0,("create_next_pdu_noauth: failed to copy %u bytes of data.\n", (unsigned int)data_len)); prs_mem_free(&outgoing_pdu); return False; } /* * Setup the counts for this PDU. */ p->out_data.data_sent_length += data_len; p->out_data.current_pdu_len = p->hdr.frag_len; p->out_data.current_pdu_sent = 0; prs_mem_free(&outgoing_pdu); return True;}/******************************************************************* Generate the next PDU to be returned from the data in p->rdata. ********************************************************************/BOOL create_next_pdu(pipes_struct *p){ switch(p->auth.auth_level) { case PIPE_AUTH_LEVEL_NONE: case PIPE_AUTH_LEVEL_CONNECT: /* This is incorrect for auth level connect. Fixme. JRA */ return create_next_pdu_noauth(p); default: switch(p->auth.auth_type) { case PIPE_AUTH_TYPE_NTLMSSP: case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: return create_next_pdu_ntlmssp(p); case PIPE_AUTH_TYPE_SCHANNEL: return create_next_pdu_schannel(p); default: break; } } DEBUG(0,("create_next_pdu: invalid internal auth level %u / type %u", (unsigned int)p->auth.auth_level, (unsigned int)p->auth.auth_type)); return False;}/******************************************************************* Process an NTLMSSP authentication response. If this function succeeds, the user has been authenticated and their domain, name and calling workstation stored in the pipe struct.*******************************************************************/static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob){ DATA_BLOB reply; NTSTATUS status; AUTH_NTLMSSP_STATE *a = p->auth.a_u.auth_ntlmssp_state; DEBUG(5,("pipe_ntlmssp_verify_final: checking user details\n")); ZERO_STRUCT(reply); memset(p->user_name, '\0', sizeof(p->user_name)); memset(p->pipe_user_name, '\0', sizeof(p->pipe_user_name)); memset(p->domain, '\0', sizeof(p->domain)); memset(p->wks, '\0', sizeof(p->wks)); /* Set up for non-authenticated user. */ delete_nt_token(&p->pipe_user.nt_user_token); p->pipe_user.ngroups = 0; SAFE_FREE( p->pipe_user.groups); status = auth_ntlmssp_update(a, *p_resp_blob, &reply); /* Don't generate a reply. */ data_blob_free(&reply); if (!NT_STATUS_IS_OK(status)) { return False; } fstrcpy(p->user_name, a->ntlmssp_state->user); fstrcpy(p->pipe_user_name, a->server_info->unix_name); fstrcpy(p->domain, a->ntlmssp_state->domain); fstrcpy(p->wks, a->ntlmssp_state->workstation); DEBUG(5,("pipe_ntlmssp_verify_final: OK: user: %s domain: %s workstation: %s\n", p->user_name, p->domain, p->wks)); /* * Store the UNIX credential data (uid/gid pair) in the pipe structure. */ p->pipe_user.uid = a->server_info->uid; p->pipe_user.gid = a->server_info->gid; /* * Copy the session key from the ntlmssp state. */ data_blob_free(&p->session_key); p->session_key = data_blob(a->ntlmssp_state->session_key.data, a->ntlmssp_state->session_key.length); if (!p->session_key.data) { return False; } p->pipe_user.ngroups = a->server_info->n_groups; if (p->pipe_user.ngroups) { if (!(p->pipe_user.groups = memdup(a->server_info->groups, sizeof(gid_t) * p->pipe_user.ngroups))) { DEBUG(0,("failed to memdup group list to p->pipe_user.groups\n")); return False; } } if (a->server_info->ptok) { p->pipe_user.nt_user_token = dup_nt_token(a->server_info->ptok); } else { DEBUG(1,("Error: Authmodule failed to provide nt_user_token\n")); p->pipe_user.nt_user_token = NULL; return False; } return True;}/******************************************************************* The switch table for the pipe names and the functions to handle them.*******************************************************************/struct rpc_table { struct { const char *clnt; const char *srv; } pipe; struct api_struct *cmds; int n_cmds;};static struct rpc_table *rpc_lookup;static int rpc_lookup_size;/******************************************************************* This is the "stage3" NTLMSSP response after a bind request and reply.*******************************************************************/BOOL api_pipe_bind_auth3(pipes_struct *p, prs_struct *rpc_in_p){ RPC_HDR_AUTH auth_info; uint32 pad; DATA_BLOB blob; ZERO_STRUCT(blob); DEBUG(5,("api_pipe_bind_auth3: decode request. %d\n", __LINE__)); if (p->hdr.auth_len == 0) { DEBUG(0,("api_pipe_bind_auth3: No auth field sent !\n")); goto err; } /* 4 bytes padding. */ if (!prs_uint32("pad", rpc_in_p, 0, &pad)) { DEBUG(0,("api_pipe_bind_auth3: unmarshall of 4 byte pad failed.\n")); goto err; } /* * Decode the authentication verifier response. */ if(!smb_io_rpc_hdr_auth("", &auth_info, rpc_in_p, 0)) { DEBUG(0,("api_pipe_bind_auth3: unmarshall of RPC_HDR_AUTH failed.\n")); goto err; } if (auth_info.auth_type != RPC_NTLMSSP_AUTH_TYPE) { DEBUG(0,("api_pipe_bind_auth3: incorrect auth type (%u).\n", (unsigned int)auth_info.auth_type )); return False; } blob = data_blob(NULL,p->hdr.auth_len); if (!prs_copy_data_out((char *)blob.data, rpc_in_p, p->hdr.auth_len)) { DEBUG(0,("api_pipe_bind_auth3: Failed to pull %u bytes - the response blob.\n", (unsigned int)p->hdr.auth_len )); goto err; } /* * The following call actually checks the challenge/response data. * for correctness against the given DOMAIN\user name. */ if (!pipe_ntlmssp_verify_final(p, &blob)) { goto err; } data_blob_free(&blob); p->pipe_bound = True; return True; err: data_blob_free(&blob); free_pipe_ntlmssp_auth_data(&p->auth); p->auth.a_u.auth_ntlmssp_state = NULL; return False;}/******************************************************************* Marshall a bind_nak pdu.*******************************************************************/static BOOL setup_bind_nak(pipes_struct *p){ prs_struct outgoing_rpc; RPC_HDR nak_hdr; uint16 zero = 0; /* Free any memory in the current return data buffer. */ prs_mem_free(&p->out_data.rdata); /* * Marshall directly into the outgoing PDU space. We * must do this as we need to set to the bind response * header and are never sending more than one PDU here. */ prs_init( &outgoing_rpc, 0, p->mem_ctx, MARSHALL); prs_give_memory( &outgoing_rpc, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False); /* * Initialize a bind_nak header. */ init_rpc_hdr(&nak_hdr, RPC_BINDNACK, RPC_FLG_FIRST | RPC_FLG_LAST, p->hdr.call_id, RPC_HEADER_LEN + sizeof(uint16), 0); /* * Marshall the header into the outgoing PDU. */ if(!smb_io_rpc_hdr("", &nak_hdr, &outgoing_rpc, 0)) { DEBUG(0,("setup_bind_nak: marshalling of RPC_HDR failed.\n")); prs_mem_free(&outgoing_rpc); return False; } /* * Now add the reject reason. */ if(!prs_uint16("reject code", &outgoing_rpc, 0, &zero)) { prs_mem_free(&outgoing_rpc); return False; } p->out_data.data_sent_length = 0; p->out_data.current_pdu_len = prs_offset(&outgoing_rpc); p->out_data.current_pdu_sent = 0; if (p->auth.auth_data_free_func) { (*p->auth.auth_data_free_func)(&p->auth); } p->auth.auth_level = PIPE_AUTH_LEVEL_NONE; p->auth.auth_type = PIPE_AUTH_TYPE_NONE; p->pipe_bound = False; return True;}/******************************************************************* Marshall a fault pdu.*******************************************************************/BOOL setup_fault_pdu(pipes_struct *p, NTSTATUS status){ prs_struct outgoing_pdu; RPC_HDR fault_hdr; RPC_HDR_RESP hdr_resp; RPC_HDR_FAULT fault_resp; /* Free any memory in the current return data buffer. */ prs_mem_free(&p->out_data.rdata); /* * Marshall directly into the outgoing PDU space. We * must do this as we need to set to the bind response * header and are never sending more than one PDU here. */ prs_init( &outgoing_pdu, 0, p->mem_ctx, MARSHALL); prs_give_memory( &outgoing_pdu, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False); /* * Initialize a fault header. */ init_rpc_hdr(&fault_hdr, RPC_FAULT, RPC_FLG_FIRST | RPC_FLG_LAST | RPC_FLG_NOCALL, p->hdr.call_id, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_FAULT_LEN, 0); /* * Initialize the HDR_RESP and FAULT parts of the PDU. */ memset((char *)&hdr_resp, '\0', sizeof(hdr_resp)); fault_resp.status = status; fault_resp.reserved = 0; /* * Marshall the header into the outgoing PDU. */ if(!smb_io_rpc_hdr("", &fault_hdr, &outgoing_pdu, 0)) { DEBUG(0,("setup_fault_pdu: marshalling of RPC_HDR failed.\n")); prs_mem_free(&outgoing_pdu); return False; } if(!smb_io_rpc_hdr_resp("resp", &hdr_resp, &outgoing_pdu, 0)) { DEBUG(0,("setup_fault_pdu: failed to marshall RPC_HDR_RESP.\n")); prs_mem_free(&outgoing_pdu); return False; } if(!smb_io_rpc_hdr_fault("fault", &fault_resp, &outgoing_pdu, 0)) { DEBUG(0,("setup_fault_pdu: failed to marshall RPC_HDR_FAULT.\n")); prs_mem_free(&outgoing_pdu); return False; } p->out_data.data_sent_length = 0; p->out_data.current_pdu_len = prs_offset(&outgoing_pdu); p->out_data.current_pdu_sent = 0; prs_mem_free(&outgoing_pdu); return True;}#if 0/******************************************************************* Marshall a cancel_ack pdu. We should probably check the auth-verifier here.*******************************************************************/BOOL setup_cancel_ack_reply(pipes_struct *p, prs_struct *rpc_in_p){ prs_struct outgoing_pdu; RPC_HDR ack_reply_hdr; /* Free any memory in the current return data buffer. */ prs_mem_free(&p->out_data.rdata); /* * Marshall directly into the outgoing PDU space. We * must do this as we need to set to the bind response * header and are never sending more than one PDU here. */ prs_init( &outgoing_pdu, 0, p->mem_ctx, MARSHALL); prs_give_memory( &outgoing_pdu, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False); /* * Initialize a cancel_ack header. */ init_rpc_hdr(&ack_reply_hdr, RPC_CANCEL_ACK, RPC_FLG_FIRST | RPC_FLG_LAST, p->hdr.call_id, RPC_HEADER_LEN, 0); /* * Marshall the header into the outgoing PDU. */ if(!smb_io_rpc_hdr("", &ack_reply_hdr, &outgoing_pdu, 0)) { DEBUG(0,("setup_cancel_ack_reply: marshalling of RPC_HDR failed.\n")); prs_mem_free(&outgoing_pdu); return False; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -