summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/torture/rpc/spoolss.c241
1 files changed, 241 insertions, 0 deletions
diff --git a/source4/torture/rpc/spoolss.c b/source4/torture/rpc/spoolss.c
index d38f11ba94..e233a2752d 100644
--- a/source4/torture/rpc/spoolss.c
+++ b/source4/torture/rpc/spoolss.c
@@ -26,6 +26,8 @@
#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_security.h"
+#include "libcli/security/security.h"
#include "torture/rpc/rpc.h"
#include "param/param.h"
@@ -1318,6 +1320,14 @@ static bool test_PrinterInfo(struct torture_context *tctx,
break; \
}
+#define SD_EQUAL(sd1, sd2, field) \
+ if (!security_descriptor_equal(sd1, sd2)) { \
+ torture_comment(tctx, "Failed to set %s (%s)\n", \
+ #field, __location__); \
+ ret = false; \
+ break; \
+ }
+
#define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
q.in.level = lvl1; \
@@ -1517,6 +1527,229 @@ static bool test_PrinterInfo(struct torture_context *tctx,
return ret;
}
+#define torture_assert_sid_equal(torture_ctx,got,expected,cmt)\
+ do { struct dom_sid *__got = (got), *__expected = (expected); \
+ if (!dom_sid_equal(__got, __expected)) { \
+ torture_result(torture_ctx, TORTURE_FAIL, \
+ __location__": "#got" was %s, expected %s: %s", \
+ dom_sid_string(torture_ctx, __got), dom_sid_string(torture_ctx, __expected), cmt); \
+ return false; \
+ } \
+ } while(0)
+
+static bool test_security_descriptor_equal(struct torture_context *tctx,
+ const struct security_descriptor *sd1,
+ const struct security_descriptor *sd2)
+{
+ if (sd1 == sd2) {
+ return true;
+ }
+
+ if (!sd1 || !sd2) {
+ torture_comment(tctx, "%s\n", __location__);
+ return false;
+ }
+
+ torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
+ torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
+
+ torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
+ torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
+
+ if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
+ torture_comment(tctx, "%s: sacl mismatch\n", __location__);
+ NDR_PRINT_DEBUG(security_acl, sd1->sacl);
+ NDR_PRINT_DEBUG(security_acl, sd2->sacl);
+ return false;
+ }
+ if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
+ torture_comment(tctx, "%s: dacl mismatch\n", __location__);
+ NDR_PRINT_DEBUG(security_acl, sd1->dacl);
+ NDR_PRINT_DEBUG(security_acl, sd2->dacl);
+ return false;
+ }
+
+ return true;
+}
+
+static bool test_sd_set_level(struct torture_context *tctx,
+ struct dcerpc_pipe *p,
+ struct policy_handle *handle,
+ uint32_t level,
+ struct security_descriptor *sd)
+{
+ struct spoolss_SetPrinter r;
+ struct spoolss_SetPrinterInfoCtr info_ctr;
+ struct spoolss_DevmodeContainer devmode_ctr;
+ struct sec_desc_buf secdesc_ctr;
+
+ ZERO_STRUCT(devmode_ctr);
+ ZERO_STRUCT(secdesc_ctr);
+
+ switch (level) {
+ case 2: {
+ union spoolss_PrinterInfo info;
+ struct spoolss_SetPrinterInfo2 info2;
+ torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
+
+ info2.servername = info.info2.servername;
+ info2.printername = info.info2.printername;
+ info2.sharename = info.info2.sharename;
+ info2.portname = info.info2.portname;
+ info2.drivername = info.info2.drivername;
+ info2.comment = info.info2.comment;
+ info2.location = info.info2.location;
+ info2.devmode_ptr = 0;
+ info2.sepfile = info.info2.sepfile;
+ info2.printprocessor = info.info2.printprocessor;
+ info2.datatype = info.info2.datatype;
+ info2.parameters = info.info2.parameters;
+ info2.secdesc_ptr = 0;
+ info2.attributes = info.info2.attributes;
+ info2.priority = info.info2.priority;
+ info2.defaultpriority = info.info2.defaultpriority;
+ info2.starttime = info.info2.starttime;
+ info2.untiltime = info.info2.untiltime;
+ info2.status = info.info2.status;
+ info2.cjobs = info.info2.cjobs;
+ info2.averageppm = info.info2.averageppm;
+
+ info_ctr.level = 2;
+ info_ctr.info.info2 = &info2;
+
+ break;
+ }
+ case 3: {
+ struct spoolss_SetPrinterInfo3 info3;
+
+ info3.sec_desc_ptr = 0;
+
+ info_ctr.level = 3;
+ info_ctr.info.info3 = &info3;
+
+ break;
+ }
+ default:
+ return false;
+ }
+
+ secdesc_ctr.sd = sd;
+
+ 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 = 0;
+
+ torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r), "SetPrinter failed");
+ torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
+
+ return true;
+}
+
+static bool test_PrinterInfo_SDs(struct torture_context *tctx,
+ struct dcerpc_pipe *p,
+ struct policy_handle *handle)
+{
+ union spoolss_PrinterInfo info;
+ union spoolss_PrinterInfo info_2;
+ struct security_descriptor *sd1, *sd2;
+ int i;
+
+ /* level 2 */
+
+ torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
+
+ sd1 = security_descriptor_copy(tctx, info.info2.secdesc);
+
+ torture_assert(tctx, test_sd_set_level(tctx, p, handle, 2, sd1), "");
+
+ torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info_2), "");
+
+ sd2 = security_descriptor_copy(tctx, info_2.info2.secdesc);
+
+ if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
+ torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED from 1st for comparison\n");
+ sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
+ }
+
+ torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2), "");
+
+ /* level 3 */
+
+ sd1 = sd2;
+
+ for (i=0; i < 93; i++) {
+ struct security_ace a;
+ const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
+ a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
+ a.flags = 0;
+ a.size = 0; /* autogenerated */
+ a.access_mask = 0;
+ a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
+ torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
+ }
+
+ torture_assert(tctx, test_sd_set_level(tctx, p, handle, 3, sd1), "");
+
+ torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info_2), "");
+ sd2 = security_descriptor_copy(tctx, info_2.info2.secdesc);
+
+ torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2), "");
+
+ return true;
+}
+
+/*
+ * wrapper call that saves original sd, runs tests, and restores sd
+ */
+
+static bool test_PrinterInfo_SD(struct torture_context *tctx,
+ struct dcerpc_pipe *p,
+ struct policy_handle *handle)
+{
+ union spoolss_PrinterInfo info;
+ struct spoolss_SetPrinter r;
+ struct spoolss_SetPrinterInfo3 info3;
+ struct spoolss_SetPrinterInfoCtr info_ctr;
+ struct spoolss_DevmodeContainer devmode_ctr;
+ struct sec_desc_buf secdesc_ctr;
+ struct security_descriptor *sd;
+ bool ret = true;
+
+ /* save original sd */
+
+ torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
+
+ sd = security_descriptor_copy(tctx, info.info2.secdesc);
+
+ /* run tests */
+
+ ret = test_PrinterInfo_SDs(tctx, p, handle);
+
+ /* restore original sd */
+
+ ZERO_STRUCT(devmode_ctr);
+ ZERO_STRUCT(secdesc_ctr);
+
+ info3.sec_desc_ptr = 0;
+
+ info_ctr.level = 3;
+ info_ctr.info.info3 = &info3;
+
+ secdesc_ctr.sd = sd;
+
+ 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 = 0;
+
+ torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r), "SetPrinter failed");
+ torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
+
+ return ret;
+}
static bool test_ClosePrinter(struct torture_context *tctx,
struct dcerpc_pipe *p,
@@ -3027,6 +3260,10 @@ static bool test_OpenPrinterEx(struct torture_context *tctx,
return false;
}
+ if (!test_PrinterInfo_SD(tctx, p, &handle)) {
+ ret = false;
+ }
+
if (!test_GetPrinter(tctx, p, &handle)) {
ret = false;
}
@@ -3806,6 +4043,10 @@ static bool test_printer(struct torture_context *tctx,
ret = false;
}
+ if (!test_PrinterInfo_SD(tctx, p, &handle[0])) {
+ ret = false;
+ }
+
if (!test_printer_keys(tctx, p, &handle[0])) {
ret = false;
}