[SCM] Samba Shared Repository - branch master updated
Jeremy Allison
jra at samba.org
Wed Feb 17 16:31:09 MST 2010
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 <jra at 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
More information about the samba-cvs
mailing list