[SCM] Samba Shared Repository - branch v4-2-test updated

Karolin Seeger kseeger at samba.org
Thu Aug 4 11:44:04 UTC 2016


The branch, v4-2-test has been updated
       via  67859d0 python/tests: add auth_pad test for the dcerpc raw_protocol test
       via  00b06bc s4:rpc_server: generate the correct error when we got an invalid auth_pad_length on BIND,ALTER,AUTH3
       via  90c2a94 librpc/rpc: ignore invalid auth_pad_length values in BIND, ALTER and AUTH3 pdus
       via  30b5b9f librpc/rpc: let dcerpc_pull_auth_trailer() check that auth_pad_length fits within the whole pdu.
       via  93e8b4e librpc/rpc: let dcerpc_pull_auth_trailer() only accept auth_length!=NULL or auth_data_only=true
       via  d950d0f s4:librpc/rpc: don't ask for auth_length if we ask for auth data only
       via  7d76653 s4:rpc_server: parse auth data only for BIND,ALTER_REQ,AUTH3
      from  996ee07 VERSION: Bump version up to 4.2.15...

https://git.samba.org/?p=samba.git;a=shortlog;h=v4-2-test


- Log -----------------------------------------------------------------
commit 67859d0f316aaf62ef662d9b9ff80381a07bfed8
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Jun 23 12:06:40 2016 +0200

    python/tests: add auth_pad test for the dcerpc raw_protocol test
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11982
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    
    Autobuild-User(master): Stefan Metzmacher <metze at samba.org>
    Autobuild-Date(master): Fri Jun 24 18:08:44 CEST 2016 on sn-devel-144
    
    (cherry picked from commit c49f9abb19adca999d0b1d897d00d91f0ad91bbd)
    
    Autobuild-User(v4-2-test): Karolin Seeger <kseeger at samba.org>
    Autobuild-Date(v4-2-test): Thu Aug  4 13:43:46 CEST 2016 on sn-devel-104

commit 00b06bccde173d8b9613d34c1f3e9c4e4788ca12
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Jun 23 13:50:39 2016 +0200

    s4:rpc_server: generate the correct error when we got an invalid auth_pad_length on BIND,ALTER,AUTH3
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11982
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit 7d8edcc24148658e92729b3d155e432994e27525)

commit 90c2a94b9686d86457d74767310b4b72f90d8c82
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Jun 20 16:26:56 2016 +0200

    librpc/rpc: ignore invalid auth_pad_length values in BIND, ALTER and AUTH3 pdus
    
    This is a workarround for a bug in old Samba releases.
    For BIND_ACK <= 3.5.x and for ALTER_RESP <= 4.2.x (see bug #11061).
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11982
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit aef032302863e5f3a888dbf4c52b21d561a0dff4)

commit 30b5b9fd97ee68d0c78f1f820b552afa33f065f4
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Jun 20 16:25:12 2016 +0200

    librpc/rpc: let dcerpc_pull_auth_trailer() check that auth_pad_length fits within the whole pdu.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11982
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit 3f7e3ed8a276f16aaed87c1f3cd5b9781aa7e1af)

commit 93e8b4e0f9d59a04551df47b438f5ebd55f568a5
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Jun 20 16:17:45 2016 +0200

    librpc/rpc: let dcerpc_pull_auth_trailer() only accept auth_length!=NULL or auth_data_only=true
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11982
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit f386e81b982cd551313eb9c0f7d2f70d65515d80)

commit d950d0f6b50b93ef8b96490c7f353336c161f12d
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Jun 20 16:16:23 2016 +0200

    s4:librpc/rpc: don't ask for auth_length if we ask for auth data only
    
    dcerpc_pull_auth_trailer() handles auth_length=NULL just fine.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11982
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit e05c732c6074df2524403ad7bb30eade91443525)

commit 7d7665355029bd8079e258623776708a70ec32e8
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Jun 20 16:11:37 2016 +0200

    s4:rpc_server: parse auth data only for BIND,ALTER_REQ,AUTH3
    
    We should tell dcerpc_pull_auth_trailer() that we only want
    auth data.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11982
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit 505a4e68d96e6fb3d8c7493632ecb4b0fc6caa9d)

-----------------------------------------------------------------------

Summary of changes:
 librpc/rpc/dcerpc_util.c                  |  61 ++++
 python/samba/tests/dcerpc/raw_protocol.py | 548 ++++++++++++++++++++++++++++++
 source4/librpc/rpc/dcerpc.c               |   8 +-
 source4/rpc_server/dcerpc_server.c        |  13 +-
 source4/rpc_server/dcesrv_auth.c          |  27 +-
 5 files changed, 642 insertions(+), 15 deletions(-)


