diff options
-rw-r--r-- | source4/torture/rpc/handles.c | 244 | ||||
-rw-r--r-- | source4/torture/rpc/rpc.c | 4 |
2 files changed, 247 insertions, 1 deletions
diff --git a/source4/torture/rpc/handles.c b/source4/torture/rpc/handles.c index 113eed0a0f..2dd9350dd7 100644 --- a/source4/torture/rpc/handles.c +++ b/source4/torture/rpc/handles.c @@ -44,6 +44,8 @@ static bool test_handles_lsa(struct torture_context *torture) uint16_t system_name = '\\'; TALLOC_CTX *mem_ctx = talloc_new(torture); + torture_comment(torture, "RPC-HANDLE-LSARPC\n"); + status = torture_rpc_connection(mem_ctx, &p1, &dcerpc_table_lsarpc); torture_assert_ntstatus_ok(torture, status, "opening lsa pipe1"); @@ -97,6 +99,243 @@ static bool test_handles_lsa(struct torture_context *torture) return true; } +static bool test_handles_lsa_shared(struct torture_context *torture) +{ + NTSTATUS status; + struct dcerpc_pipe *p1, *p2, *p3, *p4, *p5; + struct policy_handle handle; + struct policy_handle handle2; + struct lsa_ObjectAttribute attr; + struct lsa_QosInfo qos; + struct lsa_OpenPolicy r; + struct lsa_Close c; + struct lsa_QuerySecurity qsec; + uint16_t system_name = '\\'; + TALLOC_CTX *mem_ctx = talloc_new(torture); + enum dcerpc_transport_t transport; + uint32_t assoc_group_id; + + torture_comment(torture, "RPC-HANDLE-LSARPC-SHARED\n"); + + if (lp_parm_bool(-1, "torture", "samba4", False)) { + torture_comment(torture, "LSA shared-policy-handle test against Samba4 - skipping\n"); + return true; + } + + torture_comment(torture, "connect lsa pipe1\n"); + status = torture_rpc_connection(mem_ctx, &p1, &dcerpc_table_lsarpc); + torture_assert_ntstatus_ok(torture, status, "opening lsa pipe1"); + + transport = p1->conn->transport.transport, + assoc_group_id = p1->assoc_group_id; + + torture_comment(torture, "use assoc_group_id[0x%08X] for new connections\n", assoc_group_id); + + torture_comment(torture, "connect lsa pipe2\n"); + status = torture_rpc_connection_transport(mem_ctx, &p2, &dcerpc_table_lsarpc, + transport, + assoc_group_id); + torture_assert_ntstatus_ok(torture, status, "opening lsa pipe2"); + + qos.len = 0; + qos.impersonation_level = 2; + qos.context_mode = 1; + qos.effective_only = 0; + + attr.len = 0; + attr.root_dir = NULL; + attr.object_name = NULL; + attr.attributes = 0; + attr.sec_desc = NULL; + attr.sec_qos = &qos; + + r.in.system_name = &system_name; + r.in.attr = &attr; + r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + r.out.handle = &handle; + + torture_comment(torture, "open lsa policy handle\n"); + status = dcerpc_lsa_OpenPolicy(p1, mem_ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + torture_comment(torture, "lsa_OpenPolicy not supported - skipping\n"); + talloc_free(mem_ctx); + return true; + } + + /* + * connect p3 after the policy handle is opened + */ + torture_comment(torture, "connect lsa pipe3 after the policy handle is opened\n"); + status = torture_rpc_connection_transport(mem_ctx, &p3, &dcerpc_table_lsarpc, + transport, + assoc_group_id); + torture_assert_ntstatus_ok(torture, status, "opening lsa pipe3"); + + qsec.in.handle = &handle; + qsec.in.sec_info = 0; + c.in.handle = &handle; + c.out.handle = &handle2; + + /* + * use policy handle on all 3 connections + */ + torture_comment(torture, "use the policy handle on p1,p2,p3\n"); + status = dcerpc_lsa_QuerySecurity(p1, mem_ctx, &qsec); + torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, + "use policy handle on p1"); + + status = dcerpc_lsa_QuerySecurity(p2, mem_ctx, &qsec); + torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, + "use policy handle on p2"); + + status = dcerpc_lsa_QuerySecurity(p3, mem_ctx, &qsec); + torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, + "use policy handle on p3"); + + /* + * close policy handle on connection 2 and the others get a fault + */ + torture_comment(torture, "close the policy handle on p2 others get a fault\n"); + status = dcerpc_lsa_Close(p2, mem_ctx, &c); + torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, + "closing policy handle on p2"); + + status = dcerpc_lsa_Close(p1, mem_ctx, &c); + torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, + "closing policy handle on p1 again"); + torture_assert_int_equal(torture, p1->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, + "closing policy handle on p1 again"); + + status = dcerpc_lsa_Close(p3, mem_ctx, &c); + torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, + "closing policy handle on p3"); + torture_assert_int_equal(torture, p1->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, + "closing policy handle on p3"); + + status = dcerpc_lsa_Close(p2, mem_ctx, &c); + torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, + "closing policy handle on p2 again"); + torture_assert_int_equal(torture, p1->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, + "closing policy handle on p2 again"); + + /* + * open a new policy handle on p3 + */ + torture_comment(torture, "open a new policy handle on p3\n"); + status = dcerpc_lsa_OpenPolicy(p3, mem_ctx, &r); + torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, + "open policy handle on p3"); + + /* + * use policy handle on all 3 connections + */ + torture_comment(torture, "use the policy handle on p1,p2,p3\n"); + status = dcerpc_lsa_QuerySecurity(p1, mem_ctx, &qsec); + torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, + "use policy handle on p1"); + + status = dcerpc_lsa_QuerySecurity(p2, mem_ctx, &qsec); + torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, + "use policy handle on p2"); + + status = dcerpc_lsa_QuerySecurity(p3, mem_ctx, &qsec); + torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, + "use policy handle on p3"); + + /* + * close policy handle on connection 2 and the others get a fault + */ + torture_comment(torture, "close the policy handle on p2 others get a fault\n"); + status = dcerpc_lsa_Close(p2, mem_ctx, &c); + torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, + "closing policy handle on p2"); + + status = dcerpc_lsa_Close(p1, mem_ctx, &c); + torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, + "closing policy handle on p1 again"); + torture_assert_int_equal(torture, p1->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, + "closing policy handle on p1 again"); + + status = dcerpc_lsa_Close(p3, mem_ctx, &c); + torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, + "closing policy handle on p3"); + torture_assert_int_equal(torture, p1->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, + "closing policy handle on p3"); + + status = dcerpc_lsa_Close(p2, mem_ctx, &c); + torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, + "closing policy handle on p2 again"); + torture_assert_int_equal(torture, p1->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, + "closing policy handle on p2 again"); + + /* + * open a new policy handle + */ + torture_comment(torture, "open a new policy handle on p1 and use it\n"); + status = dcerpc_lsa_OpenPolicy(p1, mem_ctx, &r); + torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, + "open 2nd policy handle on p1"); + + status = dcerpc_lsa_QuerySecurity(p1, mem_ctx, &qsec); + torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, + "QuerySecurity handle on p1"); + + /* close first connection */ + torture_comment(torture, "disconnect p1\n"); + talloc_free(p1); + msleep(5); + + /* + * and it's still available on p2,p3 + */ + torture_comment(torture, "use policy handle on p2,p3\n"); + status = dcerpc_lsa_QuerySecurity(p2, mem_ctx, &qsec); + torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, + "QuerySecurity handle on p2 after p1 was disconnected"); + + status = dcerpc_lsa_QuerySecurity(p3, mem_ctx, &qsec); + torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, + "QuerySecurity handle on p3 after p1 was disconnected"); + + /* + * now open p4 + * and use the handle on it + */ + torture_comment(torture, "connect lsa pipe4 and use policy handle\n"); + status = torture_rpc_connection_transport(mem_ctx, &p4, &dcerpc_table_lsarpc, + transport, + assoc_group_id); + torture_assert_ntstatus_ok(torture, status, "opening lsa pipe4"); + + status = dcerpc_lsa_QuerySecurity(p4, mem_ctx, &qsec); + torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, + "using policy handle on p4"); + + /* + * now close p2,p3,p4 + * without closing the policy handle + */ + torture_comment(torture, "disconnect p2,p3,p4\n"); + talloc_free(p2); + talloc_free(p3); + talloc_free(p4); + msleep(10); + + /* + * now open p5 + */ + torture_comment(torture, "connect lsa pipe5 - should fail\n"); + status = torture_rpc_connection_transport(mem_ctx, &p5, &dcerpc_table_lsarpc, + transport, + assoc_group_id); + torture_assert_ntstatus_equal(torture, status, NT_STATUS_UNSUCCESSFUL, + "opening lsa pipe5"); + + talloc_free(mem_ctx); + + return true; +} + static bool test_handles_samr(struct torture_context *torture) { @@ -108,6 +347,8 @@ static bool test_handles_samr(struct torture_context *torture) struct samr_Close c; TALLOC_CTX *mem_ctx = talloc_new(torture); + torture_comment(torture, "RPC-HANDLE-SAMR\n"); + status = torture_rpc_connection(mem_ctx, &p1, &dcerpc_table_samr); torture_assert_ntstatus_ok(torture, status, "opening samr pipe1"); @@ -156,6 +397,8 @@ static bool test_handles_drsuapi(struct torture_context *torture) struct drsuapi_DsUnbind c; TALLOC_CTX *mem_ctx = talloc_new(torture); + torture_comment(torture, "RPC-HANDLE-DRSUAPI\n"); + status = torture_rpc_connection(mem_ctx, &p1, &dcerpc_table_drsuapi); torture_assert_ntstatus_ok(torture, status, "opening drsuapi pipe1"); @@ -205,6 +448,7 @@ struct torture_suite *torture_rpc_handles(void) suite = torture_suite_create(talloc_autofree_context(), "HANDLES"); torture_suite_add_simple_test(suite, "lsarpc", test_handles_lsa); + torture_suite_add_simple_test(suite, "lsarpc-shared", test_handles_lsa_shared); torture_suite_add_simple_test(suite, "samr", test_handles_samr); torture_suite_add_simple_test(suite, "drsuapi", test_handles_drsuapi); return suite; diff --git a/source4/torture/rpc/rpc.c b/source4/torture/rpc/rpc.c index 5348a87489..c3060d08d7 100644 --- a/source4/torture/rpc/rpc.c +++ b/source4/torture/rpc/rpc.c @@ -56,7 +56,8 @@ _PUBLIC_ NTSTATUS torture_rpc_connection(TALLOC_CTX *parent_ctx, NTSTATUS torture_rpc_connection_transport(TALLOC_CTX *parent_ctx, struct dcerpc_pipe **p, const struct dcerpc_interface_table *table, - enum dcerpc_transport_t transport) + enum dcerpc_transport_t transport, + uint32_t assoc_group_id) { NTSTATUS status; const char *binding = lp_parm_string(-1, "torture", "binding"); @@ -77,6 +78,7 @@ NTSTATUS torture_rpc_connection_transport(TALLOC_CTX *parent_ctx, } b->transport = transport; + b->assoc_group_id = assoc_group_id; status = dcerpc_pipe_connect_b(mem_ctx, p, b, table, cmdline_credentials, NULL); |