diff options
-rw-r--r-- | source3/include/ntdomain.h | 3 | ||||
-rw-r--r-- | source3/include/proto.h | 8 | ||||
-rw-r--r-- | source3/rpc_server/srv_pipe.c | 275 | ||||
-rw-r--r-- | source3/rpc_server/srv_pipe_hnd.c | 509 |
4 files changed, 406 insertions, 389 deletions
diff --git a/source3/include/ntdomain.h b/source3/include/ntdomain.h index e96b9b553a..18819dee21 100644 --- a/source3/include/ntdomain.h +++ b/source3/include/ntdomain.h @@ -222,6 +222,9 @@ typedef struct pipes_struct { /* handle database to use on this pipe. */ struct handle_list *pipe_handles; + /* call id retrieved from the pdu header */ + uint32_t call_id; + /* operation number retrieved from the rpc header */ uint16_t opnum; diff --git a/source3/include/proto.h b/source3/include/proto.h index 1b8aa485d5..6bc656824d 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -5156,7 +5156,7 @@ void *_policy_handle_find(struct pipes_struct *p, /* The following definitions come from rpc_server/srv_pipe.c */ bool create_next_pdu(pipes_struct *p); -bool api_pipe_bind_auth3(pipes_struct *p, prs_struct *rpc_in_p); +bool api_pipe_bind_auth3(pipes_struct *p, struct ncacn_packet *pkt); bool setup_fault_pdu(pipes_struct *p, NTSTATUS status); NTSTATUS rpc_pipe_register_commands(int version, const char *clnt, const char *srv, @@ -5167,13 +5167,13 @@ NTSTATUS rpc_srv_register(int version, const char *clnt, const struct ndr_interface_table *iface, const struct api_struct *cmds, int size); bool is_known_pipename(const char *cli_filename, struct ndr_syntax_id *syntax); -bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p); -bool api_pipe_alter_context(pipes_struct *p, prs_struct *rpc_in_p); +bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt); +bool api_pipe_alter_context(pipes_struct *p, struct ncacn_packet *pkt); bool api_pipe_ntlmssp_auth_process(pipes_struct *p, prs_struct *rpc_in, uint32 *p_ss_padding_len, NTSTATUS *pstatus); bool api_pipe_schannel_process(pipes_struct *p, prs_struct *rpc_in, uint32 *p_ss_padding_len); void free_pipe_rpc_context( PIPE_RPC_FNS *list ); -bool api_pipe_request(pipes_struct *p); +bool api_pipe_request(pipes_struct *p, struct ncacn_packet *pkt); /* The following definitions come from rpc_server/srv_pipe_hnd.c */ diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index e3ab09d8db..74c67f3832 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -160,7 +160,7 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p) data_len + ss_padding_len + RPC_HDR_AUTH_LEN + NTLMSSP_SIG_SIZE, NTLMSSP_SIG_SIZE, - p->hdr.call_id, + p->call_id, &hdr); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to marshall RPC Header.\n")); @@ -396,7 +396,7 @@ static bool create_next_pdu_schannel(pipes_struct *p) RPC_HDR_AUTH_LEN + RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN, RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN, - p->hdr.call_id, + p->call_id, &hdr); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to marshall RPC Header.\n")); @@ -603,7 +603,7 @@ static bool create_next_pdu_noauth(pipes_struct *p) hdr_flags, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len, 0, - p->hdr.call_id, + p->call_id, &hdr); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to marshall RPC Header.\n")); @@ -769,12 +769,10 @@ static bool pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob) 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) +bool api_pipe_bind_auth3(pipes_struct *p, struct ncacn_packet *pkt) { struct dcerpc_auth auth_info; - uint32 pad = 0; - DATA_BLOB auth_blob; - uint32_t auth_len = p->hdr.auth_len; + uint32_t auth_len = pkt->auth_length; NTSTATUS status; DEBUG(5,("api_pipe_bind_auth3: decode request. %d\n", __LINE__)); @@ -784,15 +782,9 @@ bool api_pipe_bind_auth3(pipes_struct *p, prs_struct *rpc_in_p) 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; - } - /* Ensure there's enough data for an authenticated request. */ if (RPC_HEADER_LEN + RPC_HDR_AUTH_LEN + auth_len > - p->hdr.frag_len) { + pkt->frag_length) { DEBUG(0,("api_pipe_ntlmssp_auth_process: auth_len " "%u is too large.\n", (unsigned int)auth_len )); @@ -803,28 +795,9 @@ bool api_pipe_bind_auth3(pipes_struct *p, prs_struct *rpc_in_p) * Decode the authentication verifier response. */ - /* Pull the auth header and the following data into a blob. */ - /* NB. The offset of the auth_header is relative to the *end* - * of the packet, not the start. Also, the length of the - * data in rpc_in_p is p->hdr.frag_len - RPC_HEADER_LEN, - * as the RPC header isn't included in rpc_in_p. */ - if(!prs_set_offset(rpc_in_p, - p->hdr.frag_len - RPC_HEADER_LEN - - RPC_HDR_AUTH_LEN - auth_len)) { - DEBUG(0,("api_pipe_bind_auth3: cannot move " - "offset to %u.\n", - (unsigned int)(p->hdr.frag_len - - RPC_HDR_AUTH_LEN - auth_len) )); - goto err; - } - - auth_blob = data_blob_const(prs_data_p(rpc_in_p) - + prs_offset(rpc_in_p), - prs_data_size(rpc_in_p) - - prs_offset(rpc_in_p)); - - status = dcerpc_pull_dcerpc_auth(prs_get_mem_context(rpc_in_p), - &auth_blob, &auth_info); + status = dcerpc_pull_dcerpc_auth(pkt, + &pkt->u.auth3.auth_info, + &auth_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to unmarshall dcerpc_auth.\n")); goto err; @@ -896,7 +869,7 @@ static bool setup_bind_nak(pipes_struct *p) DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST, 0, - p->hdr.call_id, + p->call_id, u, &blob); if (!NT_STATUS_IS_OK(status)) { @@ -959,7 +932,7 @@ bool setup_fault_pdu(pipes_struct *p, NTSTATUS fault_status) DCERPC_PFC_FLAG_LAST | DCERPC_PFC_FLAG_DID_NOT_EXECUTE, 0, - p->hdr.call_id, + p->call_id, u, &blob); if (!NT_STATUS_IS_OK(status)) { @@ -1073,7 +1046,6 @@ bool is_known_pipename(const char *cli_filename, struct ndr_syntax_id *syntax) *******************************************************************/ static bool pipe_spnego_auth_bind_kerberos(pipes_struct *p, - prs_struct *rpc_in_p, struct dcerpc_auth *pauth_info, DATA_BLOB *psecblob, prs_struct *pout_auth) @@ -1086,7 +1058,6 @@ static bool pipe_spnego_auth_bind_kerberos(pipes_struct *p, *******************************************************************/ static bool pipe_spnego_auth_bind_negotiate(pipes_struct *p, - prs_struct *rpc_in_p, uint32_t ss_padding_len, struct dcerpc_auth *pauth_info, prs_struct *pout_auth) @@ -1126,7 +1097,9 @@ static bool pipe_spnego_auth_bind_negotiate(pipes_struct *p, DEBUG(3,("pipe_spnego_auth_bind_negotiate: Got secblob of size %lu\n", (unsigned long)secblob.length)); if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || USE_KERBEROS_KEYTAB) ) { - bool ret = pipe_spnego_auth_bind_kerberos(p, rpc_in_p, pauth_info, &secblob, pout_auth); + bool ret; + ret = pipe_spnego_auth_bind_kerberos(p, pauth_info, + &secblob, pout_auth); data_blob_free(&secblob); return ret; } @@ -1225,18 +1198,17 @@ static bool pipe_spnego_auth_bind_negotiate(pipes_struct *p, Handle the second part of a SPNEGO bind auth. *******************************************************************/ -static bool pipe_spnego_auth_bind_continue(pipes_struct *p, prs_struct *rpc_in_p, - uint32_t ss_padding_len, - RPC_HDR_AUTH *pauth_info, prs_struct *pout_auth) +static bool pipe_spnego_auth_bind_continue(pipes_struct *p, + uint32_t ss_padding_len, + struct dcerpc_auth *pauth_info, + prs_struct *pout_auth) { RPC_HDR_AUTH auth_info; - DATA_BLOB spnego_blob; DATA_BLOB auth_blob; DATA_BLOB auth_reply; DATA_BLOB response; struct auth_ntlmssp_state *a = p->auth.a_u.auth_ntlmssp_state; - ZERO_STRUCT(spnego_blob); ZERO_STRUCT(auth_blob); ZERO_STRUCT(auth_reply); ZERO_STRUCT(response); @@ -1250,21 +1222,12 @@ static bool pipe_spnego_auth_bind_continue(pipes_struct *p, prs_struct *rpc_in_p goto err; } - /* Grab the SPNEGO blob. */ - spnego_blob = data_blob(NULL,p->hdr.auth_len); - - if (!prs_copy_data_out((char *)spnego_blob.data, rpc_in_p, p->hdr.auth_len)) { - DEBUG(0,("pipe_spnego_auth_bind_continue: Failed to pull %u bytes - the SPNEGO auth header.\n", - (unsigned int)p->hdr.auth_len )); - goto err; - } - - if (spnego_blob.data[0] != ASN1_CONTEXT(1)) { + if (pauth_info->credentials.data[0] != ASN1_CONTEXT(1)) { DEBUG(0,("pipe_spnego_auth_bind_continue: invalid SPNEGO blob type.\n")); goto err; } - if (!spnego_parse_auth(spnego_blob, &auth_blob)) { + if (!spnego_parse_auth(pauth_info->credentials, &auth_blob)) { DEBUG(0,("pipe_spnego_auth_bind_continue: invalid SPNEGO blob.\n")); goto err; } @@ -1278,7 +1241,6 @@ static bool pipe_spnego_auth_bind_continue(pipes_struct *p, prs_struct *rpc_in_p goto err; } - data_blob_free(&spnego_blob); data_blob_free(&auth_blob); /* Generate the spnego "accept completed" blob - no incoming data. */ @@ -1308,7 +1270,6 @@ static bool pipe_spnego_auth_bind_continue(pipes_struct *p, prs_struct *rpc_in_p err: - data_blob_free(&spnego_blob); data_blob_free(&auth_blob); data_blob_free(&auth_reply); data_blob_free(&response); @@ -1324,7 +1285,6 @@ static bool pipe_spnego_auth_bind_continue(pipes_struct *p, prs_struct *rpc_in_p *******************************************************************/ static bool pipe_schannel_auth_bind(pipes_struct *p, - prs_struct *rpc_in_p, uint32_t ss_padding_len, struct dcerpc_auth *auth_info, prs_struct *pout_auth) @@ -1463,7 +1423,6 @@ static bool pipe_schannel_auth_bind(pipes_struct *p, *******************************************************************/ static bool pipe_ntlmssp_auth_bind(pipes_struct *p, - prs_struct *rpc_in_p, uint32_t ss_padding_len, struct dcerpc_auth *auth_info, prs_struct *pout_auth) @@ -1548,13 +1507,11 @@ static bool pipe_ntlmssp_auth_bind(pipes_struct *p, Respond to a pipe bind request. *******************************************************************/ -bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) +bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt) { + RPC_HDR hdr; RPC_HDR_BA hdr_ba; - struct dcerpc_bind rpc_bind; - DATA_BLOB blob_rb; struct dcerpc_auth auth_info; - DATA_BLOB auth_blob; uint16 assoc_gid; fstring ack_pipe_name; prs_struct out_hdr_ba; @@ -1599,17 +1556,7 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) return False; } - DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__)); - - /* decode the bind request */ - blob_rb = data_blob_const(prs_data_p(rpc_in_p), - prs_data_size(rpc_in_p)); - status = dcerpc_pull_dcerpc_bind(talloc_tos(), &blob_rb, &rpc_bind); - if (!NT_STATUS_IS_OK(status)) { - goto err_exit; - } - - if (rpc_bind.num_contexts == 0) { + if (pkt->u.bind.num_contexts == 0) { DEBUG(0, ("api_pipe_bind_req: no rpc contexts around\n")); goto err_exit; } @@ -1618,7 +1565,7 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) * Try and find the correct pipe name to ensure * that this is a pipe name we support. */ - id = rpc_bind.ctx_list[0].abstract_syntax; + id = pkt->u.bind.ctx_list[0].abstract_syntax; if (rpc_srv_pipe_exists_by_id(&id)) { DEBUG(3, ("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n", rpc_srv_get_pipe_cli_name(&id), @@ -1627,13 +1574,13 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) status = smb_probe_module( "rpc", get_pipe_name_from_syntax( talloc_tos(), - &rpc_bind.ctx_list[0].abstract_syntax)); + &pkt->u.bind.ctx_list[0].abstract_syntax)); if (NT_STATUS_IS_ERR(status)) { DEBUG(3,("api_pipe_bind_req: Unknown pipe name %s in bind request.\n", get_pipe_name_from_syntax( talloc_tos(), - &rpc_bind.ctx_list[0].abstract_syntax))); + &pkt->u.bind.ctx_list[0].abstract_syntax))); prs_mem_free(&p->out_data.frag); prs_mem_free(&out_hdr_ba); prs_mem_free(&out_auth); @@ -1665,8 +1612,8 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__)); - if (rpc_bind.assoc_group_id != 0) { - assoc_gid = rpc_bind.assoc_group_id; + if (pkt->u.bind.assoc_group_id != 0) { + assoc_gid = pkt->u.bind.assoc_group_id; } else { assoc_gid = 0x53f0; } @@ -1683,16 +1630,16 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) Needed when adding entries to a DACL from NT5 - SK */ if (check_bind_req(p, - &rpc_bind.ctx_list[0].abstract_syntax, - &rpc_bind.ctx_list[0].transfer_syntaxes[0], - rpc_bind.ctx_list[0].context_id)) { + &pkt->u.bind.ctx_list[0].abstract_syntax, + &pkt->u.bind.ctx_list[0].transfer_syntaxes[0], + pkt->u.bind.ctx_list[0].context_id)) { init_rpc_hdr_ba(&hdr_ba, RPC_MAX_PDU_FRAG_LEN, RPC_MAX_PDU_FRAG_LEN, assoc_gid, ack_pipe_name, 0x1, 0x0, 0x0, - &rpc_bind.ctx_list[0].transfer_syntaxes[0]); + &pkt->u.bind.ctx_list[0].transfer_syntaxes[0]); } else { /* Rejection reason: abstract syntax not supported */ init_rpc_hdr_ba(&hdr_ba, RPC_MAX_PDU_FRAG_LEN, @@ -1715,7 +1662,7 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) * Check if this is an authenticated bind request. */ - if (p->hdr.auth_len) { + if (pkt->auth_length) { /* * Decode the authentication verifier. */ @@ -1731,36 +1678,19 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) /* Quick length check. Won't catch a bad auth footer, * prevents overrun. */ - if (p->hdr.frag_len < RPC_HEADER_LEN + RPC_HDR_AUTH_LEN + p->hdr.auth_len) { + if (pkt->frag_length < RPC_HEADER_LEN + + RPC_HDR_AUTH_LEN + + pkt->auth_length) { DEBUG(0,("api_pipe_bind_req: auth_len (%u) " "too long for fragment %u.\n", - (unsigned int)p->hdr.auth_len, - (unsigned int)p->hdr.frag_len )); - goto err_exit; - } - - /* Pull the auth header and the following data into a blob. */ - /* NB. The offset of the auth_header is relative to the *end* - * of the packet, not the start. Also, the length of the - * data in rpc_in_p is p->hdr.frag_len - RPC_HEADER_LEN, - * as the RPC header isn't included in rpc_in_p. */ - if(!prs_set_offset(rpc_in_p, - p->hdr.frag_len - RPC_HEADER_LEN - - RPC_HDR_AUTH_LEN - p->hdr.auth_len)) { - DEBUG(0,("api_pipe_bind_req: cannot move " - "offset to %u.\n", - (unsigned int)(p->hdr.frag_len - - RPC_HDR_AUTH_LEN - p->hdr.auth_len) )); + (unsigned int)pkt->auth_length, + (unsigned int)pkt->frag_length)); goto err_exit; } - auth_blob = data_blob_const(prs_data_p(rpc_in_p) - + prs_offset(rpc_in_p), - prs_data_size(rpc_in_p) - - prs_offset(rpc_in_p)); - - status = dcerpc_pull_dcerpc_auth(prs_get_mem_context(rpc_in_p), - &auth_blob, &auth_info); + status = dcerpc_pull_dcerpc_auth(pkt, + &pkt->u.bind.auth_info, + &auth_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Unable to unmarshall dcerpc_auth.\n")); goto err_exit; @@ -1787,23 +1717,24 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) switch(auth_type) { case DCERPC_AUTH_TYPE_NTLMSSP: - if (!pipe_ntlmssp_auth_bind(p, rpc_in_p, - ss_padding_len, &auth_info, &out_auth)) { + if (!pipe_ntlmssp_auth_bind(p, ss_padding_len, + &auth_info, &out_auth)) { goto err_exit; } assoc_gid = 0x7a77; break; case DCERPC_AUTH_TYPE_SCHANNEL: - if (!pipe_schannel_auth_bind(p, rpc_in_p, - ss_padding_len, &auth_info, &out_auth)) { + if (!pipe_schannel_auth_bind(p, ss_padding_len, + &auth_info, &out_auth)) { goto err_exit; } break; case DCERPC_AUTH_TYPE_SPNEGO: - if (!pipe_spnego_auth_bind_negotiate(p, rpc_in_p, - ss_padding_len, &auth_info, &out_auth)) { + if (!pipe_spnego_auth_bind_negotiate(p, + ss_padding_len, + &auth_info, &out_auth)) { goto err_exit; } break; @@ -1832,8 +1763,10 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) auth_len = prs_offset(&out_auth) - RPC_HDR_AUTH_LEN; } - init_rpc_hdr(&p->hdr, DCERPC_PKT_BIND_ACK, DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST, - p->hdr.call_id, + init_rpc_hdr(&hdr, + DCERPC_PKT_BIND_ACK, + DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST, + pkt->call_id, RPC_HEADER_LEN + prs_offset(&out_hdr_ba) + ss_padding_len + prs_offset(&out_auth), auth_len); @@ -1842,7 +1775,7 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) * Marshall the header into the outgoing PDU. */ - if(!smb_io_rpc_hdr("", &p->hdr, &p->out_data.frag, 0)) { + if (!smb_io_rpc_hdr("", &hdr, &p->out_data.frag, 0)) { DEBUG(0,("api_pipe_bind_req: marshalling of RPC_HDR failed.\n")); goto err_exit; } @@ -1900,12 +1833,11 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) SPNEGO calls. ****************************************************************************/ -bool api_pipe_alter_context(pipes_struct *p, prs_struct *rpc_in_p) +bool api_pipe_alter_context(pipes_struct *p, struct ncacn_packet *pkt) { + RPC_HDR hdr; RPC_HDR_BA hdr_ba; - struct dcerpc_bind rpc_bind; - DATA_BLOB blob_rb; - RPC_HDR_AUTH auth_info; + struct dcerpc_auth auth_info; uint16 assoc_gid; fstring ack_pipe_name; prs_struct out_hdr_ba; @@ -1940,16 +1872,6 @@ bool api_pipe_alter_context(pipes_struct *p, prs_struct *rpc_in_p) return False; } - DEBUG(5,("api_pipe_alter_context: decode request. %d\n", __LINE__)); - - /* decode the alter context request */ - blob_rb = data_blob_const(prs_data_p(rpc_in_p), - prs_data_size(rpc_in_p)); - status = dcerpc_pull_dcerpc_bind(talloc_tos(), &blob_rb, &rpc_bind); - if (!NT_STATUS_IS_OK(status)) { - goto err_exit; - } - /* secondary address CAN be NULL * as the specs say it's ignored. * It MUST be NULL to have the spoolss working. @@ -1958,8 +1880,8 @@ bool api_pipe_alter_context(pipes_struct *p, prs_struct *rpc_in_p) DEBUG(5,("api_pipe_alter_context: make response. %d\n", __LINE__)); - if (rpc_bind.assoc_group_id != 0) { - assoc_gid = rpc_bind.assoc_group_id; + if (pkt->u.bind.assoc_group_id != 0) { + assoc_gid = pkt->u.bind.assoc_group_id; } else { assoc_gid = 0x53f0; } @@ -1975,16 +1897,16 @@ bool api_pipe_alter_context(pipes_struct *p, prs_struct *rpc_in_p) Needed when adding entries to a DACL from NT5 - SK */ if (check_bind_req(p, - &rpc_bind.ctx_list[0].abstract_syntax, - &rpc_bind.ctx_list[0].transfer_syntaxes[0], - rpc_bind.ctx_list[0].context_id)) { + &pkt->u.bind.ctx_list[0].abstract_syntax, + &pkt->u.bind.ctx_list[0].transfer_syntaxes[0], + pkt->u.bind.ctx_list[0].context_id)) { init_rpc_hdr_ba(&hdr_ba, RPC_MAX_PDU_FRAG_LEN, RPC_MAX_PDU_FRAG_LEN, assoc_gid, ack_pipe_name, 0x1, 0x0, 0x0, - &rpc_bind.ctx_list[0].transfer_syntaxes[0]); + &pkt->u.bind.ctx_list[0].transfer_syntaxes[0]); } else { /* Rejection reason: abstract syntax not supported */ init_rpc_hdr_ba(&hdr_ba, RPC_MAX_PDU_FRAG_LEN, @@ -2008,7 +1930,7 @@ bool api_pipe_alter_context(pipes_struct *p, prs_struct *rpc_in_p) * Check if this is an authenticated alter context request. */ - if (p->hdr.auth_len != 0) { + if (pkt->auth_length != 0) { /* * Decode the authentication verifier. */ @@ -2024,33 +1946,24 @@ bool api_pipe_alter_context(pipes_struct *p, prs_struct *rpc_in_p) /* Quick length check. Won't catch a bad auth footer, * prevents overrun. */ - if (p->hdr.frag_len < RPC_HEADER_LEN + RPC_HDR_AUTH_LEN + p->hdr.auth_len) { + if (pkt->frag_length < RPC_HEADER_LEN + + RPC_HDR_AUTH_LEN + + pkt->auth_length) { DEBUG(0,("api_pipe_alter_context: auth_len (%u) " "too long for fragment %u.\n", - (unsigned int)p->hdr.auth_len, - (unsigned int)p->hdr.frag_len )); + (unsigned int)pkt->auth_length, + (unsigned int)pkt->frag_length )); goto err_exit; } - /* Pull the auth header and the following data into a blob. */ - /* NB. The offset of the auth_header is relative to the *end* - * of the packet, not the start. Also, the length of the - * data in rpc_in_p is p->hdr.frag_len - RPC_HEADER_LEN, - * as the RPC header isn't included in rpc_in_p. */ - if(!prs_set_offset(rpc_in_p, - p->hdr.frag_len - RPC_HEADER_LEN - - RPC_HDR_AUTH_LEN - p->hdr.auth_len)) { - DEBUG(0,("api_alter_context: cannot move " - "offset to %u.\n", - (unsigned int)(p->hdr.frag_len - - RPC_HDR_AUTH_LEN - p->hdr.auth_len) )); + status = dcerpc_pull_dcerpc_auth(pkt, + &pkt->u.bind.auth_info, + &auth_info); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Unable to unmarshall dcerpc_auth.\n")); goto err_exit; } - if(!smb_io_rpc_hdr_auth("", &auth_info, rpc_in_p, 0)) { - DEBUG(0,("api_pipe_alter_context: unable to unmarshall RPC_HDR_AUTH struct.\n")); - goto err_exit; - } /* * Currently only the SPNEGO auth type uses the alter ctx @@ -2060,8 +1973,9 @@ bool api_pipe_alter_context(pipes_struct *p, prs_struct *rpc_in_p) if (auth_info.auth_type == DCERPC_AUTH_TYPE_SPNEGO) { /* We can only finish if the pipe is unbound. */ if (!p->pipe_bound) { - if (!pipe_spnego_auth_bind_continue(p, rpc_in_p, - ss_padding_len, &auth_info, &out_auth)) { + if (!pipe_spnego_auth_bind_continue(p, + ss_padding_len, + &auth_info, &out_auth)) { goto err_exit; } } else { @@ -2079,8 +1993,8 @@ bool api_pipe_alter_context(pipes_struct *p, prs_struct *rpc_in_p) auth_len = prs_offset(&out_auth) - RPC_HDR_AUTH_LEN; } - init_rpc_hdr(&p->hdr, DCERPC_PKT_ALTER_RESP, DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST, - p->hdr.call_id, + init_rpc_hdr(&hdr, DCERPC_PKT_ALTER_RESP, DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST, + pkt->call_id, RPC_HEADER_LEN + prs_offset(&out_hdr_ba) + prs_offset(&out_auth), auth_len); @@ -2088,7 +2002,7 @@ bool api_pipe_alter_context(pipes_struct *p, prs_struct *rpc_in_p) * Marshall the header into the outgoing PDU. */ - if(!smb_io_rpc_hdr("", &p->hdr, &p->out_data.frag, 0)) { + if(!smb_io_rpc_hdr("", &hdr, &p->out_data.frag, 0)) { DEBUG(0,("api_pipe_alter_context: marshalling of RPC_HDR failed.\n")); goto err_exit; } @@ -2452,7 +2366,7 @@ void free_pipe_rpc_context( PIPE_RPC_FNS *list ) return; } -static bool api_rpcTNP(pipes_struct *p, +static bool api_rpcTNP(pipes_struct *p, struct ncacn_packet *pkt, const struct api_struct *api_rpc_cmds, int n_cmds); /**************************************************************************** @@ -2461,7 +2375,7 @@ static bool api_rpcTNP(pipes_struct *p, before doing the call. ****************************************************************************/ -bool api_pipe_request(pipes_struct *p) +bool api_pipe_request(pipes_struct *p, struct ncacn_packet *pkt) { bool ret = False; bool changed_user = False; @@ -2482,17 +2396,20 @@ bool api_pipe_request(pipes_struct *p) /* get the set of RPC functions for this context */ - pipe_fns = find_pipe_fns_by_context(p->contexts, p->hdr_req.context_id); + pipe_fns = find_pipe_fns_by_context(p->contexts, + pkt->u.request.context_id); if ( pipe_fns ) { TALLOC_CTX *frame = talloc_stackframe(); - ret = api_rpcTNP(p, pipe_fns->cmds, pipe_fns->n_cmds); + ret = api_rpcTNP(p, pkt, pipe_fns->cmds, pipe_fns->n_cmds); TALLOC_FREE(frame); } else { - DEBUG(0,("api_pipe_request: No rpc function table associated with context [%d] on pipe [%s]\n", - p->hdr_req.context_id, - get_pipe_name_from_syntax(talloc_tos(), &p->syntax))); + DEBUG(0, ("No rpc function table associated with context " + "[%d] on pipe [%s]\n", + pkt->u.request.context_id, + get_pipe_name_from_syntax(talloc_tos(), + &p->syntax))); } if (changed_user) { @@ -2506,7 +2423,7 @@ bool api_pipe_request(pipes_struct *p) Calls the underlying RPC function for a named pipe. ********************************************************************/ -static bool api_rpcTNP(pipes_struct *p, +static bool api_rpcTNP(pipes_struct *p, struct ncacn_packet *pkt, const struct api_struct *api_rpc_cmds, int n_cmds) { int fn_num; @@ -2515,18 +2432,20 @@ static bool api_rpcTNP(pipes_struct *p, /* interpret the command */ DEBUG(4,("api_rpcTNP: %s op 0x%x - ", get_pipe_name_from_syntax(talloc_tos(), &p->syntax), - p->opnum)); + pkt->u.request.opnum)); if (DEBUGLEVEL >= 50) { fstring name; slprintf(name, sizeof(name)-1, "in_%s", get_pipe_name_from_syntax(talloc_tos(), &p->syntax)); - prs_dump(name, p->opnum, &p->in_data.data); + prs_dump(name, pkt->u.request.opnum, &p->in_data.data); } for (fn_num = 0; fn_num < n_cmds; fn_num++) { - if (api_rpc_cmds[fn_num].opnum == p->opnum && api_rpc_cmds[fn_num].fn != NULL) { - DEBUG(3,("api_rpcTNP: rpc command: %s\n", api_rpc_cmds[fn_num].name)); + if (api_rpc_cmds[fn_num].opnum == pkt->u.request.opnum && + api_rpc_cmds[fn_num].fn != NULL) { + DEBUG(3, ("api_rpcTNP: rpc command: %s\n", + api_rpc_cmds[fn_num].name)); break; } } @@ -2575,7 +2494,7 @@ static bool api_rpcTNP(pipes_struct *p, fstring name; slprintf(name, sizeof(name)-1, "out_%s", get_pipe_name_from_syntax(talloc_tos(), &p->syntax)); - prs_dump(name, p->opnum, &p->out_data.rdata); + prs_dump(name, pkt->u.request.opnum, &p->out_data.rdata); } prs_set_offset(&p->out_data.rdata, offset2); diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index 2cecd89781..0ac9072f3e 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -23,6 +23,9 @@ #include "../librpc/gen_ndr/srv_spoolss.h" #include "librpc/gen_ndr/ndr_named_pipe_auth.h" #include "../libcli/named_pipe_auth/npa_tstream.h" +#include "../libcli/auth/schannel.h" +#include "../libcli/auth/spnego.h" +#include "../libcli/auth/ntlmssp.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV @@ -274,82 +277,169 @@ static void free_pipe_context(pipes_struct *p) appends the data into the complete stream if the LAST flag is not set. ****************************************************************************/ -static bool process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p) +static bool dcesrv_auth_request(pipes_struct *p, struct ncacn_packet *pkt) { - uint32 ss_padding_len = 0; - size_t data_len = p->hdr.frag_len - - RPC_HEADER_LEN - - RPC_HDR_REQ_LEN - - (p->hdr.auth_len ? RPC_HDR_AUTH_LEN : 0) - - p->hdr.auth_len; - - if(!p->pipe_bound) { - DEBUG(0,("process_request_pdu: rpc request with no bind.\n")); - set_incoming_fault(p); - return False; + NTSTATUS status; + size_t hdr_size = DCERPC_REQUEST_LENGTH; + struct dcerpc_auth auth; + uint32_t auth_length; + DATA_BLOB data; + DATA_BLOB full_pkt; + + if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) { + hdr_size += 16; } - /* - * Check if we need to do authentication processing. - * This is only done on requests, not binds. - */ + switch (p->auth.auth_level) { + case DCERPC_AUTH_LEVEL_PRIVACY: + case DCERPC_AUTH_LEVEL_INTEGRITY: + break; - /* - * Read the RPC request header. - */ + case DCERPC_AUTH_LEVEL_CONNECT: + if (pkt->auth_length != 0) { + break; + } + return true; + case DCERPC_AUTH_LEVEL_NONE: + if (pkt->auth_length != 0) { + return false; + } + return true; - if(!smb_io_rpc_hdr_req("req", &p->hdr_req, rpc_in_p, 0)) { - DEBUG(0,("process_request_pdu: failed to unmarshall RPC_HDR_REQ.\n")); - set_incoming_fault(p); - return False; + default: + return false; + } + + status = dcerpc_pull_auth_trailer(pkt, pkt, + &pkt->u.request.stub_and_verifier, + &auth, &auth_length, false); + if (!NT_STATUS_IS_OK(status)) { + return false; } - /* Save the operation number */ - p->opnum = p->hdr_req.opnum; + pkt->u.request.stub_and_verifier.length -= auth_length; + + data.data = p->in_data.pdu.data + hdr_size; + data.length = pkt->u.request.stub_and_verifier.length; + full_pkt.data = p->in_data.pdu.data; + full_pkt.length = p->in_data.pdu.length - auth.credentials.length; + + switch (p->auth.auth_type) { + case PIPE_AUTH_TYPE_NONE: + return true; + + case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: + case PIPE_AUTH_TYPE_NTLMSSP: - switch(p->auth.auth_type) { - case PIPE_AUTH_TYPE_NONE: + if (!p->auth.a_u.auth_ntlmssp_state) { + DEBUG(0, ("Invalid auth level, " + "failed to process packet auth.\n")); + return false; + } + + switch (p->auth.auth_level) { + case DCERPC_AUTH_LEVEL_PRIVACY: + status = auth_ntlmssp_unseal_packet( + p->auth.a_u.auth_ntlmssp_state, + data.data, data.length, + full_pkt.data, full_pkt.length, + &auth.credentials); + if (!NT_STATUS_IS_OK(status)) { + return false; + } + memcpy(pkt->u.request.stub_and_verifier.data, + data.data, data.length); break; - case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: - case PIPE_AUTH_TYPE_NTLMSSP: - { - NTSTATUS status; - if (!api_pipe_ntlmssp_auth_process(p, rpc_in_p, - &ss_padding_len, - &status)) { - DEBUG(0, ("process_request_pdu: " - "failed to do auth processing.\n")); - DEBUG(0, ("process_request_pdu: error is %s\n", - nt_errstr(status))); - set_incoming_fault(p); - return False; + case DCERPC_AUTH_LEVEL_INTEGRITY: + status = auth_ntlmssp_check_packet( + p->auth.a_u.auth_ntlmssp_state, + data.data, data.length, + full_pkt.data, full_pkt.length, + &auth.credentials); + if (!NT_STATUS_IS_OK(status)) { + return false; } break; + + default: + DEBUG(0, ("Invalid auth level, " + "failed to process packet auth.\n")); + return false; } + break; + + case PIPE_AUTH_TYPE_SCHANNEL: + + switch (p->auth.auth_level) { + case DCERPC_AUTH_LEVEL_PRIVACY: + status = netsec_incoming_packet( + p->auth.a_u.schannel_auth, + pkt, true, + data.data, data.length, + &auth.credentials); + if (!NT_STATUS_IS_OK(status)) { + return false; + } + memcpy(pkt->u.request.stub_and_verifier.data, + data.data, data.length); + break; - case PIPE_AUTH_TYPE_SCHANNEL: - if (!api_pipe_schannel_process(p, rpc_in_p, - &ss_padding_len)) { - DEBUG(3, ("process_request_pdu: " - "failed to do schannel processing.\n")); - set_incoming_fault(p); - return False; + case DCERPC_AUTH_LEVEL_INTEGRITY: + status = netsec_incoming_packet( + p->auth.a_u.schannel_auth, + pkt, false, + data.data, data.length, + &auth.credentials); + if (!NT_STATUS_IS_OK(status)) { + return false; } break; default: - DEBUG(0, ("process_request_pdu: " - "unknown auth type %u set.\n", - (unsigned int)p->auth.auth_type)); - set_incoming_fault(p); - return False; + DEBUG(0, ("Invalid auth level, " + "failed to process packet auth.\n")); + return false; + } + break; + + default: + DEBUG(0, ("process_request_pdu: " + "unknown auth type %u set.\n", + (unsigned int)p->auth.auth_type)); + set_incoming_fault(p); + return false; } - /* Now we've done the sign/seal we can remove any padding data. */ - if (data_len > ss_padding_len) { - data_len -= ss_padding_len; + /* remove the indicated amount of padding */ + if (pkt->u.request.stub_and_verifier.length < auth.auth_pad_length) { + return false; } + pkt->u.request.stub_and_verifier.length -= auth.auth_pad_length; + + return true; +} + +static bool process_request_pdu(pipes_struct *p, struct ncacn_packet *pkt) +{ + DATA_BLOB data; + + if (!p->pipe_bound) { + DEBUG(0,("process_request_pdu: rpc request with no bind.\n")); + set_incoming_fault(p); + return False; + } + + /* Store the opnum */ + p->opnum = pkt->u.request.opnum; + + if (!dcesrv_auth_request(p, pkt)) { + DEBUG(0,("Failed to check packet auth.\n")); + set_incoming_fault(p); + return false; + } + + data = pkt->u.request.stub_and_verifier; /* * Check the data length doesn't go over the 15Mb limit. @@ -358,11 +448,11 @@ static bool process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p) * will not fit in the initial buffer of size 0x1068 --jerry 22/01/2002 */ - if(prs_offset(&p->in_data.data) + data_len > MAX_RPC_DATA_SIZE) { + if (prs_offset(&p->in_data.data) + data.length > MAX_RPC_DATA_SIZE) { DEBUG(0, ("process_request_pdu: " "rpc data buffer too large (%u) + (%u)\n", (unsigned int)prs_data_size(&p->in_data.data), - (unsigned int)data_len )); + (unsigned int)data.length)); set_incoming_fault(p); return False; } @@ -371,17 +461,17 @@ static bool process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p) * Append the data portion into the buffer and return. */ - if (!prs_append_some_prs_data(&p->in_data.data, rpc_in_p, - prs_offset(rpc_in_p), data_len)) { + if (!prs_copy_data_in(&p->in_data.data, + (char *)data.data, data.length)) { DEBUG(0, ("process_request_pdu: Unable to append data size %u " "to parse buffer of size %u.\n", - (unsigned int)data_len, + (unsigned int)data.length, (unsigned int)prs_data_size(&p->in_data.data))); set_incoming_fault(p); return False; } - if(p->hdr.flags & DCERPC_PFC_FLAG_LAST) { + if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) { bool ret = False; /* * Ok - we finally have a complete RPC stream. @@ -413,8 +503,8 @@ static bool process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p) * Process the complete data stream here. */ - if(pipe_init_outgoing_data(p)) { - ret = api_pipe_request(p); + if (pipe_init_outgoing_data(p)) { + ret = api_pipe_request(p, pkt); } return ret; @@ -429,176 +519,181 @@ static bool process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p) static void process_complete_pdu(pipes_struct *p) { - prs_struct rpc_in; - size_t data_len = p->in_data.pdu.length - RPC_HEADER_LEN; - char *data_p = (char *)&p->in_data.pdu.data[RPC_HEADER_LEN]; + struct ncacn_packet *pkt; + NTSTATUS status; bool reply = False; - bool hdr_ok; if(p->fault_state) { DEBUG(10,("process_complete_pdu: pipe %s in fault state.\n", get_pipe_name_from_syntax(talloc_tos(), &p->syntax))); - set_incoming_fault(p); - setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR)); - return; + goto done; } - /* parse the header now */ - hdr_ok = unmarshall_rpc_header(p); - if (!hdr_ok) { - setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR)); - return; + pkt = talloc(p->mem_ctx, struct ncacn_packet); + if (!pkt) { + DEBUG(0, ("Out of memory!\n")); + goto done; } - prs_init_empty( &rpc_in, p->mem_ctx, UNMARSHALL); + status = dcerpc_pull_ncacn_packet(pkt, &p->in_data.pdu, pkt); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Failed to unmarshal rpc packet: %s!\n", + nt_errstr(status))); + goto done; + } + + /* Store the call_id */ + p->call_id = pkt->call_id; /* * Ensure we're using the corrent endianness for both the * RPC header flags and the raw data we will be reading from. */ + if (pkt->drep[0] == DCERPC_DREP_LE) { + p->endian = RPC_LITTLE_ENDIAN; + } else { + p->endian = RPC_BIG_ENDIAN; + } + prs_set_endian_data(&p->in_data.data, p->endian); + + DEBUG(10, ("Processing packet type %d\n", (int)pkt->ptype)); + + switch (pkt->ptype) { + case DCERPC_PKT_REQUEST: + reply = process_request_pdu(p, pkt); + break; + + case DCERPC_PKT_PING: /* CL request - ignore... */ + DEBUG(0, ("process_complete_pdu: Error. " + "Connectionless packet type %d received on " + "pipe %s.\n", (int)pkt->ptype, + get_pipe_name_from_syntax(talloc_tos(), + &p->syntax))); + break; + + case DCERPC_PKT_RESPONSE: /* No responses here. */ + DEBUG(0, ("process_complete_pdu: Error. " + "DCERPC_PKT_RESPONSE received from client " + "on pipe %s.\n", + get_pipe_name_from_syntax(talloc_tos(), + &p->syntax))); + break; + + case DCERPC_PKT_FAULT: + case DCERPC_PKT_WORKING: + /* CL request - reply to a ping when a call in process. */ + case DCERPC_PKT_NOCALL: + /* CL - server reply to a ping call. */ + case DCERPC_PKT_REJECT: + case DCERPC_PKT_ACK: + case DCERPC_PKT_CL_CANCEL: + case DCERPC_PKT_FACK: + case DCERPC_PKT_CANCEL_ACK: + DEBUG(0, ("process_complete_pdu: Error. " + "Connectionless packet type %u received on " + "pipe %s.\n", (unsigned int)pkt->ptype, + get_pipe_name_from_syntax(talloc_tos(), + &p->syntax))); + break; + + case DCERPC_PKT_BIND: + /* + * We assume that a pipe bind is only in one pdu. + */ + if (pipe_init_outgoing_data(p)) { + reply = api_pipe_bind_req(p, pkt); + } + break; - prs_set_endian_data( &rpc_in, p->endian); - prs_set_endian_data( &p->in_data.data, p->endian); - - prs_give_memory( &rpc_in, data_p, (uint32)data_len, False); - - DEBUG(10,("process_complete_pdu: processing packet type %u\n", - (unsigned int)p->hdr.pkt_type )); - - switch (p->hdr.pkt_type) { - case DCERPC_PKT_REQUEST: - reply = process_request_pdu(p, &rpc_in); - break; - - case DCERPC_PKT_PING: /* CL request - ignore... */ - DEBUG(0, ("process_complete_pdu: Error. " - "Connectionless packet type %u received on " - "pipe %s.\n", (unsigned int)p->hdr.pkt_type, - get_pipe_name_from_syntax(talloc_tos(), - &p->syntax))); - break; - - case DCERPC_PKT_RESPONSE: /* No responses here. */ - DEBUG(0, ("process_complete_pdu: Error. " - "DCERPC_PKT_RESPONSE received from client " - "on pipe %s.\n", - get_pipe_name_from_syntax(talloc_tos(), - &p->syntax))); - break; - - case DCERPC_PKT_FAULT: - case DCERPC_PKT_WORKING: - /* CL request - reply to a ping when a call in process. */ - case DCERPC_PKT_NOCALL: - /* CL - server reply to a ping call. */ - case DCERPC_PKT_REJECT: - case DCERPC_PKT_ACK: - case DCERPC_PKT_CL_CANCEL: - case DCERPC_PKT_FACK: - case DCERPC_PKT_CANCEL_ACK: - DEBUG(0, ("process_complete_pdu: Error. " - "Connectionless packet type %u received on " - "pipe %s.\n", (unsigned int)p->hdr.pkt_type, - get_pipe_name_from_syntax(talloc_tos(), - &p->syntax))); - break; - - case DCERPC_PKT_BIND: - /* - * We assume that a pipe bind is only in one pdu. - */ - if(pipe_init_outgoing_data(p)) { - reply = api_pipe_bind_req(p, &rpc_in); - } - break; - - case DCERPC_PKT_BIND_ACK: - case DCERPC_PKT_BIND_NAK: - DEBUG(0, ("process_complete_pdu: Error. " - "DCERPC_PKT_BINDACK/DCERPC_PKT_BINDNACK " - "packet type %u received on pipe %s.\n", - (unsigned int)p->hdr.pkt_type, - get_pipe_name_from_syntax(talloc_tos(), - &p->syntax))); - break; - + case DCERPC_PKT_BIND_ACK: + case DCERPC_PKT_BIND_NAK: + DEBUG(0, ("process_complete_pdu: Error. " + "DCERPC_PKT_BINDACK/DCERPC_PKT_BINDNACK " + "packet type %u received on pipe %s.\n", + (unsigned int)pkt->ptype, + get_pipe_name_from_syntax(talloc_tos(), + &p->syntax))); + break; - case DCERPC_PKT_ALTER: - /* - * We assume that a pipe bind is only in one pdu. - */ - if(pipe_init_outgoing_data(p)) { - reply = api_pipe_alter_context(p, &rpc_in); - } - break; - case DCERPC_PKT_ALTER_RESP: - DEBUG(0, ("process_complete_pdu: Error. " - "DCERPC_PKT_ALTER_RESP on pipe %s: " - "Should only be server -> client.\n", - get_pipe_name_from_syntax(talloc_tos(), - &p->syntax))); - break; + case DCERPC_PKT_ALTER: + /* + * We assume that a pipe bind is only in one pdu. + */ + if (pipe_init_outgoing_data(p)) { + reply = api_pipe_alter_context(p, pkt); + } + break; - case DCERPC_PKT_AUTH3: - /* - * The third packet in an NTLMSSP auth exchange. - */ - if(pipe_init_outgoing_data(p)) { - reply = api_pipe_bind_auth3(p, &rpc_in); - } - break; + case DCERPC_PKT_ALTER_RESP: + DEBUG(0, ("process_complete_pdu: Error. " + "DCERPC_PKT_ALTER_RESP on pipe %s: " + "Should only be server -> client.\n", + get_pipe_name_from_syntax(talloc_tos(), + &p->syntax))); + break; - case DCERPC_PKT_SHUTDOWN: - DEBUG(0, ("process_complete_pdu: Error. " - "DCERPC_PKT_SHUTDOWN on pipe %s: " - "Should only be server -> client.\n", - get_pipe_name_from_syntax(talloc_tos(), - &p->syntax))); - break; + case DCERPC_PKT_AUTH3: + /* + * The third packet in an NTLMSSP auth exchange. + */ + if (pipe_init_outgoing_data(p)) { + reply = api_pipe_bind_auth3(p, pkt); + } + break; + + case DCERPC_PKT_SHUTDOWN: + DEBUG(0, ("process_complete_pdu: Error. " + "DCERPC_PKT_SHUTDOWN on pipe %s: " + "Should only be server -> client.\n", + get_pipe_name_from_syntax(talloc_tos(), + &p->syntax))); + break; + + case DCERPC_PKT_CO_CANCEL: + /* For now just free all client data and continue + * processing. */ + DEBUG(3,("process_complete_pdu: DCERPC_PKT_CO_CANCEL." + " Abandoning rpc call.\n")); + /* As we never do asynchronous RPC serving, we can + * never cancel a call (as far as I know). + * If we ever did we'd have to send a cancel_ack reply. + * For now, just free all client data and continue + * processing. */ + reply = True; + break; - case DCERPC_PKT_CO_CANCEL: - /* For now just free all client data and continue - * processing. */ - DEBUG(3,("process_complete_pdu: DCERPC_PKT_CO_CANCEL." - " Abandoning rpc call.\n")); - /* As we never do asynchronous RPC serving, we can - * never cancel a call (as far as I know). - * If we ever did we'd have to send a cancel_ack reply. - * For now, just free all client data and continue - * processing. */ - reply = True; - break; #if 0 - /* Enable this if we're doing async rpc. */ - /* We must check the outstanding callid matches. */ - if(pipe_init_outgoing_data(p)) { - /* Send a cancel_ack PDU reply. */ - /* We should probably check the auth-verifier here. */ - reply = setup_cancel_ack_reply(p, &rpc_in); - } - break; + /* Enable this if we're doing async rpc. */ + /* We must check the outstanding callid matches. */ + if (pipe_init_outgoing_data(p)) { + /* Send a cancel_ack PDU reply. */ + /* We should probably check the auth-verifier here. */ + reply = setup_cancel_ack_reply(p, pkt); + } + break; #endif - case DCERPC_PKT_ORPHANED: - /* We should probably check the auth-verifier here. - * For now just free all client data and continue - * processing. */ - DEBUG(3, ("process_complete_pdu: DCERPC_PKT_ORPHANED." - " Abandoning rpc call.\n")); - reply = True; - break; + case DCERPC_PKT_ORPHANED: + /* We should probably check the auth-verifier here. + * For now just free all client data and continue + * processing. */ + DEBUG(3, ("process_complete_pdu: DCERPC_PKT_ORPHANED." + " Abandoning rpc call.\n")); + reply = True; + break; - default: - DEBUG(0, ("process_complete_pdu: " - "Unknown rpc type = %u received.\n", - (unsigned int)p->hdr.pkt_type)); - break; + default: + DEBUG(0, ("process_complete_pdu: " + "Unknown rpc type = %u received.\n", + (unsigned int)pkt->ptype)); + break; } +done: /* Reset to little endian. * Probably don't need this but it won't hurt. */ - prs_set_endian_data( &p->in_data.data, RPC_LITTLE_ENDIAN); + prs_set_endian_data(&p->in_data.data, RPC_LITTLE_ENDIAN); if (!reply) { DEBUG(3,("process_complete_pdu: DCE/RPC fault sent on " @@ -606,7 +701,7 @@ static void process_complete_pdu(pipes_struct *p) &p->syntax))); set_incoming_fault(p); setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR)); - prs_mem_free(&rpc_in); + TALLOC_FREE(pkt); } else { /* * Reset the lengths. We're ready for a new pdu. @@ -616,7 +711,7 @@ static void process_complete_pdu(pipes_struct *p) p->in_data.pdu.length = 0; } - prs_mem_free(&rpc_in); + TALLOC_FREE(pkt); } /**************************************************************************** |