From 0a9049be872a0eaf56c1449f8b362b6d91dd781b Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 18 May 2009 19:37:13 +0200 Subject: s4-smbtorture: add RPC-SAMR-USERS-PRIVILEGES test. This test demonstrates the independence of the lsa and samr accounts while remove a samr users that still has privileges granted. Guenther --- source4/torture/rpc/rpc.c | 1 + source4/torture/rpc/samr.c | 395 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 387 insertions(+), 9 deletions(-) diff --git a/source4/torture/rpc/rpc.c b/source4/torture/rpc/rpc.c index 647d51470d..48a488741f 100644 --- a/source4/torture/rpc/rpc.c +++ b/source4/torture/rpc/rpc.c @@ -408,6 +408,7 @@ NTSTATUS torture_rpc_init(void) torture_suite_add_suite(suite, torture_rpc_svcctl(suite)); torture_suite_add_suite(suite, torture_rpc_samr_accessmask(suite)); torture_suite_add_suite(suite, torture_rpc_samr_passwords_pwdlastset(suite)); + torture_suite_add_suite(suite, torture_rpc_samr_user_privileges(suite)); torture_suite_add_suite(suite, torture_rpc_epmapper(suite)); torture_suite_add_suite(suite, torture_rpc_initshutdown(suite)); torture_suite_add_suite(suite, torture_rpc_oxidresolve(suite)); diff --git a/source4/torture/rpc/samr.c b/source4/torture/rpc/samr.c index c1535577d6..4037e6b11c 100644 --- a/source4/torture/rpc/samr.c +++ b/source4/torture/rpc/samr.c @@ -4,6 +4,7 @@ Copyright (C) Andrew Tridgell 2003 Copyright (C) Andrew Bartlett 2003 + Copyright (C) Guenther Deschner 2008,2009 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,6 +27,7 @@ #include "librpc/gen_ndr/ndr_netlogon.h" #include "librpc/gen_ndr/ndr_netlogon_c.h" #include "librpc/gen_ndr/ndr_samr_c.h" +#include "librpc/gen_ndr/ndr_lsa_c.h" #include "../lib/crypto/crypto.h" #include "libcli/auth/libcli_auth.h" #include "libcli/security/security.h" @@ -45,6 +47,7 @@ enum torture_samr_choice { TORTURE_SAMR_PASSWORDS, TORTURE_SAMR_PASSWORDS_PWDLASTSET, TORTURE_SAMR_USER_ATTRIBUTES, + TORTURE_SAMR_USER_PRIVILEGES, TORTURE_SAMR_OTHER }; @@ -70,6 +73,11 @@ static void init_lsa_String(struct lsa_String *string, const char *s) string->string = s; } +static void init_lsa_StringLarge(struct lsa_StringLarge *string, const char *s) +{ + string->string = s; +} + static void init_lsa_BinaryString(struct lsa_BinaryString *string, const char *s, uint32_t length) { string->length = length; @@ -3267,10 +3275,307 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p, return ret; } +static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p, + struct dcerpc_pipe *lp, + struct torture_context *tctx, + struct policy_handle *domain_handle, + struct policy_handle *lsa_handle, + struct policy_handle *user_handle, + const struct dom_sid *domain_sid, + uint32_t rid, + struct cli_credentials *machine_credentials) +{ + NTSTATUS status; + bool ret = true; + + struct policy_handle lsa_acct_handle; + struct dom_sid *user_sid; + + user_sid = dom_sid_add_rid(tctx, domain_sid, rid); + + { + struct lsa_EnumAccountRights r; + struct lsa_RightSet rights; + + printf("Testing LSA EnumAccountRights\n"); + + r.in.handle = lsa_handle; + r.in.sid = user_sid; + r.out.rights = &rights; + + status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r); + torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, + "Expected enum rights for account to fail"); + } + + { + struct lsa_RightSet rights; + struct lsa_StringLarge names[2]; + struct lsa_AddAccountRights r; + + printf("Testing LSA AddAccountRights\n"); + + init_lsa_StringLarge(&names[0], "SeMachineAccountPrivilege"); + init_lsa_StringLarge(&names[1], NULL); + + rights.count = 1; + rights.names = names; + + r.in.handle = lsa_handle; + r.in.sid = user_sid; + r.in.rights = &rights; + + status = dcerpc_lsa_AddAccountRights(lp, tctx, &r); + torture_assert_ntstatus_ok(tctx, status, + "Failed to add privileges"); + } + + { + struct lsa_EnumAccounts r; + uint32_t resume_handle = 0; + struct lsa_SidArray lsa_sid_array; + int i; + bool found_sid = false; + + printf("Testing LSA EnumAccounts\n"); + + r.in.handle = lsa_handle; + r.in.num_entries = 0x1000; + r.in.resume_handle = &resume_handle; + r.out.sids = &lsa_sid_array; + r.out.resume_handle = &resume_handle; + + status = dcerpc_lsa_EnumAccounts(lp, tctx, &r); + torture_assert_ntstatus_ok(tctx, status, + "Failed to enum accounts"); + + for (i=0; i < lsa_sid_array.num_sids; i++) { + if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) { + found_sid = true; + } + } + + torture_assert(tctx, found_sid, + "failed to list privileged account"); + } + + { + struct lsa_EnumAccountRights r; + struct lsa_RightSet user_rights; + + printf("Testing LSA EnumAccountRights\n"); + + r.in.handle = lsa_handle; + r.in.sid = user_sid; + r.out.rights = &user_rights; + + status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r); + torture_assert_ntstatus_ok(tctx, status, + "Failed to enum rights for account"); + + if (user_rights.count < 1) { + torture_warning(tctx, "failed to find newly added rights"); + return false; + } + } + + { + struct lsa_OpenAccount r; + + printf("Testing LSA OpenAccount\n"); + + r.in.handle = lsa_handle; + r.in.sid = user_sid; + r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + r.out.acct_handle = &lsa_acct_handle; + + status = dcerpc_lsa_OpenAccount(lp, tctx, &r); + torture_assert_ntstatus_ok(tctx, status, + "Failed to open lsa account"); + } + + { + struct lsa_GetSystemAccessAccount r; + uint32_t access_mask; + + printf("Testing LSA GetSystemAccessAccount\n"); + + r.in.handle = &lsa_acct_handle; + r.out.access_mask = &access_mask; + + status = dcerpc_lsa_GetSystemAccessAccount(lp, tctx, &r); + torture_assert_ntstatus_ok(tctx, status, + "Failed to get lsa system access account"); + } + + { + struct lsa_Close r; + + printf("Testing LSA Close\n"); + + r.in.handle = &lsa_acct_handle; + r.out.handle = &lsa_acct_handle; + + status = dcerpc_lsa_Close(lp, tctx, &r); + torture_assert_ntstatus_ok(tctx, status, + "Failed to close lsa"); + } + + { + struct samr_DeleteUser r; + + printf("Testing SAMR DeleteUser\n"); + + r.in.user_handle = user_handle; + r.out.user_handle = user_handle; + + status = dcerpc_samr_DeleteUser(p, tctx, &r); + torture_assert_ntstatus_ok(tctx, status, "Delete User failed"); + } + + { + struct lsa_EnumAccounts r; + uint32_t resume_handle = 0; + struct lsa_SidArray lsa_sid_array; + int i; + bool found_sid = false; + + printf("Testing LSA EnumAccounts\n"); + + r.in.handle = lsa_handle; + r.in.num_entries = 0x1000; + r.in.resume_handle = &resume_handle; + r.out.sids = &lsa_sid_array; + r.out.resume_handle = &resume_handle; + + status = dcerpc_lsa_EnumAccounts(lp, tctx, &r); + torture_assert_ntstatus_ok(tctx, status, + "Failed to enum accounts"); + + for (i=0; i < lsa_sid_array.num_sids; i++) { + if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) { + found_sid = true; + } + } + + torture_assert(tctx, found_sid, + "failed to list privileged account"); + } + + { + struct lsa_EnumAccountRights r; + struct lsa_RightSet user_rights; + + printf("Testing LSA EnumAccountRights\n"); + + r.in.handle = lsa_handle; + r.in.sid = user_sid; + r.out.rights = &user_rights; + + status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r); + torture_assert_ntstatus_ok(tctx, status, + "Failed to enum rights for account"); + + if (user_rights.count < 1) { + torture_warning(tctx, "failed to find newly added rights"); + return false; + } + } + + { + struct lsa_OpenAccount r; + + printf("Testing LSA OpenAccount\n"); + + r.in.handle = lsa_handle; + r.in.sid = user_sid; + r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + r.out.acct_handle = &lsa_acct_handle; + + status = dcerpc_lsa_OpenAccount(lp, tctx, &r); + torture_assert_ntstatus_ok(tctx, status, + "Failed to open lsa account"); + } + + { + struct lsa_GetSystemAccessAccount r; + uint32_t access_mask; + + printf("Testing LSA GetSystemAccessAccount\n"); + + r.in.handle = &lsa_acct_handle; + r.out.access_mask = &access_mask; + + status = dcerpc_lsa_GetSystemAccessAccount(lp, tctx, &r); + torture_assert_ntstatus_ok(tctx, status, + "Failed to get lsa system access account"); + } + + { + struct lsa_DeleteObject r; + + printf("Testing LSA DeleteObject\n"); + + r.in.handle = &lsa_acct_handle; + r.out.handle = &lsa_acct_handle; + + status = dcerpc_lsa_DeleteObject(lp, tctx, &r); + torture_assert_ntstatus_ok(tctx, status, + "Failed to delete object"); + } + + { + struct lsa_EnumAccounts r; + uint32_t resume_handle = 0; + struct lsa_SidArray lsa_sid_array; + int i; + bool found_sid = false; + + printf("Testing LSA EnumAccounts\n"); + + r.in.handle = lsa_handle; + r.in.num_entries = 0x1000; + r.in.resume_handle = &resume_handle; + r.out.sids = &lsa_sid_array; + r.out.resume_handle = &resume_handle; + + status = dcerpc_lsa_EnumAccounts(lp, tctx, &r); + torture_assert_ntstatus_ok(tctx, status, + "Failed to enum accounts"); + + for (i=0; i < lsa_sid_array.num_sids; i++) { + if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) { + found_sid = true; + } + } + + torture_assert(tctx, !found_sid, + "should not have listed privileged account"); + } + + { + struct lsa_EnumAccountRights r; + struct lsa_RightSet user_rights; + + printf("Testing LSA EnumAccountRights\n"); + + r.in.handle = lsa_handle; + r.in.sid = user_sid; + r.out.rights = &user_rights; + + status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r); + torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, + "Failed to enum rights for account"); + } + + return ret; +} + static bool test_user_ops(struct dcerpc_pipe *p, struct torture_context *tctx, struct policy_handle *user_handle, struct policy_handle *domain_handle, + const struct dom_sid *domain_sid, uint32_t base_acct_flags, const char *base_acct_name, enum torture_samr_choice which_ops, struct cli_credentials *machine_credentials) @@ -3469,6 +3774,35 @@ static bool test_user_ops(struct dcerpc_pipe *p, break; + case TORTURE_SAMR_USER_PRIVILEGES: { + + struct dcerpc_pipe *lp; + struct policy_handle *lsa_handle; + + status = torture_rpc_connection(tctx, &lp, &ndr_table_lsarpc); + torture_assert_ntstatus_ok(tctx, status, "Failed to open LSA pipe"); + + if (!test_lsa_OpenPolicy2(lp, tctx, &lsa_handle)) { + ret = false; + } + + if (!test_DeleteUser_with_privs(p, lp, tctx, + domain_handle, lsa_handle, user_handle, + domain_sid, rid, + machine_credentials)) { + ret = false; + } + + if (!test_lsa_Close(lp, tctx, lsa_handle)) { + ret = false; + } + + if (!ret) { + torture_warning(tctx, "privileged user delete test failed\n"); + } + + break; + } case TORTURE_SAMR_OTHER: /* We just need the account to exist */ break; @@ -3959,7 +4293,7 @@ static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx, } if (!test_user_ops(p, tctx, &user_handle, domain_handle, - acct_flags, name.string, which_ops, + domain_sid, acct_flags, name.string, which_ops, machine_credentials)) { ret = false; } @@ -4119,20 +4453,22 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx } if (!test_user_ops(p, tctx, &user_handle, domain_handle, - acct_flags, name.string, which_ops, + domain_sid, acct_flags, name.string, which_ops, machine_credentials)) { ret = false; } - printf("Testing DeleteUser (createuser2 test)\n"); + if (!policy_handle_empty(&user_handle)) { + printf("Testing DeleteUser (createuser2 test)\n"); - d.in.user_handle = &user_handle; - d.out.user_handle = &user_handle; + d.in.user_handle = &user_handle; + d.out.user_handle = &user_handle; - status = dcerpc_samr_DeleteUser(p, user_ctx, &d); - if (!NT_STATUS_IS_OK(status)) { - printf("DeleteUser failed - %s\n", nt_errstr(status)); - ret = false; + status = dcerpc_samr_DeleteUser(p, user_ctx, &d); + if (!NT_STATUS_IS_OK(status)) { + printf("DeleteUser failed - %s\n", nt_errstr(status)); + ret = false; + } } } talloc_free(user_ctx); @@ -5719,6 +6055,7 @@ static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx, switch (which_ops) { case TORTURE_SAMR_USER_ATTRIBUTES: + case TORTURE_SAMR_USER_PRIVILEGES: case TORTURE_SAMR_PASSWORDS: if (!torture_setting_bool(tctx, "samba3", false)) { ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops, NULL); @@ -6127,3 +6464,43 @@ struct torture_suite *torture_rpc_samr_passwords_pwdlastset(struct torture_conte return suite; } + +static bool torture_rpc_samr_users_privileges_delete_user(struct torture_context *torture, + struct dcerpc_pipe *p2, + struct cli_credentials *machine_credentials) +{ + NTSTATUS status; + struct dcerpc_pipe *p; + bool ret = true; + struct policy_handle handle; + + status = torture_rpc_connection(torture, &p, &ndr_table_samr); + if (!NT_STATUS_IS_OK(status)) { + return false; + } + + ret &= test_Connect(p, torture, &handle); + + ret &= test_EnumDomains(p, torture, &handle, + TORTURE_SAMR_USER_PRIVILEGES, + machine_credentials); + + ret &= test_samr_handle_Close(p, torture, &handle); + + return ret; +} + +struct torture_suite *torture_rpc_samr_user_privileges(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-USERS-PRIVILEGES"); + struct torture_rpc_tcase *tcase; + + tcase = torture_suite_add_machine_rpc_iface_tcase(suite, "samr", + &ndr_table_samr, + TEST_ACCOUNT_NAME_PWD); + + torture_rpc_tcase_add_test_creds(tcase, "delete_privileged_user", + torture_rpc_samr_users_privileges_delete_user); + + return suite; +} -- cgit