The branch, master has been updated via 7b4387f... Fix bug #7146 - Samba miss-parses authenticated RPC packets. from 5564e71... Fix bug #6557 - Do not work VFS full_audit
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 7b4387f765e34177000c8218f51e2c1d227504e6 Author: Jeremy Allison <j...@samba.org> Date: Wed Feb 17 15:27:59 2010 -0800 Fix bug #7146 - Samba miss-parses authenticated RPC packets. Parts of the Samba RPC client and server code misinterpret authenticated packets. DCE authenticated packets actually look like this : +--------------------------+ |header | | ... frag_len (packet len)| | ... auth_len | +--------------------------+ | | | Data payload | ... .... | | +--------------------------+ | | | auth_pad_len bytes | +--------------------------+ | | | Auth footer | | auth_pad_len value | +--------------------------+ | | | Auth payload | | (auth_len bytes long) | +--------------------------+ That's right. The pad bytes come *before* the footer specifying how many pad bytes there are. In order to read this you must seek to the end of the packet and subtract the auth_len (in the packet header) and the auth footer length (a known value). The client and server code gets this right (mostly) in 3.0.x -> 3.4.x so long as the pad alignment is on an 8 byte boundary (there are some special cases in the code for this). Tridge discovered there are some (DRS replication) cases where on 64-bit machines where the pad alignment is on a 16-byte boundary. This breaks the existing S3 hand-optimized rpc code. This patch removes all the special cases in client and server code, and allows the pad alignment for generated packets to be specified by changing a constant in include/local.h (this doesn't affect received packets, the new code always handles them correctly whatever pad alignment is used). This patch also works correctly with rpcclient using sign+seal from the 3.4.x and 3.3.x builds (testing with 3.0.x and 3.2.x to follow) so even as a server it should still work with older libsmbclient and winbindd code. Jeremy ----------------------------------------------------------------------- Summary of changes: source3/include/local.h | 3 + source3/rpc_client/cli_pipe.c | 62 +++++-- source3/rpc_parse/parse_rpc.c | 5 +- source3/rpc_server/srv_pipe.c | 431 +++++++++++++++++++++++++++++------------ 4 files changed, 363 insertions(+), 138 deletions(-) Changeset truncated at 500 lines: diff --git a/source3/include/local.h b/source3/include/local.h index a88b17b..a3baf64 100644 --- a/source3/include/local.h +++ b/source3/include/local.h @@ -274,4 +274,7 @@ /* Maximum size of RPC data we will accept for one call. */ #define MAX_RPC_DATA_SIZE (15*1024*1024) +#define CLIENT_NDR_PADDING_SIZE 8 +#define SERVER_NDR_PADDING_SIZE 8 + #endif diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 48e2f9e..2f7db99 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -650,8 +650,9 @@ static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *pr } /* Ensure there's enough data for an authenticated response. */ - if ((auth_len > RPC_MAX_SIGN_SIZE) || - (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) { + if (auth_len > RPC_MAX_PDU_FRAG_LEN || + prhdr->frag_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN + + RPC_HDR_AUTH_LEN + auth_len) { DEBUG(0,("cli_pipe_verify_ntlmssp: auth_len %u is too large.\n", (unsigned int)auth_len )); return NT_STATUS_BUFFER_TOO_SMALL; @@ -671,17 +672,31 @@ static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *pr full_packet_data_len = prhdr->frag_len - auth_len; /* Pull the auth header and the following data into a blob. */ - if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) { + /* NB. The offset of the auth_header is relative to the *end* + * of the packet, not the start. */ + if(!prs_set_offset(current_pdu, prhdr->frag_len - RPC_HDR_AUTH_LEN - auth_len)) { DEBUG(0,("cli_pipe_verify_ntlmssp: cannot move offset to %u.\n", (unsigned int)RPC_HEADER_LEN + (unsigned int)RPC_HDR_RESP_LEN + (unsigned int)data_len )); return NT_STATUS_BUFFER_TOO_SMALL; - } + } if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) { DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall RPC_HDR_AUTH.\n")); return NT_STATUS_BUFFER_TOO_SMALL; } + /* Ensure auth_pad_len fits into the packet. */ + if (RPC_HEADER_LEN + RPC_HDR_REQ_LEN + auth_info.auth_pad_len + + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len) { + DEBUG(0,("cli_pipe_verify_ntlmssp: auth_info.auth_pad_len " + "too large (%u), auth_len (%u), frag_len = (%u).\n", + (unsigned int)auth_info.auth_pad_len, + (unsigned int)auth_len, + (unsigned int)prhdr->frag_len )); + return NT_STATUS_BUFFER_TOO_SMALL; + } + + auth_blob.data = (unsigned char *)prs_data_p(current_pdu) + prs_offset(current_pdu); auth_blob.length = auth_len; @@ -775,7 +790,7 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *p } /* Ensure there's enough data for an authenticated response. */ - if ((auth_len > RPC_MAX_SIGN_SIZE) || + if ((auth_len > RPC_MAX_PDU_FRAG_LEN) || (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) { DEBUG(0,("cli_pipe_verify_schannel: auth_len %u is too large.\n", (unsigned int)auth_len )); @@ -784,9 +799,15 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *p data_len = prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len; - if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) { - DEBUG(0,("cli_pipe_verify_schannel: cannot move offset to %u.\n", - (unsigned int)RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len )); + /* 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. */ + if(!prs_set_offset(current_pdu, + prhdr->frag_len - RPC_HDR_AUTH_LEN - auth_len)) { + DEBUG(0,("cli_pipe_verify_schannel: cannot move " + "offset to %u.\n", + (unsigned int)(prhdr->frag_len - + RPC_HDR_AUTH_LEN - auth_len) )); return NT_STATUS_BUFFER_TOO_SMALL; } @@ -795,6 +816,17 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *p return NT_STATUS_BUFFER_TOO_SMALL; } + /* Ensure auth_pad_len fits into the packet. */ + if (RPC_HEADER_LEN + RPC_HDR_REQ_LEN + auth_info.auth_pad_len + + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len) { + DEBUG(0,("cli_pipe_verify_schannel: auth_info.auth_pad_len " + "too large (%u), auth_len (%u), frag_len = (%u).\n", + (unsigned int)auth_info.auth_pad_len, + (unsigned int)auth_len, + (unsigned int)prhdr->frag_len )); + return NT_STATUS_BUFFER_TOO_SMALL; + } + if (auth_info.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) { DEBUG(0,("cli_pipe_verify_schannel: Invalid auth info %d on schannel\n", auth_info.auth_type)); @@ -1790,8 +1822,8 @@ static NTSTATUS create_bind_or_alt_ctx_internal(enum dcerpc_pkt_type pkt_type, /* Do we need to pad ? */ if (auth_len) { uint16 data_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb); - if (data_len % 8) { - ss_padding_len = 8 - (data_len % 8); + if (data_len % CLIENT_NDR_PADDING_SIZE) { + ss_padding_len = CLIENT_NDR_PADDING_SIZE - (data_len % CLIENT_NDR_PADDING_SIZE); phdr_auth->auth_pad_len = ss_padding_len; } frag_len += RPC_HDR_AUTH_LEN + auth_len + ss_padding_len; @@ -1818,8 +1850,8 @@ static NTSTATUS create_bind_or_alt_ctx_internal(enum dcerpc_pkt_type pkt_type, if(auth_len != 0) { if (ss_padding_len) { - char pad[8]; - memset(pad, '\0', 8); + char pad[CLIENT_NDR_PADDING_SIZE]; + memset(pad, '\0', CLIENT_NDR_PADDING_SIZE); if (!prs_copy_data_in(rpc_out, pad, ss_padding_len)) { DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall padding.\n")); return NT_STATUS_NO_MEMORY; @@ -2120,8 +2152,8 @@ static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli, data_len = MIN(data_space, data_left); *p_ss_padding = 0; - if (data_len % 8) { - *p_ss_padding = 8 - (data_len % 8); + if (data_len % CLIENT_NDR_PADDING_SIZE) { + *p_ss_padding = CLIENT_NDR_PADDING_SIZE - (data_len % CLIENT_NDR_PADDING_SIZE); } *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + /* Normal headers. */ data_len + *p_ss_padding + /* data plus padding. */ @@ -2517,7 +2549,7 @@ static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli, /* I'm puzzled about this - seems to violate the DCE RPC auth rules, - about padding - shouldn't this pad to length 8 ? JRA. + about padding - shouldn't this pad to length CLIENT_NDR_PADDING_SIZE ? JRA. */ /* 4 bytes padding. */ diff --git a/source3/rpc_parse/parse_rpc.c b/source3/rpc_parse/parse_rpc.c index f720de3..441a00b 100644 --- a/source3/rpc_parse/parse_rpc.c +++ b/source3/rpc_parse/parse_rpc.c @@ -480,6 +480,8 @@ void init_rpc_hdr_auth(RPC_HDR_AUTH *rai, /******************************************************************* Reads or writes an RPC_HDR_AUTH structure. + NB This writes UNALIGNED. Ensure you're correctly aligned before + calling. ********************************************************************/ bool smb_io_rpc_hdr_auth(const char *desc, RPC_HDR_AUTH *rai, prs_struct *ps, int depth) @@ -490,9 +492,6 @@ bool smb_io_rpc_hdr_auth(const char *desc, RPC_HDR_AUTH *rai, prs_struct *ps, in prs_debug(ps, depth, desc, "smb_io_rpc_hdr_auth"); depth++; - if(!prs_align(ps)) - return False; - if(!prs_uint8 ("auth_type ", ps, depth, &rai->auth_type)) return False; if(!prs_uint8 ("auth_level ", ps, depth, &rai->auth_level)) diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index f92a100..6b08f1f 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -131,11 +131,12 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p) if(p->out_data.data_sent_length + data_len >= prs_offset(&p->out_data.rdata)) { p->hdr.flags |= DCERPC_PFC_FLAG_LAST; - if (data_len_left % 8) { - ss_padding_len = 8 - (data_len_left % 8); - DEBUG(10,("create_next_pdu_ntlmssp: adding sign/seal padding of %u\n", - ss_padding_len )); - } + } + + if (data_len_left % SERVER_NDR_PADDING_SIZE) { + ss_padding_len = SERVER_NDR_PADDING_SIZE - (data_len_left % SERVER_NDR_PADDING_SIZE); + DEBUG(10,("create_next_pdu_ntlmssp: adding sign/seal padding of %u\n", + ss_padding_len )); } /* @@ -179,9 +180,9 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p) /* Copy the sign/seal padding data. */ if (ss_padding_len) { - char pad[8]; + char pad[SERVER_NDR_PADDING_SIZE]; - memset(pad, '\0', 8); + memset(pad, '\0', SERVER_NDR_PADDING_SIZE); if (!prs_copy_data_in(&p->out_data.frag, pad, ss_padding_len)) { DEBUG(0,("create_next_pdu_ntlmssp: failed to add %u bytes of pad data.\n", @@ -205,8 +206,9 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p) } init_rpc_hdr_auth(&auth_info, auth_type, auth_level, ss_padding_len, 1 /* context id. */); - if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &p->out_data.frag, - 0)) { + + if (!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, + &p->out_data.frag, 0)) { DEBUG(0,("create_next_pdu_ntlmssp: failed to marshall RPC_HDR_AUTH.\n")); prs_mem_free(&p->out_data.frag); return False; @@ -350,11 +352,11 @@ static bool create_next_pdu_schannel(pipes_struct *p) if(p->out_data.data_sent_length + data_len >= prs_offset(&p->out_data.rdata)) { p->hdr.flags |= DCERPC_PFC_FLAG_LAST; - if (data_len_left % 8) { - ss_padding_len = 8 - (data_len_left % 8); - DEBUG(10,("create_next_pdu_schannel: adding sign/seal padding of %u\n", - ss_padding_len )); - } + } + if (data_len_left % SERVER_NDR_PADDING_SIZE) { + ss_padding_len = SERVER_NDR_PADDING_SIZE - (data_len_left % SERVER_NDR_PADDING_SIZE); + DEBUG(10,("create_next_pdu_schannel: adding sign/seal padding of %u\n", + ss_padding_len )); } p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len + ss_padding_len + @@ -395,8 +397,8 @@ static bool create_next_pdu_schannel(pipes_struct *p) /* Copy the sign/seal padding data. */ if (ss_padding_len) { - char pad[8]; - memset(pad, '\0', 8); + char pad[SERVER_NDR_PADDING_SIZE]; + memset(pad, '\0', SERVER_NDR_PADDING_SIZE); if (!prs_copy_data_in(&p->out_data.frag, pad, ss_padding_len)) { DEBUG(0,("create_next_pdu_schannel: failed to add %u bytes of pad data.\n", (unsigned int)ss_padding_len)); @@ -421,7 +423,7 @@ static bool create_next_pdu_schannel(pipes_struct *p) DCERPC_AUTH_LEVEL_PRIVACY : DCERPC_AUTH_LEVEL_INTEGRITY, ss_padding_len, 1); - if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, + if (!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &p->out_data.frag, 0)) { DEBUG(0,("create_next_pdu_schannel: failed to marshall RPC_HDR_AUTH.\n")); prs_mem_free(&p->out_data.frag); @@ -746,12 +748,13 @@ bool api_pipe_bind_auth3(pipes_struct *p, prs_struct *rpc_in_p) RPC_HDR_AUTH auth_info; uint32 pad = 0; DATA_BLOB blob; + uint32_t auth_len = p->hdr.auth_len; ZERO_STRUCT(blob); DEBUG(5,("api_pipe_bind_auth3: decode request. %d\n", __LINE__)); - if (p->hdr.auth_len == 0) { + if (auth_len == 0) { DEBUG(0,("api_pipe_bind_auth3: No auth field sent !\n")); goto err; } @@ -762,15 +765,45 @@ bool api_pipe_bind_auth3(pipes_struct *p, prs_struct *rpc_in_p) 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) { + DEBUG(0,("api_pipe_ntlmssp_auth_process: auth_len " + "%u is too large.\n", + (unsigned int)auth_len )); + 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")); + /* 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; + } + + if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, rpc_in_p, 0)) { + DEBUG(0,("api_pipe_bind_auth3: failed to " + "unmarshall RPC_HDR_AUTH.\n")); goto err; } + /* We must NEVER look at auth_info->auth_pad_len here, + * as old Samba client code gets it wrong and sends it + * as zero. JRA. + */ + if (auth_info.auth_type != DCERPC_AUTH_TYPE_NTLMSSP) { DEBUG(0,("api_pipe_bind_auth3: incorrect auth type (%u).\n", (unsigned int)auth_info.auth_type )); @@ -1154,6 +1187,7 @@ static bool pipe_spnego_auth_bind_kerberos(pipes_struct *p, prs_struct *rpc_in_p *******************************************************************/ static bool pipe_spnego_auth_bind_negotiate(pipes_struct *p, prs_struct *rpc_in_p, + uint32_t ss_padding_len, RPC_HDR_AUTH *pauth_info, prs_struct *pout_auth) { DATA_BLOB blob; @@ -1245,8 +1279,11 @@ static bool pipe_spnego_auth_bind_negotiate(pipes_struct *p, prs_struct *rpc_in_ OID_NTLMSSP); } + /* auth_pad_len will be handled by the caller */ + /* Copy the blob into the pout_auth parse struct */ - init_rpc_hdr_auth(&auth_info, DCERPC_AUTH_TYPE_SPNEGO, pauth_info->auth_level, RPC_HDR_AUTH_LEN, 1); + init_rpc_hdr_auth(&auth_info, DCERPC_AUTH_TYPE_SPNEGO, + pauth_info->auth_level, ss_padding_len, 1); if(!smb_io_rpc_hdr_auth("", &auth_info, pout_auth, 0)) { DEBUG(0,("pipe_spnego_auth_bind_negotiate: marshalling of RPC_HDR_AUTH failed.\n")); goto err; @@ -1286,7 +1323,8 @@ static bool pipe_spnego_auth_bind_negotiate(pipes_struct *p, prs_struct *rpc_in_ *******************************************************************/ static bool pipe_spnego_auth_bind_continue(pipes_struct *p, prs_struct *rpc_in_p, - RPC_HDR_AUTH *pauth_info, prs_struct *pout_auth) + uint32_t ss_padding_len, + RPC_HDR_AUTH *pauth_info, prs_struct *pout_auth) { RPC_HDR_AUTH auth_info; DATA_BLOB spnego_blob; @@ -1343,8 +1381,11 @@ static bool pipe_spnego_auth_bind_continue(pipes_struct *p, prs_struct *rpc_in_p /* Generate the spnego "accept completed" blob - no incoming data. */ response = spnego_gen_auth_response(&auth_reply, NT_STATUS_OK, OID_NTLMSSP); + /* FIXME - add auth_pad_len here ! */ + /* Copy the blob into the pout_auth parse struct */ - init_rpc_hdr_auth(&auth_info, DCERPC_AUTH_TYPE_SPNEGO, pauth_info->auth_level, RPC_HDR_AUTH_LEN, 1); + init_rpc_hdr_auth(&auth_info, DCERPC_AUTH_TYPE_SPNEGO, + pauth_info->auth_level, ss_padding_len, 1); if(!smb_io_rpc_hdr_auth("", &auth_info, pout_auth, 0)) { DEBUG(0,("pipe_spnego_auth_bind_continue: marshalling of RPC_HDR_AUTH failed.\n")); goto err; @@ -1380,6 +1421,7 @@ 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, RPC_HDR_AUTH *pauth_info, prs_struct *pout_auth) { RPC_HDR_AUTH auth_info; @@ -1466,7 +1508,8 @@ static bool pipe_schannel_auth_bind(pipes_struct *p, prs_struct *rpc_in_p, return false; } - init_rpc_hdr_auth(&auth_info, DCERPC_AUTH_TYPE_SCHANNEL, pauth_info->auth_level, RPC_HDR_AUTH_LEN, 1); + init_rpc_hdr_auth(&auth_info, DCERPC_AUTH_TYPE_SCHANNEL, + pauth_info->auth_level, ss_padding_len, 1); if(!smb_io_rpc_hdr_auth("", &auth_info, pout_auth, 0)) { DEBUG(0,("pipe_schannel_auth_bind: marshalling of RPC_HDR_AUTH failed.\n")); return False; @@ -1512,6 +1555,7 @@ static bool pipe_schannel_auth_bind(pipes_struct *p, prs_struct *rpc_in_p, *******************************************************************/ static bool pipe_ntlmssp_auth_bind(pipes_struct *p, prs_struct *rpc_in_p, + uint32_t ss_padding_len, RPC_HDR_AUTH *pauth_info, prs_struct *pout_auth) { RPC_HDR_AUTH auth_info; @@ -1555,7 +1599,8 @@ static bool pipe_ntlmssp_auth_bind(pipes_struct *p, prs_struct *rpc_in_p, data_blob_free(&blob); /* Copy the blob into the pout_auth parse struct */ - init_rpc_hdr_auth(&auth_info, DCERPC_AUTH_TYPE_NTLMSSP, pauth_info->auth_level, RPC_HDR_AUTH_LEN, 1); + init_rpc_hdr_auth(&auth_info, DCERPC_AUTH_TYPE_NTLMSSP, + pauth_info->auth_level, ss_padding_len, 1); if(!smb_io_rpc_hdr_auth("", &auth_info, pout_auth, 0)) { DEBUG(0,("pipe_ntlmssp_auth_bind: marshalling of RPC_HDR_AUTH failed.\n")); goto err; @@ -1604,6 +1649,7 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) int i = 0; int auth_len = 0; unsigned int auth_type = DCERPC_AUTH_TYPE_NONE; + uint32_t ss_padding_len = 0; /* No rebinds on a bound pipe - use alter context. */ if (p->pipe_bound) { @@ -1717,6 +1763,45 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__)); + assoc_gid = hdr_rb.bba.assoc_gid ? hdr_rb.bba.assoc_gid : 0x53f0; + + /* + * Create the bind response struct. + */ + + /* If the requested abstract synt uuid doesn't match our client pipe, + reject the bind_ack & set the transfer interface synt to all 0's, + ver 0 (observed when NT5 attempts to bind to abstract interfaces + unknown to NT4) + Needed when adding entries to a DACL from NT5 - SK */ + + if(check_bind_req(p, &hdr_rb.rpc_context[0].abstract, &hdr_rb.rpc_context[0].transfer[0], + hdr_rb.rpc_context[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, + &hdr_rb.rpc_context[0].transfer[0]); + } else { + /* Rejection reason: abstract syntax not supported */ + init_rpc_hdr_ba(&hdr_ba, RPC_MAX_PDU_FRAG_LEN, + RPC_MAX_PDU_FRAG_LEN, assoc_gid, + ack_pipe_name, 0x1, 0x2, 0x1, + &null_ndr_syntax_id); + p->pipe_bound = False; + } + + /* + * and marshall it. + */ + + if(!smb_io_rpc_hdr_ba("", &hdr_ba, &out_hdr_ba, 0)) { + DEBUG(0,("api_pipe_bind_req: marshalling of RPC_HDR_BA failed.\n")); + goto err_exit; + } + /* * Check if this is an authenticated bind request. */ @@ -1726,6 +1811,40 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) * Decode the authentication verifier. */ + /* Work out any padding needed before the auth footer. */ + if ((RPC_HEADER_LEN + prs_offset(&out_hdr_ba)) % SERVER_NDR_PADDING_SIZE) { + ss_padding_len = SERVER_NDR_PADDING_SIZE - + ((RPC_HEADER_LEN + prs_offset(&out_hdr_ba)) % SERVER_NDR_PADDING_SIZE); + DEBUG(10,("api_pipe_bind_req: auth pad_len = %u\n", + (unsigned int)ss_padding_len )); + } + + /* 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) { + 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) )); + goto err_exit; + } + if(!smb_io_rpc_hdr_auth("", &auth_info, rpc_in_p, 0)) { DEBUG(0,("api_pipe_bind_req: unable to unmarshall RPC_HDR_AUTH struct.\n")); goto err_exit; @@ -1750,24 +1869,25 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) ZERO_STRUCT(auth_info); } - assoc_gid = hdr_rb.bba.assoc_gid ? hdr_rb.bba.assoc_gid : 0x53f0; - -- Samba Shared Repository