Changeset truncated at 500 lines:

diff --git a/librpc/rpc/dcerpc_util.c b/librpc/rpc/dcerpc_util.c
index 43e1b7f..df14948 100644
--- a/librpc/rpc/dcerpc_util.c
+++ b/librpc/rpc/dcerpc_util.c
@@ -95,10 +95,19 @@ NTSTATUS dcerpc_pull_auth_trailer(const struct ncacn_packet *pkt,
 	uint16_t data_and_pad;
 	uint16_t auth_length;
 	uint32_t tmp_length;
+	uint32_t max_pad_len = 0;
 
 	ZERO_STRUCTP(auth);
 	if (_auth_length != NULL) {
 		*_auth_length = 0;
+
+		if (auth_data_only) {
+			return NT_STATUS_INTERNAL_ERROR;
+		}
+	} else {
+		if (!auth_data_only) {
+			return NT_STATUS_INTERNAL_ERROR;
+		}
 	}
 
 	/* Paranoia checks for auth_length. The caller should check this... */
@@ -149,6 +158,58 @@ NTSTATUS dcerpc_pull_auth_trailer(const struct ncacn_packet *pkt,
 		return ndr_map_error2ntstatus(ndr_err);
 	}
 
+	/*
+	 * Make sure the padding would not exceed
+	 * the frag_length.
+	 *
+	 * Here we assume at least 24 bytes for the
+	 * payload specific header the value of
+	 * DCERPC_{REQUEST,RESPONSE}_LENGTH.
+	 *
+	 * We use this also for BIND_*, ALTER_* and AUTH3 pdus.
+	 *
+	 * We need this check before we ignore possible
+	 * invalid values. See also bug #11982.
+	 *
+	 * This check is mainly used to generate the correct
+	 * error for BIND_*, ALTER_* and AUTH3 pdus.
+	 *
+	 * We always have the 'if (data_and_pad < auth->auth_pad_length)'
+	 * protection for REQUEST and RESPONSE pdus, where the
+	 * auth_pad_length field is actually used by the caller.
+	 */
+	tmp_length = DCERPC_REQUEST_LENGTH;
+	tmp_length += DCERPC_AUTH_TRAILER_LENGTH;
+	tmp_length += pkt->auth_length;
+	if (tmp_length < pkt->frag_length) {
+		max_pad_len = pkt->frag_length - tmp_length;
+	}
+	if (max_pad_len < auth->auth_pad_length) {
+		DEBUG(1, (__location__ ": ERROR: pad length to large. "
+			  "max %u got %u\n",
+			  (unsigned)max_pad_len,
+			  (unsigned)auth->auth_pad_length));
+		talloc_free(ndr);
+		ZERO_STRUCTP(auth);
+		return NT_STATUS_RPC_PROTOCOL_ERROR;
+	}
+
+	/*
+	 * This is a workarround for a bug in old
+	 * Samba releases. For BIND_ACK <= 3.5.x
+	 * and for ALTER_RESP <= 4.2.x (see bug #11061)
+	 *
+	 * See also bug #11982.
+	 */
+	if (auth_data_only && data_and_pad == 0 &&
+	    auth->auth_pad_length > 0) {
+		/*
+		 * we need to ignore invalid auth_pad_length
+		 * values for BIND_*, ALTER_* and AUTH3 pdus.
+		 */
+		auth->auth_pad_length = 0;
+	}
+
 	if (data_and_pad < auth->auth_pad_length) {
 		DEBUG(1, (__location__ ": ERROR: pad length mismatch. "
 			  "Calculated %u  got %u\n",
diff --git a/python/samba/tests/dcerpc/raw_protocol.py b/python/samba/tests/dcerpc/raw_protocol.py
index ccd0f6b..8b0bc4e 100755
--- a/python/samba/tests/dcerpc/raw_protocol.py
+++ b/python/samba/tests/dcerpc/raw_protocol.py
@@ -2616,6 +2616,554 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.assertIsNone(rep)
         self.assertNotConnected()
 
+    def test_spnego_auth_pad_ok(self):
+        ndr32 = base.transfer_syntax_ndr()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+        ctx_list = [ctx1]
+
+        c = Credentials()
+        c.set_anonymous()
+        g = gensec.Security.start_client(self.settings)
+        g.set_credentials(c)
+        g.want_feature(gensec.FEATURE_DCE_STYLE)
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_SPNEGO
+        auth_level = dcerpc.DCERPC_AUTH_LEVEL_CONNECT
+        auth_context_id = 2
+        g.start_mech_by_authtype(auth_type, auth_level)
+        from_server = ""
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+
+        req = self.generate_bind(call_id=0,
+                                 ctx_list=ctx_list,
+                                 auth_info=auth_info)
+        req_pdu = samba.ndr.ndr_pack(req)
+
+        auth_pad_ok = len(req_pdu)
+        auth_pad_ok -= dcerpc.DCERPC_REQUEST_LENGTH
+        auth_pad_ok -= dcerpc.DCERPC_AUTH_TRAILER_LENGTH
+        auth_pad_ok -= len(to_server)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_pad_length=auth_pad_ok,
+                                       auth_blob=to_server)
+
+        req = self.generate_bind(call_id=0,
+                                 ctx_list=ctx_list,
+                                 auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 4)
+        self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
+        self.assertEquals(len(rep.u._pad1), 2)
+        #self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertNotEquals(len(rep.u.auth_info), 0)
+        a = self.parse_auth(rep.u.auth_info)
+
+        from_server = a.credentials
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+        req = self.generate_alter(call_id=0,
+                                  ctx_list=ctx_list,
+                                  assoc_group_id=rep.u.assoc_group_id,
+                                  auth_info=auth_info)
+        req_pdu = samba.ndr.ndr_pack(req)
+
+        auth_pad_ok = len(req_pdu)
+        auth_pad_ok -= dcerpc.DCERPC_REQUEST_LENGTH
+        auth_pad_ok -= dcerpc.DCERPC_AUTH_TRAILER_LENGTH
+        auth_pad_ok -= len(to_server)
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_pad_length=auth_pad_ok,
+                                       auth_blob=to_server)
+        req = self.generate_alter(call_id=0,
+                                  ctx_list=ctx_list,
+                                  assoc_group_id=rep.u.assoc_group_id,
+                                  auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_ALTER_RESP, req.call_id)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 0)
+        self.assertEquals(len(rep.u._pad1), 2)
+        # Windows sends garbage
+        #self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertNotEquals(len(rep.u.auth_info), 0)
+        a = self.parse_auth(rep.u.auth_info)
+
+        from_server = a.credentials
+        (finished, to_server) = g.update(from_server)
+        self.assertTrue(finished)
+
+        # And now try a request without auth_info
+        req = self.generate_request(call_id = 2,
+                                    context_id=ctx1.context_id,
+                                    opnum=0,
+                                    stub="")
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
+
+        # Now a request with auth_info DCERPC_AUTH_LEVEL_CONNECT
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob="\x01"+"\x00"*15)
+        req = self.generate_request(call_id = 3,
+                                    context_id=ctx1.context_id,
+                                    opnum=0,
+                                    stub="",
+                                    auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        # We don't get an auth_info back
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
+
+        self._disconnect("disconnect")
+        self.assertNotConnected()
+
+    def test_spnego_auth_pad_fail_bind(self):
+        ndr32 = base.transfer_syntax_ndr()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+        ctx_list = [ctx1]
+
+        c = Credentials()
+        c.set_anonymous()
+        g = gensec.Security.start_client(self.settings)
+        g.set_credentials(c)
+        g.want_feature(gensec.FEATURE_DCE_STYLE)
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_SPNEGO
+        auth_level = dcerpc.DCERPC_AUTH_LEVEL_CONNECT
+        auth_context_id = 2
+        g.start_mech_by_authtype(auth_type, auth_level)
+        from_server = ""
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+
+        req = self.generate_bind(call_id=0,
+                                 ctx_list=ctx_list,
+                                 auth_info=auth_info)
+        req_pdu = samba.ndr.ndr_pack(req)
+
+        auth_pad_ok = len(req_pdu)
+        auth_pad_ok -= dcerpc.DCERPC_REQUEST_LENGTH
+        auth_pad_ok -= dcerpc.DCERPC_AUTH_TRAILER_LENGTH
+        auth_pad_ok -= len(to_server)
+        auth_pad_bad = auth_pad_ok + 1
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_pad_length=auth_pad_bad,
+                                       auth_blob=to_server)
+
+        req = self.generate_bind(call_id=0,
+                                 ctx_list=ctx_list,
+                                 auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_NAK, req.call_id,
+                        auth_length=0)
+        self.assertEquals(rep.u.reject_reason,
+                dcerpc.DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED)
+        self.assertEquals(rep.u.num_versions, 1)
+        self.assertEquals(rep.u.versions[0].rpc_vers, req.rpc_vers)
+        self.assertEquals(rep.u.versions[0].rpc_vers_minor, req.rpc_vers_minor)
+        self.assertEquals(len(rep.u._pad), 3)
+        self.assertEquals(rep.u._pad, '\0' * 3)
+
+        # wait for a disconnect
+        rep = self.recv_pdu()
+        self.assertIsNone(rep)
+        self.assertNotConnected()
+
+    def test_spnego_auth_pad_fail_alter(self):
+        ndr32 = base.transfer_syntax_ndr()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+        ctx_list = [ctx1]
+
+        c = Credentials()
+        c.set_anonymous()
+        g = gensec.Security.start_client(self.settings)
+        g.set_credentials(c)
+        g.want_feature(gensec.FEATURE_DCE_STYLE)
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_SPNEGO
+        auth_level = dcerpc.DCERPC_AUTH_LEVEL_CONNECT
+        auth_context_id = 2
+        g.start_mech_by_authtype(auth_type, auth_level)
+        from_server = ""
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+
+        req = self.generate_bind(call_id=0,
+                                 ctx_list=ctx_list,
+                                 auth_info=auth_info)
+        req_pdu = samba.ndr.ndr_pack(req)
+
+        auth_pad_ok = len(req_pdu)
+        auth_pad_ok -= dcerpc.DCERPC_REQUEST_LENGTH
+        auth_pad_ok -= dcerpc.DCERPC_AUTH_TRAILER_LENGTH
+        auth_pad_ok -= len(to_server)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_pad_length=auth_pad_ok,
+                                       auth_blob=to_server)
+
+        req = self.generate_bind(call_id=0,
+                                 ctx_list=ctx_list,
+                                 auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 4)
+        self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
+        self.assertEquals(len(rep.u._pad1), 2)
+        #self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertNotEquals(len(rep.u.auth_info), 0)
+        a = self.parse_auth(rep.u.auth_info)
+
+        from_server = a.credentials
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+        req = self.generate_alter(call_id=0,
+                                  ctx_list=ctx_list,
+                                  assoc_group_id=rep.u.assoc_group_id,
+                                  auth_info=auth_info)
+        req_pdu = samba.ndr.ndr_pack(req)
+
+        auth_pad_ok = len(req_pdu)
+        auth_pad_ok -= dcerpc.DCERPC_REQUEST_LENGTH
+        auth_pad_ok -= dcerpc.DCERPC_AUTH_TRAILER_LENGTH
+        auth_pad_ok -= len(to_server)
+        auth_pad_bad = auth_pad_ok + 1
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_pad_length=auth_pad_bad,
+                                       auth_blob=to_server)
+        req = self.generate_alter(call_id=0,
+                                  ctx_list=ctx_list,
+                                  assoc_group_id=rep.u.assoc_group_id,
+                                  auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
+                        pfc_flags=req.pfc_flags |
+                        dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, 0)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertEquals(rep.u.status, dcerpc.DCERPC_NCA_S_PROTO_ERROR)
+        self.assertEquals(len(rep.u._pad), 4)
+        self.assertEquals(rep.u._pad, '\0' * 4)
+
+        # wait for a disconnect
+        rep = self.recv_pdu()
+        self.assertIsNone(rep)
+        self.assertNotConnected()
+
+    def test_ntlmssp_auth_pad_ok(self):
+        ndr32 = base.transfer_syntax_ndr()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+        ctx_list = [ctx1]
+
+        c = Credentials()
+        c.set_anonymous()
+        g = gensec.Security.start_client(self.settings)
+        g.set_credentials(c)
+        g.want_feature(gensec.FEATURE_DCE_STYLE)
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        auth_level = dcerpc.DCERPC_AUTH_LEVEL_CONNECT
+        auth_context_id = 2
+        g.start_mech_by_authtype(auth_type, auth_level)
+        from_server = ""
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+
+        req = self.generate_bind(call_id=0,
+                                 ctx_list=ctx_list,
+                                 auth_info=auth_info)
+        req_pdu = samba.ndr.ndr_pack(req)
+
+        auth_pad_ok = len(req_pdu)
+        auth_pad_ok -= dcerpc.DCERPC_REQUEST_LENGTH
+        auth_pad_ok -= dcerpc.DCERPC_AUTH_TRAILER_LENGTH
+        auth_pad_ok -= len(to_server)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_pad_length=auth_pad_ok,
+                                       auth_blob=to_server)
+
+        req = self.generate_bind(call_id=0,
+                                 ctx_list=ctx_list,
+                                 auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 4)
+        self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
+        self.assertEquals(len(rep.u._pad1), 2)
+        #self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertNotEquals(len(rep.u.auth_info), 0)
+        a = self.parse_auth(rep.u.auth_info)
+
+        from_server = a.credentials
+        (finished, to_server) = g.update(from_server)
+        self.assertTrue(finished)
+
+        auth_pad_ok = 0
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_pad_length=auth_pad_ok,
+                                       auth_blob=to_server)


-- 
Samba Shared Repository



More information about the samba-cvs mailing list