diff options
Diffstat (limited to 'source3/rpc_server')
-rw-r--r-- | source3/rpc_server/srv_pipe.c | 78 |
1 files changed, 52 insertions, 26 deletions
diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index ad7c544b68..076f800a40 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -87,6 +87,7 @@ BOOL create_next_pdu(pipes_struct *p) RPC_HDR_RESP hdr_resp; BOOL auth_verify = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SIGN) != 0); BOOL auth_seal = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SEAL) != 0); + uint32 ss_padding_len = 0; uint32 data_len; uint32 data_space_available; uint32 data_len_left; @@ -109,21 +110,22 @@ BOOL create_next_pdu(pipes_struct *p) p->hdr.pkt_type = RPC_RESPONSE; /* Set up rpc header flags. */ - if (p->out_data.data_sent_length == 0) + if (p->out_data.data_sent_length == 0) { p->hdr.flags = RPC_FLG_FIRST; - else + } else { p->hdr.flags = 0; + } /* * Work out how much we can fit in a single PDU. */ data_space_available = sizeof(p->out_data.current_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN; - if(p->ntlmssp_auth_validated) + if(p->ntlmssp_auth_validated) { data_space_available -= (RPC_HDR_AUTH_LEN + RPC_AUTH_NTLMSSP_CHK_LEN); - - if(p->netsec_auth_validated) + } else if(p->netsec_auth_validated) { data_space_available -= (RPC_HDR_AUTH_LEN + RPC_AUTH_NETSEC_CHK_LEN); + } /* * The amount we send is the minimum of the available @@ -151,15 +153,30 @@ BOOL create_next_pdu(pipes_struct *p) 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; + if ((auth_seal || auth_verify) && (data_len_left % 8)) { + ss_padding_len = 8 - (data_len_left % 8); + DEBUG(10,("create_next_pdu: adding sign/seal padding of %u\n", + ss_padding_len )); + } + } + + /* * Set up the header lengths. */ if (p->ntlmssp_auth_validated) { - p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len + - RPC_HDR_AUTH_LEN + RPC_AUTH_NTLMSSP_CHK_LEN; + p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + + data_len + ss_padding_len + + RPC_HDR_AUTH_LEN + RPC_AUTH_NTLMSSP_CHK_LEN; p->hdr.auth_len = RPC_AUTH_NTLMSSP_CHK_LEN; } else if (p->netsec_auth_validated) { - p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len + + p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + + data_len + ss_padding_len + RPC_HDR_AUTH_LEN + RPC_AUTH_NETSEC_CHK_LEN; p->hdr.auth_len = RPC_AUTH_NETSEC_CHK_LEN; } else { @@ -168,13 +185,6 @@ BOOL create_next_pdu(pipes_struct *p) } /* - * 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; - - /* * Init the parse struct to point at the outgoing * data. */ @@ -206,12 +216,26 @@ BOOL create_next_pdu(pipes_struct *p) return False; } + /* Copy the sign/seal padding data. */ + if (ss_padding_len) { + char pad[8]; + memset(pad, '\0', 8); + if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding_len)) { + DEBUG(0,("create_next_pdu: failed to add %u bytes of pad data.\n", (unsigned int)ss_padding_len)); + prs_mem_free(&outgoing_pdu); + return False; + } + } + if (p->ntlmssp_auth_validated) { + /* + * NTLMSSP processing. Mutually exclusive with Schannel. + */ uint32 crc32 = 0; char *data; DEBUG(5,("create_next_pdu: sign: %s seal: %s data %d auth %d\n", - BOOLSTR(auth_verify), BOOLSTR(auth_seal), data_len, p->hdr.auth_len)); + BOOLSTR(auth_verify), BOOLSTR(auth_seal), data_len + ss_padding_len, p->hdr.auth_len)); /* * Set data to point to where we copied the data into. @@ -220,15 +244,16 @@ BOOL create_next_pdu(pipes_struct *p) data = prs_data_p(&outgoing_pdu) + data_pos; if (auth_seal) { - crc32 = crc32_calc_buffer(data, data_len); - NTLMSSPcalc_p(p, (uchar*)data, data_len); + crc32 = crc32_calc_buffer(data, data_len + ss_padding_len); + NTLMSSPcalc_p(p, (uchar*)data, data_len + ss_padding_len); } if (auth_seal || auth_verify) { RPC_HDR_AUTH auth_info; - init_rpc_hdr_auth(&auth_info, NTLMSSP_AUTH_TYPE, auth_info.auth_level, - (auth_verify ? RPC_HDR_AUTH_LEN : 0), (auth_verify ? 1 : 0)); + init_rpc_hdr_auth(&auth_info, NTLMSSP_AUTH_TYPE, + auth_seal ? RPC_PIPE_AUTH_SEAL_LEVEL : RPC_PIPE_AUTH_SIGN_LEVEL, + (auth_verify ? ss_padding_len : 0), (auth_verify ? 1 : 0)); if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) { DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_AUTH.\n")); prs_mem_free(&outgoing_pdu); @@ -251,9 +276,10 @@ BOOL create_next_pdu(pipes_struct *p) } NTLMSSPcalc_p(p, (uchar*)auth_data, RPC_AUTH_NTLMSSP_CHK_LEN - 4); } - } - - if (p->netsec_auth_validated) { + } else if (p->netsec_auth_validated) { + /* + * Schannel processing. Mutually exclusive with NTLMSSP. + */ int auth_type, auth_level; char *data; RPC_HDR_AUTH auth_info; @@ -267,7 +293,7 @@ BOOL create_next_pdu(pipes_struct *p) get_auth_type_level(p->netsec_auth.auth_flags, &auth_type, &auth_level); init_rpc_hdr_auth(&auth_info, auth_type, auth_level, - RPC_HDR_AUTH_LEN, 1); + ss_padding_len, 1); if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) { DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_AUTH.\n")); @@ -281,7 +307,7 @@ BOOL create_next_pdu(pipes_struct *p) netsec_encode(&p->netsec_auth, p->netsec_auth.auth_flags, SENDER_IS_ACCEPTOR, - &verf, data, data_len); + &verf, data, data_len + ss_padding_len); smb_io_rpc_auth_netsec_chk("", &verf, &outgoing_pdu, 0); @@ -292,7 +318,7 @@ BOOL create_next_pdu(pipes_struct *p) * Setup the counts for this PDU. */ - p->out_data.data_sent_length += data_len; + p->out_data.data_sent_length += (data_len + ss_padding_len); p->out_data.current_pdu_len = p->hdr.frag_len; p->out_data.current_pdu_sent = 0; |