/* test two schannel connections */ bool torture_rpc_schannel2(struct torture_context *torture) { struct test_join *join_ctx; NTSTATUS status; const char *binding = torture_setting_string(torture, "binding", NULL); struct dcerpc_binding *b; struct dcerpc_pipe *p1 = NULL, *p2 = NULL; struct cli_credentials *credentials1, *credentials2; uint32_t dcerpc_flags = DCERPC_SCHANNEL | DCERPC_SIGN; join_ctx = torture_join_domain(torture, talloc_asprintf(torture, "%s2", TEST_MACHINE_NAME), ACB_WSTRUST, &credentials1); torture_assert(torture, join_ctx != NULL, "Failed to join domain with acct_flags=ACB_WSTRUST"); credentials2 = cli_credentials_shallow_copy(torture, credentials1); cli_credentials_set_netlogon_creds(credentials1, NULL); cli_credentials_set_netlogon_creds(credentials2, NULL); status = dcerpc_parse_binding(torture, binding, &b); torture_assert_ntstatus_ok(torture, status, "Bad binding string"); status = dcerpc_binding_set_flags(b, dcerpc_flags, DCERPC_AUTH_OPTIONS); torture_assert_ntstatus_ok(torture, status, "set flags"); torture_comment(torture, "Opening first connection\n"); status = dcerpc_pipe_connect_b(torture, &p1, b, &ndr_table_netlogon, credentials1, torture->ev, torture->lp_ctx); torture_assert_ntstatus_ok(torture, status, "Failed to connect with schannel"); torture_comment(torture, "Opening second connection\n"); status = dcerpc_pipe_connect_b(torture, &p2, b, &ndr_table_netlogon, credentials2, torture->ev, torture->lp_ctx); torture_assert_ntstatus_ok(torture, status, "Failed to connect with schannel"); cli_credentials_set_netlogon_creds(credentials1, NULL); cli_credentials_set_netlogon_creds(credentials2, NULL); torture_comment(torture, "Testing logon on pipe1\n"); if (!test_netlogon_ex_ops(p1, torture, credentials1, NULL)) return false; torture_comment(torture, "Testing logon on pipe2\n"); if (!test_netlogon_ex_ops(p2, torture, credentials2, NULL)) return false; torture_comment(torture, "Again on pipe1\n"); if (!test_netlogon_ex_ops(p1, torture, credentials1, NULL)) return false; torture_comment(torture, "Again on pipe2\n"); if (!test_netlogon_ex_ops(p2, torture, credentials2, NULL)) return false; torture_leave_domain(torture, join_ctx); return true; }
/* test a schannel connection with the given flags */ static bool test_schannel(struct torture_context *tctx, uint16_t acct_flags, uint32_t dcerpc_flags, int i) { struct test_join *join_ctx; NTSTATUS status; const char *binding = torture_setting_string(tctx, "binding", NULL); struct dcerpc_binding *b; struct dcerpc_pipe *p = NULL; struct dcerpc_pipe *p_netlogon = NULL; struct dcerpc_pipe *p_netlogon2 = NULL; struct dcerpc_pipe *p_netlogon3 = NULL; struct dcerpc_pipe *p_samr2 = NULL; struct dcerpc_pipe *p_lsa = NULL; struct netlogon_creds_CredentialState *creds; struct cli_credentials *credentials; join_ctx = torture_join_domain(tctx, talloc_asprintf(tctx, "%s%d", TEST_MACHINE_NAME, i), acct_flags, &credentials); torture_assert(tctx, join_ctx != NULL, "Failed to join domain"); status = dcerpc_parse_binding(tctx, binding, &b); torture_assert_ntstatus_ok(tctx, status, "Bad binding string"); b->flags &= ~DCERPC_AUTH_OPTIONS; b->flags |= dcerpc_flags; status = dcerpc_pipe_connect_b(tctx, &p, b, &ndr_table_samr, credentials, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "Failed to connect with schannel"); torture_assert(tctx, test_samr_ops(tctx, p->binding_handle), "Failed to process schannel secured SAMR ops"); /* Also test that when we connect to the netlogon pipe, that * the credentials we setup on the first pipe are valid for * the second */ /* Swap the binding details from SAMR to NETLOGON */ status = dcerpc_epm_map_binding(tctx, b, &ndr_table_netlogon, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "epm map"); status = dcerpc_secondary_connection(p, &p_netlogon, b); torture_assert_ntstatus_ok(tctx, status, "seconday connection"); status = dcerpc_bind_auth(p_netlogon, &ndr_table_netlogon, credentials, lpcfg_gensec_settings(tctx, tctx->lp_ctx), DCERPC_AUTH_TYPE_SCHANNEL, dcerpc_auth_level(p->conn), NULL); torture_assert_ntstatus_ok(tctx, status, "bind auth"); status = dcerpc_schannel_creds(p_netlogon->conn->security_state.generic_state, tctx, &creds); torture_assert_ntstatus_ok(tctx, status, "schannel creds"); /* do a couple of logins */ torture_assert(tctx, test_netlogon_ops(p_netlogon, tctx, credentials, creds), "Failed to process schannel secured NETLOGON ops"); torture_assert(tctx, test_netlogon_ex_ops(p_netlogon, tctx, credentials, creds), "Failed to process schannel secured NETLOGON EX ops"); /* Swap the binding details from SAMR to LSARPC */ status = dcerpc_epm_map_binding(tctx, b, &ndr_table_lsarpc, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "epm map"); status = dcerpc_secondary_connection(p, &p_lsa, b); torture_assert_ntstatus_ok(tctx, status, "seconday connection"); status = dcerpc_bind_auth(p_lsa, &ndr_table_lsarpc, credentials, lpcfg_gensec_settings(tctx, tctx->lp_ctx), DCERPC_AUTH_TYPE_SCHANNEL, dcerpc_auth_level(p->conn), NULL); torture_assert_ntstatus_ok(tctx, status, "bind auth"); torture_assert(tctx, test_lsa_ops(tctx, p_lsa), "Failed to process schannel secured LSA ops"); /* Drop the socket, we want to start from scratch */ talloc_free(p); p = NULL; /* Now see what we are still allowed to do */ status = dcerpc_parse_binding(tctx, binding, &b); torture_assert_ntstatus_ok(tctx, status, "Bad binding string"); b->flags &= ~DCERPC_AUTH_OPTIONS; b->flags |= dcerpc_flags; status = dcerpc_pipe_connect_b(tctx, &p_samr2, b, &ndr_table_samr, credentials, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "Failed to connect with schannel"); /* do a some SAMR operations. We have *not* done a new serverauthenticate */ torture_assert (tctx, test_samr_ops(tctx, p_samr2->binding_handle), "Failed to process schannel secured SAMR ops (on fresh connection)"); /* Swap the binding details from SAMR to NETLOGON */ status = dcerpc_epm_map_binding(tctx, b, &ndr_table_netlogon, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "epm"); status = dcerpc_secondary_connection(p_samr2, &p_netlogon2, b); torture_assert_ntstatus_ok(tctx, status, "seconday connection"); /* and now setup an SCHANNEL bind on netlogon */ status = dcerpc_bind_auth(p_netlogon2, &ndr_table_netlogon, credentials, lpcfg_gensec_settings(tctx, tctx->lp_ctx), DCERPC_AUTH_TYPE_SCHANNEL, dcerpc_auth_level(p_samr2->conn), NULL); torture_assert_ntstatus_ok(tctx, status, "auth failed"); /* Try the schannel-only SamLogonEx operation */ torture_assert(tctx, test_netlogon_ex_ops(p_netlogon2, tctx, credentials, creds), "Failed to process schannel secured NETLOGON EX ops (on fresh connection)"); /* And the more traditional style, proving that the * credentials chaining state is fully present */ torture_assert(tctx, test_netlogon_ops(p_netlogon2, tctx, credentials, creds), "Failed to process schannel secured NETLOGON ops (on fresh connection)"); /* Drop the socket, we want to start from scratch (again) */ talloc_free(p_samr2); /* We don't want schannel for this test */ b->flags &= ~DCERPC_AUTH_OPTIONS; status = dcerpc_pipe_connect_b(tctx, &p_netlogon3, b, &ndr_table_netlogon, credentials, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "Failed to connect without schannel"); torture_assert(tctx, !test_netlogon_ex_ops(p_netlogon3, tctx, credentials, creds), "Processed NOT schannel secured NETLOGON EX ops without SCHANNEL (unsafe)"); /* Required because the previous call will mark the current context as having failed */ tctx->last_result = TORTURE_OK; tctx->last_reason = NULL; torture_assert(tctx, test_netlogon_ops(p_netlogon3, tctx, credentials, creds), "Failed to processed NOT schannel secured NETLOGON ops without new ServerAuth"); torture_leave_domain(tctx, join_ctx); return true; }
/* test a schannel connection with the given flags */ static bool test_schannel(struct torture_context *tctx, uint16_t acct_flags, uint32_t dcerpc_flags, int i) { struct test_join *join_ctx; NTSTATUS status; const char *binding = torture_setting_string(tctx, "binding", NULL); struct dcerpc_binding *b; struct dcerpc_pipe *p = NULL; struct dcerpc_pipe *p_netlogon = NULL; struct dcerpc_pipe *p_netlogon2 = NULL; struct dcerpc_pipe *p_netlogon3 = NULL; struct dcerpc_pipe *p_samr2 = NULL; struct dcerpc_pipe *p_lsa = NULL; struct netlogon_creds_CredentialState *creds; struct cli_credentials *credentials; enum dcerpc_transport_t transport; join_ctx = torture_join_domain(tctx, talloc_asprintf(tctx, "%s%d", TEST_MACHINE_NAME, i), acct_flags, &credentials); torture_assert(tctx, join_ctx != NULL, "Failed to join domain"); status = dcerpc_parse_binding(tctx, binding, &b); torture_assert_ntstatus_ok(tctx, status, "Bad binding string"); status = dcerpc_binding_set_flags(b, dcerpc_flags, DCERPC_AUTH_OPTIONS); torture_assert_ntstatus_ok(tctx, status, "set flags"); status = dcerpc_pipe_connect_b(tctx, &p, b, &ndr_table_samr, credentials, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "Failed to connect to samr with schannel"); torture_assert(tctx, test_samr_ops(tctx, p->binding_handle), "Failed to process schannel secured SAMR ops"); /* Also test that when we connect to the netlogon pipe, that * the credentials we setup on the first pipe are valid for * the second */ /* Swap the binding details from SAMR to NETLOGON */ status = dcerpc_epm_map_binding(tctx, b, &ndr_table_netlogon, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "epm map"); status = dcerpc_binding_set_flags(b, dcerpc_flags, DCERPC_AUTH_OPTIONS); torture_assert_ntstatus_ok(tctx, status, "set flags"); status = dcerpc_secondary_auth_connection(p, b, &ndr_table_netlogon, credentials, tctx->lp_ctx, tctx, &p_netlogon); torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection"); creds = cli_credentials_get_netlogon_creds(credentials); torture_assert(tctx, (creds != NULL), "schannel creds"); /* checks the capabilities */ torture_assert(tctx, test_netlogon_capabilities(p_netlogon, tctx, credentials, creds), "Failed to process schannel secured capability ops (on fresh connection)"); /* do a couple of logins */ torture_assert(tctx, test_netlogon_ops(p_netlogon, tctx, credentials, creds), "Failed to process schannel secured NETLOGON ops"); torture_assert(tctx, test_netlogon_ex_ops(p_netlogon, tctx, credentials, creds), "Failed to process schannel secured NETLOGON EX ops"); /* we *MUST* use ncacn_np for openpolicy etc. */ transport = dcerpc_binding_get_transport(b); status = dcerpc_binding_set_transport(b, NCACN_NP); torture_assert_ntstatus_ok(tctx, status, "set transport"); /* Swap the binding details from SAMR to LSARPC */ status = dcerpc_epm_map_binding(tctx, b, &ndr_table_lsarpc, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "epm map"); torture_assert_ntstatus_ok(tctx, dcerpc_pipe_connect_b(tctx, &p_lsa, b, &ndr_table_lsarpc, credentials, tctx->ev, tctx->lp_ctx), "failed to connect lsarpc with schannel"); torture_assert(tctx, test_lsa_ops(tctx, p_lsa), "Failed to process schannel secured LSA ops"); talloc_free(p_lsa); p_lsa = NULL; /* we *MUST* use ncacn_ip_tcp for lookupsids3/lookupnames4 */ status = dcerpc_binding_set_transport(b, NCACN_IP_TCP); torture_assert_ntstatus_ok(tctx, status, "set transport"); torture_assert_ntstatus_ok(tctx, dcerpc_epm_map_binding(tctx, b, &ndr_table_lsarpc, tctx->ev, tctx->lp_ctx), "failed to call epm map"); torture_assert_ntstatus_ok(tctx, dcerpc_pipe_connect_b(tctx, &p_lsa, b, &ndr_table_lsarpc, credentials, tctx->ev, tctx->lp_ctx), "failed to connect lsarpc with schannel"); torture_assert(tctx, test_many_LookupSids(p_lsa, tctx, NULL), "LsaLookupSids3 failed!\n"); status = dcerpc_binding_set_transport(b, transport); torture_assert_ntstatus_ok(tctx, status, "set transport"); /* Drop the socket, we want to start from scratch */ talloc_free(p); p = NULL; /* Now see what we are still allowed to do */ status = dcerpc_parse_binding(tctx, binding, &b); torture_assert_ntstatus_ok(tctx, status, "Bad binding string"); status = dcerpc_binding_set_flags(b, dcerpc_flags, DCERPC_AUTH_OPTIONS); torture_assert_ntstatus_ok(tctx, status, "set flags"); status = dcerpc_pipe_connect_b(tctx, &p_samr2, b, &ndr_table_samr, credentials, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "Failed to connect with schannel"); /* do a some SAMR operations. We have *not* done a new serverauthenticate */ torture_assert (tctx, test_samr_ops(tctx, p_samr2->binding_handle), "Failed to process schannel secured SAMR ops (on fresh connection)"); /* Swap the binding details from SAMR to NETLOGON */ status = dcerpc_epm_map_binding(tctx, b, &ndr_table_netlogon, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "epm"); status = dcerpc_binding_set_flags(b, dcerpc_flags, DCERPC_AUTH_OPTIONS); torture_assert_ntstatus_ok(tctx, status, "set flags"); status = dcerpc_secondary_auth_connection(p_samr2, b, &ndr_table_netlogon, credentials, tctx->lp_ctx, tctx, &p_netlogon2); torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection"); /* checks the capabilities */ torture_assert(tctx, test_netlogon_capabilities(p_netlogon2, tctx, credentials, creds), "Failed to process schannel secured capability ops (on fresh connection)"); /* Try the schannel-only SamLogonEx operation */ torture_assert(tctx, test_netlogon_ex_ops(p_netlogon2, tctx, credentials, creds), "Failed to process schannel secured NETLOGON EX ops (on fresh connection)"); /* And the more traditional style, proving that the * credentials chaining state is fully present */ torture_assert(tctx, test_netlogon_ops(p_netlogon2, tctx, credentials, creds), "Failed to process schannel secured NETLOGON ops (on fresh connection)"); /* Drop the socket, we want to start from scratch (again) */ talloc_free(p_samr2); /* We don't want schannel for this test */ status = dcerpc_binding_set_flags(b, 0, DCERPC_AUTH_OPTIONS); torture_assert_ntstatus_ok(tctx, status, "set flags"); status = dcerpc_pipe_connect_b(tctx, &p_netlogon3, b, &ndr_table_netlogon, credentials, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "Failed to connect without schannel"); torture_assert(tctx, !test_netlogon_ex_ops(p_netlogon3, tctx, credentials, creds), "Processed NOT schannel secured NETLOGON EX ops without SCHANNEL (unsafe)"); /* Required because the previous call will mark the current context as having failed */ tctx->last_result = TORTURE_OK; tctx->last_reason = NULL; torture_assert(tctx, test_netlogon_ops(p_netlogon3, tctx, credentials, creds), "Failed to processed NOT schannel secured NETLOGON ops without new ServerAuth"); torture_leave_domain(tctx, join_ctx); return true; }
/* test a schannel connection with the given flags */ static BOOL test_schannel(TALLOC_CTX *mem_ctx, uint16_t acct_flags, uint32_t dcerpc_flags, int i) { BOOL ret = True; struct test_join *join_ctx; NTSTATUS status; const char *binding = lp_parm_string(-1, "torture", "binding"); struct dcerpc_binding *b; struct dcerpc_pipe *p = NULL; struct dcerpc_pipe *p_netlogon = NULL; struct dcerpc_pipe *p_netlogon2 = NULL; struct dcerpc_pipe *p_netlogon3 = NULL; struct dcerpc_pipe *p_samr2 = NULL; struct dcerpc_pipe *p_lsa = NULL; struct creds_CredentialState *creds; struct cli_credentials *credentials; TALLOC_CTX *test_ctx = talloc_named(mem_ctx, 0, "test_schannel context"); join_ctx = torture_join_domain(talloc_asprintf(mem_ctx, "%s%d", TEST_MACHINE_NAME, i), acct_flags, &credentials); if (!join_ctx) { printf("Failed to join domain with acct_flags=0x%x\n", acct_flags); talloc_free(test_ctx); return False; } status = dcerpc_parse_binding(test_ctx, binding, &b); if (!NT_STATUS_IS_OK(status)) { printf("Bad binding string %s\n", binding); goto failed; } b->flags &= ~DCERPC_AUTH_OPTIONS; b->flags |= dcerpc_flags; status = dcerpc_pipe_connect_b(test_ctx, &p, b, &dcerpc_table_samr, credentials, NULL); if (!NT_STATUS_IS_OK(status)) { printf("Failed to connect with schannel: %s\n", nt_errstr(status)); goto failed; } if (!test_samr_ops(p, test_ctx)) { printf("Failed to process schannel secured SAMR ops\n"); ret = False; } /* Also test that when we connect to the netlogon pipe, that * the credentials we setup on the first pipe are valid for * the second */ /* Swap the binding details from SAMR to NETLOGON */ status = dcerpc_epm_map_binding(test_ctx, b, &dcerpc_table_netlogon, NULL); if (!NT_STATUS_IS_OK(status)) { goto failed; } status = dcerpc_secondary_connection(p, &p_netlogon, b); if (!NT_STATUS_IS_OK(status)) { goto failed; } status = dcerpc_bind_auth(p_netlogon, &dcerpc_table_netlogon, credentials, DCERPC_AUTH_TYPE_SCHANNEL, dcerpc_auth_level(p->conn), NULL); if (!NT_STATUS_IS_OK(status)) { goto failed; } status = dcerpc_schannel_creds(p_netlogon->conn->security_state.generic_state, test_ctx, &creds); if (!NT_STATUS_IS_OK(status)) { goto failed; } /* do a couple of logins */ if (!test_netlogon_ops(p_netlogon, test_ctx, credentials, creds)) { printf("Failed to process schannel secured NETLOGON ops\n"); ret = False; } if (!test_netlogon_ex_ops(p_netlogon, test_ctx, credentials, creds)) { printf("Failed to process schannel secured NETLOGON EX ops\n"); ret = False; } /* Swap the binding details from SAMR to LSARPC */ status = dcerpc_epm_map_binding(test_ctx, b, &dcerpc_table_lsarpc, NULL); if (!NT_STATUS_IS_OK(status)) { goto failed; } status = dcerpc_secondary_connection(p, &p_lsa, b); if (!NT_STATUS_IS_OK(status)) { goto failed; } status = dcerpc_bind_auth(p_lsa, &dcerpc_table_lsarpc, credentials, DCERPC_AUTH_TYPE_SCHANNEL, dcerpc_auth_level(p->conn), NULL); if (!NT_STATUS_IS_OK(status)) { goto failed; } if (!test_lsa_ops(p_lsa, test_ctx)) { printf("Failed to process schannel secured LSA ops\n"); ret = False; } /* Drop the socket, we want to start from scratch */ talloc_free(p); p = NULL; /* Now see what we are still allowed to do */ status = dcerpc_parse_binding(test_ctx, binding, &b); if (!NT_STATUS_IS_OK(status)) { printf("Bad binding string %s\n", binding); goto failed; } b->flags &= ~DCERPC_AUTH_OPTIONS; b->flags |= dcerpc_flags; status = dcerpc_pipe_connect_b(test_ctx, &p_samr2, b, &dcerpc_table_samr, credentials, NULL); if (!NT_STATUS_IS_OK(status)) { printf("Failed to connect with schannel: %s\n", nt_errstr(status)); goto failed; } /* do a some SAMR operations. We have *not* done a new serverauthenticate */ if (!test_samr_ops(p_samr2, test_ctx)) { printf("Failed to process schannel secured SAMR ops (on fresh connection)\n"); goto failed; } /* Swap the binding details from SAMR to NETLOGON */ status = dcerpc_epm_map_binding(test_ctx, b, &dcerpc_table_netlogon, NULL); if (!NT_STATUS_IS_OK(status)) { goto failed; } status = dcerpc_secondary_connection(p_samr2, &p_netlogon2, b); if (!NT_STATUS_IS_OK(status)) { goto failed; } /* and now setup an SCHANNEL bind on netlogon */ status = dcerpc_bind_auth(p_netlogon2, &dcerpc_table_netlogon, credentials, DCERPC_AUTH_TYPE_SCHANNEL, dcerpc_auth_level(p_samr2->conn), NULL); if (!NT_STATUS_IS_OK(status)) { goto failed; } /* Try the schannel-only SamLogonEx operation */ if (!test_netlogon_ex_ops(p_netlogon2, test_ctx, credentials, creds)) { printf("Failed to process schannel secured NETLOGON EX ops (on fresh connection)\n"); ret = False; } /* And the more traditional style, proving that the * credentials chaining state is fully present */ if (!test_netlogon_ops(p_netlogon2, test_ctx, credentials, creds)) { printf("Failed to process schannel secured NETLOGON ops (on fresh connection)\n"); ret = False; } /* Drop the socket, we want to start from scratch (again) */ talloc_free(p_samr2); /* We don't want schannel for this test */ b->flags &= ~DCERPC_AUTH_OPTIONS; status = dcerpc_pipe_connect_b(test_ctx, &p_netlogon3, b, &dcerpc_table_netlogon, credentials, NULL); if (!NT_STATUS_IS_OK(status)) { printf("Failed to connect without schannel: %s\n", nt_errstr(status)); goto failed; } if (test_netlogon_ex_ops(p_netlogon3, test_ctx, credentials, creds)) { printf("Processed NOT schannel secured NETLOGON EX ops without SCHANNEL (unsafe)\n"); ret = False; } if (!test_netlogon_ops(p_netlogon3, test_ctx, credentials, creds)) { printf("Failed to processed NOT schannel secured NETLOGON ops without new ServerAuth\n"); ret = False; } torture_leave_domain(join_ctx); talloc_free(test_ctx); return ret; failed: torture_leave_domain(join_ctx); talloc_free(test_ctx); return False; }