summaryrefslogtreecommitdiff
path: root/source3/rpc_server
diff options
context:
space:
mode:
Diffstat (limited to 'source3/rpc_server')
-rw-r--r--source3/rpc_server/srv_pipe.c78
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;