[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