The branch, master has been updated via e89502e... s4-smbtorture: add RPC-SPOOLSS-ACCESS. via 29c0c10... s4-smbtorture: share test_ClosePrinter between RPC-SPOOLSS and RPC-SPOOLSS-WIN. via b3ebebd... s3-rpcclient: allow to add access_mask in cmd_spoolss_open_printer_ex(). via 8b3059d... s4-smbtorture: check error codes in RAP-SAM testsuite. from fb79a8d... Oops. Forgot to re-initialize the aio_ex pointer from sival_ptr.
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit e89502e0f5a79c960cbecf50f49af3aa4bba8e35 Author: Günther Deschner <g...@samba.org> Date: Fri Jun 4 19:03:11 2010 +0200 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 commit 29c0c103afed7238698cc83ff3ab017fc1510dcd Author: Günther Deschner <g...@samba.org> Date: Fri Jun 4 19:02:17 2010 +0200 s4-smbtorture: share test_ClosePrinter between RPC-SPOOLSS and RPC-SPOOLSS-WIN. Guenther commit b3ebebd3b18e4d9ebfc50012e02f7011f8d067be Author: Günther Deschner <g...@samba.org> Date: Fri Jun 4 16:55:07 2010 +0200 s3-rpcclient: allow to add access_mask in cmd_spoolss_open_printer_ex(). Guenther commit 8b3059de977eeeae69ebff7d33119bd6b565b637 Author: Günther Deschner <g...@samba.org> Date: Fri Jun 4 19:05:24 2010 +0200 s4-smbtorture: check error codes in RAP-SAM testsuite. Guenther ----------------------------------------------------------------------- Summary of changes: source3/rpcclient/cmd_spoolss.c | 12 +- source4/torture/config.mk | 2 +- source4/torture/rap/sam.c | 2 + source4/torture/rpc/rpc.c | 1 + source4/torture/rpc/spoolss.c | 10 +- source4/torture/rpc/spoolss_access.c | 751 ++++++++++++++++++++++++++++++++++ source4/torture/rpc/spoolss_win.c | 19 - source4/torture/wscript_build | 2 +- 8 files changed, 766 insertions(+), 33 deletions(-) create mode 100644 source4/torture/rpc/spoolss_access.c Changeset truncated at 500 lines: diff --git a/source3/rpcclient/cmd_spoolss.c b/source3/rpcclient/cmd_spoolss.c index d5a7ce7..39c581c 100644 --- a/source3/rpcclient/cmd_spoolss.c +++ b/source3/rpcclient/cmd_spoolss.c @@ -105,20 +105,22 @@ static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli, { WERROR werror; struct policy_handle hnd; + uint32_t access_mask = PRINTER_ALL_ACCESS; - if (argc != 2) { - printf("Usage: %s <printername>\n", argv[0]); + if (argc < 2) { + printf("Usage: %s <printername> [access_mask]\n", argv[0]); return WERR_OK; } - if (!cli) - return WERR_GENERAL_FAILURE; + if (argc >= 3) { + sscanf(argv[2], "%x", &access_mask); + } /* Open the printer handle */ werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx, argv[1], - PRINTER_ALL_ACCESS, + access_mask, &hnd); if (W_ERROR_IS_OK(werror)) { printf("Printer %s opened successfully\n", argv[1]); diff --git a/source4/torture/config.mk b/source4/torture/config.mk index 4d65256..25e9b53 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/rap/sam.c b/source4/torture/rap/sam.c index 290ba08..144abaa 100644 --- a/source4/torture/rap/sam.c +++ b/source4/torture/rap/sam.c @@ -206,6 +206,8 @@ static bool test_usergetinfo_byname(struct torture_context *tctx, torture_assert_ntstatus_ok(tctx, smbcli_rap_netusergetinfo(cli->tree, tctx, &r), "smbcli_rap_netusergetinfo failed"); + torture_assert_werr_ok(tctx, W_ERROR(r.out.status), + "smbcli_rap_netusergetinfo failed"); } return true; diff --git a/source4/torture/rpc/rpc.c b/source4/torture/rpc/rpc.c index 746698e..a860bda 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.c b/source4/torture/rpc/spoolss.c index 7154b83..e61adfe 100644 --- a/source4/torture/rpc/spoolss.c +++ b/source4/torture/rpc/spoolss.c @@ -2185,10 +2185,6 @@ static bool call_OpenPrinterEx(struct torture_context *tctx, struct spoolss_DeviceMode *devmode, struct policy_handle *handle); -static bool test_ClosePrinter(struct torture_context *tctx, - struct dcerpc_binding_handle *b, - struct policy_handle *handle); - static bool test_PrinterInfo_DevModes(struct torture_context *tctx, struct dcerpc_pipe *p, struct policy_handle *handle, @@ -2373,9 +2369,9 @@ static bool test_PrinterInfo_DevMode(struct torture_context *tctx, return ret; } -static bool test_ClosePrinter(struct torture_context *tctx, - struct dcerpc_binding_handle *b, - struct policy_handle *handle) +bool test_ClosePrinter(struct torture_context *tctx, + struct dcerpc_binding_handle *b, + struct policy_handle *handle) { NTSTATUS status; struct spoolss_ClosePrinter r; diff --git a/source4/torture/rpc/spoolss_access.c b/source4/torture/rpc/spoolss_access.c new file mode 100644 index 0000000..f86c2e3 --- /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"); + -- Samba Shared Repository