diff options
author | Günther Deschner <gd@samba.org> | 2010-06-04 19:03:11 +0200 |
---|---|---|
committer | Günther Deschner <gd@samba.org> | 2010-06-05 00:35:09 +0200 |
commit | e89502e0f5a79c960cbecf50f49af3aa4bba8e35 (patch) | |
tree | 1b4aa6ca465541545e6d67671f1d95668a90bb02 /source4 | |
parent | 29c0c103afed7238698cc83ff3ab017fc1510dcd (diff) | |
download | samba-e89502e0f5a79c960cbecf50f49af3aa4bba8e35.tar.gz samba-e89502e0f5a79c960cbecf50f49af3aa4bba8e35.tar.bz2 samba-e89502e0f5a79c960cbecf50f49af3aa4bba8e35.zip |
s4-smbtorture: add RPC-SPOOLSS-ACCESS.
This test creates
- a user
- a user with BUILTIN\Administrators membership
- a user with BUILTIN\Print Operators membership
- a user with SePrintOperatorPrivilege (if available)
- a user with full access in security descriptor
and checks what access rights are granted in spoolss_OpenPrinterEx.
Guenther
Diffstat (limited to 'source4')
-rw-r--r-- | source4/torture/config.mk | 2 | ||||
-rw-r--r-- | source4/torture/rpc/rpc.c | 1 | ||||
-rw-r--r-- | source4/torture/rpc/spoolss_access.c | 751 | ||||
-rw-r--r-- | source4/torture/wscript_build | 2 |
4 files changed, 754 insertions, 2 deletions
diff --git a/source4/torture/config.mk b/source4/torture/config.mk index 4d65256a3d..25e9b5377b 100644 --- a/source4/torture/config.mk +++ b/source4/torture/config.mk @@ -124,7 +124,7 @@ PRIVATE_DEPENDENCIES = \ torture_rpc_OBJ_FILES = $(addprefix $(torturesrcdir)/rpc/, \ join.o lsa.o lsa_lookup.o session_key.o echo.o dfs.o drsuapi.o \ - drsuapi_cracknames.o dssync.o dsgetinfo.o spoolss.o spoolss_notify.o spoolss_win.o \ + drsuapi_cracknames.o dssync.o dsgetinfo.o spoolss.o spoolss_notify.o spoolss_win.o spoolss_access.o \ unixinfo.o samr.o samr_accessmask.o wkssvc.o srvsvc.o svcctl.o atsvc.o \ eventlog.o epmapper.o winreg.o initshutdown.o oxidresolve.o remact.o mgmt.o \ scanner.o autoidl.o countcalls.o testjoin.o schannel.o netlogon.o remote_pac.o samlogon.o \ diff --git a/source4/torture/rpc/rpc.c b/source4/torture/rpc/rpc.c index 746698ec37..a860bdad72 100644 --- a/source4/torture/rpc/rpc.c +++ b/source4/torture/rpc/rpc.c @@ -445,6 +445,7 @@ NTSTATUS torture_rpc_init(void) torture_suite_add_suite(suite, torture_rpc_spoolss_notify(suite)); torture_suite_add_suite(suite, torture_rpc_spoolss_win(suite)); torture_suite_add_suite(suite, torture_rpc_spoolss_driver(suite)); + torture_suite_add_suite(suite, torture_rpc_spoolss_access(suite)); torture_suite_add_simple_test(suite, "SAMR", torture_rpc_samr); torture_suite_add_simple_test(suite, "SAMR-USERS", torture_rpc_samr_users); torture_suite_add_simple_test(suite, "SAMR-PASSWORDS", torture_rpc_samr_passwords); diff --git a/source4/torture/rpc/spoolss_access.c b/source4/torture/rpc/spoolss_access.c new file mode 100644 index 0000000000..f86c2e3dcb --- /dev/null +++ b/source4/torture/rpc/spoolss_access.c @@ -0,0 +1,751 @@ +/* + Unix SMB/CIFS implementation. + test suite for spoolss rpc operations + + Copyright (C) Guenther Deschner 2010 + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "torture/torture.h" +#include "librpc/gen_ndr/ndr_misc.h" +#include "librpc/gen_ndr/ndr_spoolss.h" +#include "librpc/gen_ndr/ndr_spoolss_c.h" +#include "librpc/gen_ndr/ndr_samr_c.h" +#include "librpc/gen_ndr/ndr_lsa_c.h" +#include "librpc/gen_ndr/ndr_security.h" +#include "libcli/security/security.h" +#include "torture/rpc/torture_rpc.h" +#include "param/param.h" +#include "lib/cmdline/popt_common.h" + +#define TORTURE_USER "torture_user" +#define TORTURE_USER_ADMINGROUP "torture_user_544" +#define TORTURE_USER_PRINTOPGROUP "torture_user_550" +#define TORTURE_USER_PRINTOPPRIV "torture_user_priv" +#define TORTURE_USER_SD "torture_user_sd" + +struct torture_user { + const char *username; + void *testuser; + uint32_t *builtin_memberships; + uint32_t num_builtin_memberships; + const char **privs; + uint32_t num_privs; + bool privs_present; + bool sd; +}; + +struct torture_access_context { + struct dcerpc_pipe *spoolss_pipe; + const char *printername; + struct security_descriptor *sd_orig; + struct torture_user user; +}; + +static bool test_openprinter_handle(struct torture_context *tctx, + struct dcerpc_pipe *p, + const char *printername, + const char *username, + uint32_t access_mask, + struct policy_handle *handle) +{ + struct spoolss_OpenPrinterEx r; + struct spoolss_UserLevel1 level1; + struct dcerpc_binding_handle *b = p->binding_handle; + + level1.size = 28; + level1.client = talloc_asprintf(tctx, "\\\\%s", "smbtorture"); + level1.user = username; + level1.build = 1381; + level1.major = 3; + level1.minor = 0; + level1.processor= 0; + + r.in.printername = printername; + r.in.datatype = NULL; + r.in.devmode_ctr.devmode= NULL; + r.in.access_mask = access_mask; + r.in.level = 1; + r.in.userlevel.level1 = &level1; + r.out.handle = handle; + + torture_comment(tctx, "Testing OpenPrinterEx(%s) with access_mask 0x%08x\n", + r.in.printername, r.in.access_mask); + + torture_assert_ntstatus_ok(tctx, + dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), + "OpenPrinterEx failed"); + torture_assert_werr_ok(tctx, r.out.result, + talloc_asprintf(tctx, "OpenPrinterEx(%s) as '%s' with access_mask: 0x%08x failed", + r.in.printername, username, r.in.access_mask)); + + return true; +} + +static bool test_openprinter_access(struct torture_context *tctx, + struct dcerpc_pipe *p, + const char *printername, + const char *username, + uint32_t access_mask) +{ + struct policy_handle handle; + struct dcerpc_binding_handle *b = p->binding_handle; + + if (test_openprinter_handle(tctx, p, printername, username, access_mask, &handle)) { + test_ClosePrinter(tctx, b, &handle); + return true; + } + + return false; +} + +static bool spoolss_access_setup_membership(struct torture_context *tctx, + struct dcerpc_pipe *p, + uint32_t num_members, + uint32_t *members, + struct dom_sid *user_sid) +{ + struct dcerpc_binding_handle *b = p->binding_handle; + struct policy_handle connect_handle, domain_handle; + int i; + + { + struct samr_Connect2 r; + r.in.system_name = ""; + r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + r.out.connect_handle = &connect_handle; + + torture_assert_ntstatus_ok(tctx, + dcerpc_samr_Connect2_r(b, tctx, &r), + "samr_Connect2 failed"); + torture_assert_ntstatus_ok(tctx, r.out.result, + "samr_Connect2 failed"); + } + + { + struct samr_OpenDomain r; + r.in.connect_handle = &connect_handle; + r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32"); + r.out.domain_handle = &domain_handle; + + torture_assert_ntstatus_ok(tctx, + dcerpc_samr_OpenDomain_r(b, tctx, &r), + "samr_OpenDomain failed"); + torture_assert_ntstatus_ok(tctx, r.out.result, + "samr_OpenDomain failed"); + } + + for (i=0; i < num_members; i++) { + + struct policy_handle alias_handle; + + { + struct samr_OpenAlias r; + r.in.domain_handle = &domain_handle; + r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + r.in.rid = members[i]; + r.out.alias_handle = &alias_handle; + + torture_assert_ntstatus_ok(tctx, + dcerpc_samr_OpenAlias_r(b, tctx, &r), + "samr_OpenAlias failed"); + torture_assert_ntstatus_ok(tctx, r.out.result, + "samr_OpenAlias failed"); + } + + { + struct samr_AddAliasMember r; + r.in.alias_handle = &alias_handle; + r.in.sid = user_sid; + + torture_assert_ntstatus_ok(tctx, + dcerpc_samr_AddAliasMember_r(b, tctx, &r), + "samr_AddAliasMember failed"); + torture_assert_ntstatus_ok(tctx, r.out.result, + "samr_AddAliasMember failed"); + } + + test_samr_handle_Close(b, tctx, &alias_handle); + } + + test_samr_handle_Close(b, tctx, &domain_handle); + test_samr_handle_Close(b, tctx, &connect_handle); + + return true; +} + +static void init_lsa_StringLarge(struct lsa_StringLarge *name, const char *s) +{ + name->string = s; +} +static void init_lsa_String(struct lsa_String *name, const char *s) +{ + name->string = s; +} + +static bool spoolss_access_setup_privs(struct torture_context *tctx, + struct dcerpc_pipe *p, + uint32_t num_privs, + const char **privs, + struct dom_sid *user_sid, + bool *privs_present) +{ + struct dcerpc_binding_handle *b = p->binding_handle; + struct policy_handle *handle; + int i; + + torture_assert(tctx, + test_lsa_OpenPolicy2(b, tctx, &handle), + "failed to open policy"); + + for (i=0; i < num_privs; i++) { + struct lsa_LookupPrivValue r; + struct lsa_LUID luid; + struct lsa_String name; + + init_lsa_String(&name, privs[i]); + + r.in.handle = handle; + r.in.name = &name; + r.out.luid = &luid; + + torture_assert_ntstatus_ok(tctx, + dcerpc_lsa_LookupPrivValue_r(b, tctx, &r), + "lsa_LookupPrivValue failed"); + if (!NT_STATUS_IS_OK(r.out.result)) { + torture_comment(tctx, "lsa_LookupPrivValue failed for '%s' with %s\n", + privs[i], nt_errstr(r.out.result)); + *privs_present = false; + return true; + } + } + + *privs_present = true; + + { + struct lsa_AddAccountRights r; + struct lsa_RightSet rights; + + rights.count = num_privs; + rights.names = talloc_zero_array(tctx, struct lsa_StringLarge, rights.count); + + for (i=0; i < rights.count; i++) { + init_lsa_StringLarge(&rights.names[i], privs[i]); + } + + r.in.handle = handle; + r.in.sid = user_sid; + r.in.rights = &rights; + + torture_assert_ntstatus_ok(tctx, + dcerpc_lsa_AddAccountRights_r(b, tctx, &r), + "lsa_AddAccountRights failed"); + torture_assert_ntstatus_ok(tctx, r.out.result, + "lsa_AddAccountRights failed"); + } + + test_lsa_Close(b, tctx, handle); + + return true; +} + +static bool test_SetPrinter(struct torture_context *tctx, + struct dcerpc_binding_handle *b, + struct policy_handle *handle, + struct spoolss_SetPrinterInfoCtr *info_ctr, + struct spoolss_DevmodeContainer *devmode_ctr, + struct sec_desc_buf *secdesc_ctr, + enum spoolss_PrinterControl command) +{ + struct spoolss_SetPrinter r; + + r.in.handle = handle; + r.in.info_ctr = info_ctr; + r.in.devmode_ctr = devmode_ctr; + r.in.secdesc_ctr = secdesc_ctr; + r.in.command = command; + + torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level); + + torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r), + "failed to call SetPrinter"); + torture_assert_werr_ok(tctx, r.out.result, + "failed to call SetPrinter"); + + return true; +} + +static bool spoolss_access_setup_sd(struct torture_context *tctx, + struct dcerpc_pipe *p, + const char *printername, + struct dom_sid *user_sid, + struct security_descriptor **sd_orig) +{ + struct dcerpc_binding_handle *b = p->binding_handle; + struct policy_handle handle; + union spoolss_PrinterInfo info; + struct spoolss_SetPrinterInfoCtr info_ctr; + struct spoolss_SetPrinterInfo3 info3; + struct spoolss_DevmodeContainer devmode_ctr; + struct sec_desc_buf secdesc_ctr; + struct security_ace *ace; + struct security_descriptor *sd; + + torture_assert(tctx, + test_openprinter_handle(tctx, p, printername, "", SEC_FLAG_MAXIMUM_ALLOWED, &handle), + "failed to open printer"); + + torture_assert(tctx, + test_GetPrinter_level(tctx, b, &handle, 3, &info), + "failed to get sd"); + + sd = security_descriptor_copy(tctx, info.info3.secdesc); + *sd_orig = security_descriptor_copy(tctx, info.info3.secdesc); + + ace = talloc_zero(tctx, struct security_ace); + + ace->type = SEC_ACE_TYPE_ACCESS_ALLOWED; + ace->flags = 0; + ace->access_mask = PRINTER_ALL_ACCESS; + ace->trustee = *user_sid; + + torture_assert_ntstatus_ok(tctx, + security_descriptor_dacl_add(sd, ace), + "failed to add new ace"); + + ace = talloc_zero(tctx, struct security_ace); + + ace->type = SEC_ACE_TYPE_ACCESS_ALLOWED; + ace->flags = SEC_ACE_FLAG_OBJECT_INHERIT | + SEC_ACE_FLAG_CONTAINER_INHERIT | + SEC_ACE_FLAG_INHERIT_ONLY; + ace->access_mask = SEC_GENERIC_ALL; + ace->trustee = *user_sid; + + torture_assert_ntstatus_ok(tctx, + security_descriptor_dacl_add(sd, ace), + "failed to add new ace"); + + ZERO_STRUCT(info3); + ZERO_STRUCT(info_ctr); + ZERO_STRUCT(devmode_ctr); + ZERO_STRUCT(secdesc_ctr); + + info_ctr.level = 3; + info_ctr.info.info3 = &info3; + secdesc_ctr.sd = sd; + + torture_assert(tctx, + test_SetPrinter(tctx, b, &handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), + "failed to set sd"); + + return true; +} + +static bool test_EnumPrinters_findone(struct torture_context *tctx, + struct dcerpc_binding_handle *b, + const char **printername) +{ + struct spoolss_EnumPrinters r; + uint32_t count; + union spoolss_PrinterInfo *info; + uint32_t needed; + int i; + + *printername = NULL; + + r.in.flags = PRINTER_ENUM_LOCAL; + r.in.server = NULL; + r.in.level = 1; + r.in.buffer = NULL; + r.in.offered = 0; + r.out.count = &count; + r.out.info = &info; + r.out.needed = &needed; + + torture_assert_ntstatus_ok(tctx, + dcerpc_spoolss_EnumPrinters_r(b, tctx, &r), + "failed to enum printers"); + + if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) { + DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); + r.in.buffer = &blob; + r.in.offered = needed; + + torture_assert_ntstatus_ok(tctx, + dcerpc_spoolss_EnumPrinters_r(b, tctx, &r), + "failed to enum printers"); + } + + torture_assert_werr_ok(tctx, r.out.result, + "failed to enum printers"); + + for (i=0; i < count; i++) { + + *printername = talloc_strdup(tctx, info[i].info1.name); + + break; + } + + return true; +} + +static bool torture_rpc_spoolss_access_setup_common(struct torture_context *tctx, struct torture_access_context *t) +{ + void *testuser; + const char *testuser_passwd; + struct cli_credentials *test_credentials; + struct dom_sid *test_sid; + struct dcerpc_pipe *p; + const char *printername; + const char *binding = torture_setting_string(tctx, "binding", NULL); + + testuser = torture_create_testuser(tctx, t->user.username, + torture_setting_string(tctx, "workgroup", NULL), + ACB_NORMAL, &testuser_passwd); + if (!testuser) { + torture_fail(tctx, "Failed to create test user"); + } + + test_credentials = cli_credentials_init(tctx); + cli_credentials_set_workstation(test_credentials, "localhost", CRED_SPECIFIED); + cli_credentials_set_domain(test_credentials, lp_workgroup(tctx->lp_ctx), + CRED_SPECIFIED); + cli_credentials_set_username(test_credentials, t->user.username, CRED_SPECIFIED); + cli_credentials_set_password(test_credentials, testuser_passwd, CRED_SPECIFIED); + test_sid = torture_join_user_sid(testuser); + + if (t->user.num_builtin_memberships) { + struct dcerpc_pipe *samr_pipe = torture_join_samr_pipe(testuser); + + torture_assert(tctx, + spoolss_access_setup_membership(tctx, samr_pipe, + t->user.num_builtin_memberships, + t->user.builtin_memberships, + test_sid), + "failed to setup membership"); + } + + if (t->user.num_privs) { + struct dcerpc_pipe *lsa_pipe; + + torture_assert_ntstatus_ok(tctx, + torture_rpc_connection(tctx, &lsa_pipe, &ndr_table_lsarpc), + "Error connecting to server"); + + torture_assert(tctx, + spoolss_access_setup_privs(tctx, lsa_pipe, + t->user.num_privs, + t->user.privs, + test_sid, + &t->user.privs_present), + "failed to setup privs"); + talloc_free(lsa_pipe); + } + + struct dcerpc_pipe *spoolss_pipe; + + torture_assert_ntstatus_ok(tctx, + torture_rpc_connection(tctx, &spoolss_pipe, &ndr_table_spoolss), + "Error connecting to server"); + + torture_assert(tctx, + test_EnumPrinters_findone(tctx, spoolss_pipe->binding_handle, &printername), + "failed to enumerate printers"); + + if (t->user.sd) { + torture_assert(tctx, + spoolss_access_setup_sd(tctx, spoolss_pipe, + printername, + test_sid, + &t->sd_orig), + "failed to setup sd"); + } + + talloc_free(spoolss_pipe); + + torture_assert_ntstatus_ok(tctx, + dcerpc_pipe_connect(tctx, &p, binding, &ndr_table_spoolss, + test_credentials, tctx->ev, tctx->lp_ctx), + "Error connecting to server"); + + t->spoolss_pipe = p; + t->printername = printername; + t->user.testuser = testuser; + + return true; +} + +static bool torture_rpc_spoolss_access_setup(struct torture_context *tctx, void **data) +{ + struct torture_access_context *t; + + *data = t = talloc_zero(tctx, struct torture_access_context); + + t->user.username = talloc_strdup(t, TORTURE_USER); + + return torture_rpc_spoolss_access_setup_common(tctx, t); +} + +static bool torture_rpc_spoolss_access_admin_setup(struct torture_context *tctx, void **data) +{ + struct torture_access_context *t; + + *data = t = talloc_zero(tctx, struct torture_access_context); + + t->user.num_builtin_memberships = 1; + t->user.builtin_memberships = talloc_zero_array(t, uint32_t, t->user.num_builtin_memberships); + t->user.builtin_memberships[0] = BUILTIN_RID_ADMINISTRATORS; + t->user.username = talloc_strdup(t, TORTURE_USER_ADMINGROUP); + + return torture_rpc_spoolss_access_setup_common(tctx, t); +} + +static bool torture_rpc_spoolss_access_printop_setup(struct torture_context *tctx, void **data) +{ + struct torture_access_context *t; + + *data = t = talloc_zero(tctx, struct torture_access_context); + + t->user.num_builtin_memberships = 1; + t->user.builtin_memberships = talloc_zero_array(t, uint32_t, t->user.num_builtin_memberships); + t->user.builtin_memberships[0] = BUILTIN_RID_PRINT_OPERATORS; + t->user.username = talloc_strdup(t, TORTURE_USER_PRINTOPGROUP); + + return torture_rpc_spoolss_access_setup_common(tctx, t); +} + +static bool torture_rpc_spoolss_access_priv_setup(struct torture_context *tctx, void **data) +{ + struct torture_access_context *t; + + *data = t = talloc_zero(tctx, struct torture_access_context); + + t->user.username = talloc_strdup(t, TORTURE_USER_PRINTOPPRIV); + t->user.num_privs = 1; + t->user.privs = talloc_zero_array(t, const char *, t->user.num_privs); + t->user.privs[0] = talloc_strdup(t, "SePrintOperatorPrivilege"); + + return torture_rpc_spoolss_access_setup_common(tctx, t); +} + +static bool torture_rpc_spoolss_access_sd_setup(struct torture_context *tctx, void **data) +{ + struct torture_access_context *t; + + *data = t = talloc_zero(tctx, struct torture_access_context); + + t->user.username = talloc_strdup(t, TORTURE_USER_SD); + t->user.sd = true; + + return torture_rpc_spoolss_access_setup_common(tctx, t); +} + +static bool torture_rpc_spoolss_access_teardown_common(struct torture_context *tctx, struct torture_access_context *t) +{ + if (t->user.testuser) { + torture_leave_domain(tctx, t->user.testuser); + } + + /* remove membership ? */ + if (t->user.num_builtin_memberships) { + } + + /* remove privs ? */ + if (t->user.num_privs) { + } + + /* restore sd */ + if (t->user.sd) { + struct policy_handle handle; + struct spoolss_SetPrinterInfoCtr info_ctr; + struct spoolss_SetPrinterInfo3 info3; + struct spoolss_DevmodeContainer devmode_ctr; + struct sec_desc_buf secdesc_ctr; + struct dcerpc_pipe *spoolss_pipe; + struct dcerpc_binding_handle *b; + + torture_assert_ntstatus_ok(tctx, + torture_rpc_connection(tctx, &spoolss_pipe, &ndr_table_spoolss), + "Error connecting to server"); + + b = spoolss_pipe->binding_handle; + + ZERO_STRUCT(info_ctr); + ZERO_STRUCT(info3); + ZERO_STRUCT(devmode_ctr); + ZERO_STRUCT(secdesc_ctr); + + info_ctr.level = 3; + info_ctr.info.info3 = &info3; + secdesc_ctr.sd = t->sd_orig; + + torture_assert(tctx, + test_openprinter_handle(tctx, spoolss_pipe, t->printername, "", SEC_FLAG_MAXIMUM_ALLOWED, &handle), + "failed to open printer"); + + torture_assert(tctx, + test_SetPrinter(tctx, b, &handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), + "failed to set sd"); + + talloc_free(spoolss_pipe); + } + + return true; +} + +static bool torture_rpc_spoolss_access_teardown(struct torture_context *tctx, void *data) +{ + struct torture_access_context *t = talloc_get_type(data, struct torture_access_context); + bool ret; + + ret = torture_rpc_spoolss_access_teardown_common(tctx, t); + talloc_free(t); + + return ret; +} + +static bool test_openprinter(struct torture_context *tctx, + void *private_data) +{ + struct torture_access_context *t = + (struct torture_access_context *)talloc_get_type_abort(private_data, struct torture_access_context); + struct dcerpc_pipe *p = t->spoolss_pipe; + bool ret = true; + const char *printername; + const char *username = t->user.username; + + printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); + + ret &= test_openprinter_access(tctx, p, printername, username, 0); + ret &= test_openprinter_access(tctx, p, printername, username, SEC_FLAG_MAXIMUM_ALLOWED); + ret &= test_openprinter_access(tctx, p, printername, username, SERVER_ACCESS_ENUMERATE); + ret &= test_openprinter_access(tctx, p, printername, username, SERVER_READ); + + if (t->printername == NULL) { + return ret; + } + + printername = t->printername; + + ret &= test_openprinter_access(tctx, p, printername, username, 0); + ret &= test_openprinter_access(tctx, p, printername, username, SEC_FLAG_MAXIMUM_ALLOWED); + ret &= test_openprinter_access(tctx, p, printername, username, PRINTER_ACCESS_USE); + ret &= test_openprinter_access(tctx, p, printername, username, PRINTER_READ); + + return ret; +} + +static bool test_openprinter_admin(struct torture_context *tctx, + void *private_data) +{ + struct torture_access_context *t = + (struct torture_access_context *)talloc_get_type_abort(private_data, struct torture_access_context); + struct dcerpc_pipe *p = t->spoolss_pipe; + bool ret = true; + const char *printername; + const char *username = t->user.username; + + if (t->user.num_privs && !t->user.privs_present) { + torture_skip(tctx, "skipping test as not all required privileges are present on the server\n"); + } + + if (t->user.sd) { + goto try_printer; + } + + printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); + + ret &= test_openprinter_access(tctx, p, printername, username, 0); + ret &= test_openprinter_access(tctx, p, printername, username, SEC_FLAG_MAXIMUM_ALLOWED); + ret &= test_openprinter_access(tctx, p, printername, username, SERVER_ACCESS_ENUMERATE); + ret &= test_openprinter_access(tctx, p, printername, username, SERVER_ACCESS_ADMINISTER); + ret &= test_openprinter_access(tctx, p, printername, username, SERVER_READ); + ret &= test_openprinter_access(tctx, p, printername, username, SERVER_WRITE); + ret &= test_openprinter_access(tctx, p, printername, username, SERVER_EXECUTE); + ret &= test_openprinter_access(tctx, p, printername, username, SERVER_ALL_ACCESS); + + try_printer: + if (t->printername == NULL) { + return ret; + } + + printername = t->printername; + + ret &= test_openprinter_access(tctx, p, printername, username, 0); + ret &= test_openprinter_access(tctx, p, printername, username, SEC_FLAG_MAXIMUM_ALLOWED); + ret &= test_openprinter_access(tctx, p, printername, username, PRINTER_ACCESS_USE); + ret &= test_openprinter_access(tctx, p, printername, username, PRINTER_ACCESS_ADMINISTER); + ret &= test_openprinter_access(tctx, p, printername, username, PRINTER_READ); + ret &= test_openprinter_access(tctx, p, printername, username, PRINTER_WRITE); + ret &= test_openprinter_access(tctx, p, printername, username, PRINTER_EXECUTE); + ret &= test_openprinter_access(tctx, p, printername, username, PRINTER_ALL_ACCESS); + + return ret; +} + +struct torture_suite *torture_rpc_spoolss_access(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-ACCESS"); + struct torture_tcase *tcase; + + tcase = torture_suite_add_tcase(suite, "normaluser"); + + torture_tcase_set_fixture(tcase, + torture_rpc_spoolss_access_setup, + torture_rpc_spoolss_access_teardown); + + torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter); + + tcase = torture_suite_add_tcase(suite, "adminuser"); + + torture_tcase_set_fixture(tcase, + torture_rpc_spoolss_access_admin_setup, + torture_rpc_spoolss_access_teardown); + + torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter); + torture_tcase_add_simple_test(tcase, "openprinter_admin", test_openprinter_admin); + + tcase = torture_suite_add_tcase(suite, "printopuser"); + + torture_tcase_set_fixture(tcase, + torture_rpc_spoolss_access_printop_setup, + torture_rpc_spoolss_access_teardown); + + torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter); + torture_tcase_add_simple_test(tcase, "openprinter_admin", test_openprinter_admin); + + tcase = torture_suite_add_tcase(suite, "printopuserpriv"); + + torture_tcase_set_fixture(tcase, + torture_rpc_spoolss_access_priv_setup, + torture_rpc_spoolss_access_teardown); + + torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter); + torture_tcase_add_simple_test(tcase, "openprinter_admin", test_openprinter_admin); + + tcase = torture_suite_add_tcase(suite, "normaluser_sd"); + + torture_tcase_set_fixture(tcase, + torture_rpc_spoolss_access_sd_setup, + torture_rpc_spoolss_access_teardown); + + torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter); + torture_tcase_add_simple_test(tcase, "openprinter_admin", test_openprinter_admin); + + return suite; +} diff --git a/source4/torture/wscript_build b/source4/torture/wscript_build index a9183623ff..4474e2b5f6 100644 --- a/source4/torture/wscript_build +++ b/source4/torture/wscript_build @@ -40,7 +40,7 @@ bld.SAMBA_SUBSYSTEM('TORTURE_NDR', bld.SAMBA_MODULE('torture_rpc', - source='rpc/join.c rpc/lsa.c rpc/lsa_lookup.c rpc/session_key.c rpc/echo.c rpc/dfs.c rpc/drsuapi.c rpc/drsuapi_cracknames.c rpc/dssync.c rpc/dsgetinfo.c rpc/spoolss.c rpc/spoolss_notify.c rpc/spoolss_win.c rpc/unixinfo.c rpc/samr.c rpc/samr_accessmask.c rpc/wkssvc.c rpc/srvsvc.c rpc/svcctl.c rpc/atsvc.c rpc/eventlog.c rpc/epmapper.c rpc/winreg.c rpc/initshutdown.c rpc/oxidresolve.c rpc/remact.c rpc/mgmt.c rpc/scanner.c rpc/autoidl.c rpc/countcalls.c rpc/testjoin.c rpc/schannel.c rpc/netlogon.c rpc/remote_pac.c rpc/samlogon.c rpc/samsync.c rpc/bind.c rpc/dssetup.c rpc/alter_context.c rpc/bench.c rpc/samba3rpc.c rpc/rpc.c rpc/async_bind.c rpc/handles.c rpc/frsapi.c rpc/object_uuid.c rpc/ntsvcs.c rpc/browser.c', + source='rpc/join.c rpc/lsa.c rpc/lsa_lookup.c rpc/session_key.c rpc/echo.c rpc/dfs.c rpc/drsuapi.c rpc/drsuapi_cracknames.c rpc/dssync.c rpc/dsgetinfo.c rpc/spoolss.c rpc/spoolss_notify.c rpc/spoolss_win.c rpc/spoolss_access.c rpc/unixinfo.c rpc/samr.c rpc/samr_accessmask.c rpc/wkssvc.c rpc/srvsvc.c rpc/svcctl.c rpc/atsvc.c rpc/eventlog.c rpc/epmapper.c rpc/winreg.c rpc/initshutdown.c rpc/oxidresolve.c rpc/remact.c rpc/mgmt.c rpc/scanner.c rpc/autoidl.c rpc/countcalls.c rpc/testjoin.c rpc/schannel.c rpc/netlogon.c rpc/remote_pac.c rpc/samlogon.c rpc/samsync.c rpc/bind.c rpc/dssetup.c rpc/alter_context.c rpc/bench.c rpc/samba3rpc.c rpc/rpc.c rpc/async_bind.c rpc/handles.c rpc/frsapi.c rpc/object_uuid.c rpc/ntsvcs.c rpc/browser.c', autoproto='rpc/proto.h', subsystem='smbtorture', init_function='torture_rpc_init', |