[SCM] Samba Shared Repository - branch master updated

Andreas Schneider asn at samba.org
Mon Jun 3 08:07:03 MDT 2013


The branch, master has been updated
       via  b475ef0 torture: support printer publish pending responses
       via  56b0246 torture: add AD printer publishing test
       via  002d1a4 Fix bug 9900: is_printer_published GUID retrieval
       via  f9b6b09 printing: explicitly clear PUBLISHED attribute
      from  1f269fc tdb: Add another overflow check to tdb_expand_adjust

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit b475ef008b1a2d2095c9b2276a55e9fbd38a5ca5
Author: David Disseldorp <ddiss at samba.org>
Date:   Wed May 29 10:43:35 2013 +0200

    torture: support printer publish pending responses
    
    Windows (tested against 2k8r2) returns WERR_IO_PENDING and
    DSPRINT_PENDING when a publish or unpublish is requested via
    setprinter(level=7). Modify the AD printer publishing test to support
    these responses.
    
    Signed-off-by: David Disseldorp <ddiss at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>
    
    Autobuild-User(master): Andreas Schneider <asn at cryptomilk.org>
    Autobuild-Date(master): Mon Jun  3 16:06:15 CEST 2013 on sn-devel-104

commit 56b02461626a0d49c47ff5e909b60d10b93afecf
Author: David Disseldorp <ddiss at samba.org>
Date:   Wed May 29 10:43:34 2013 +0200

    torture: add AD printer publishing test
    
    This test publishes and unpublishes a printer using setprinter(level=7).
    Printer info2.attributes and info7.action flags are check at each point
    to ensure MS-RPRN conformance.
    
    Signed-off-by: David Disseldorp <ddiss at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 002d1a44672c9b3247a68a86899ce6644b696a48
Author: David Disseldorp <ddiss at samba.org>
Date:   Wed May 29 10:43:33 2013 +0200

    Fix bug 9900: is_printer_published GUID retrieval
    
    Samba currently always responds to GetPrinter(level = 7) requests with
    DSPRINT_UNPUBLISH, regardless of the AD publish status tracked via the
    PRINTER_ATTRIBUTE_PUBLISHED flag. This is due to erroneous "objectGUID"
    unmarshalling in is_printer_published().
    
    This change splits "objectGUID" retrieval into a separate function, and
    adds a pull_reg_sz() call to correctly unmarshall the GUID.
    
    Signed-off-by: David Disseldorp <ddiss at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit f9b6b09e4e4e15257ce0a21caa46e26e119667d4
Author: David Disseldorp <ddiss at samba.org>
Date:   Wed May 29 10:43:32 2013 +0200

    printing: explicitly clear PUBLISHED attribute
    
    Currently nt_printer_publish(DSPRINT_UNPUBLISH) flips (via xor) the
    info2->attributes PRINTER_ATTRIBUTE_PUBLISHED flag, rather than
    explicitly clearing it.
    
    Signed-off-by: David Disseldorp <ddiss at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 selftest/knownfail                          |    1 +
 source3/include/nt_printing.h               |    6 +-
 source3/printing/nt_printing_ads.c          |  131 +++++++++++++++---------
 source3/rpc_server/spoolss/srv_spoolss_nt.c |   40 ++++++--
 source3/smbd/server_reload.c                |    2 +-
 source4/torture/rpc/spoolss.c               |  148 ++++++++++++++++++++++++++-
 6 files changed, 269 insertions(+), 59 deletions(-)


Changeset truncated at 500 lines:

diff --git a/selftest/knownfail b/selftest/knownfail
index a06bab6..313d6c9 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -215,6 +215,7 @@
 ^samba3.raw.session.*reauth2 # maybe fix this?
 ^samba3.rpc.spoolss.printer.addprinter.driver_info_winreg # knownfail or flapping?
 ^samba3.rpc.spoolss.printer.addprinterex.driver_info_winreg # knownfail or flapping?
+^samba3.rpc.spoolss.printer.*.publish_toggle\(.*\)$ # needs spoolss AD member env
 ^samba3.rpc.spoolss.printserver.*.add_processor\(.*\)$
 #
 # The following tests fail against plugin_s4_dc (aka s3fs) currently.
diff --git a/source3/include/nt_printing.h b/source3/include/nt_printing.h
index 2243a3d..2a0e883 100644
--- a/source3/include/nt_printing.h
+++ b/source3/include/nt_printing.h
@@ -132,6 +132,11 @@ bool print_access_check(const struct auth_session_info *server_info,
 			struct messaging_context *msg_ctx, int snum,
 			int access_type);
 
+WERROR nt_printer_guid_get(TALLOC_CTX *mem_ctx,
+			   const struct auth_session_info *session_info,
+			   struct messaging_context *msg_ctx,
+			   const char *printer, struct GUID *guid);
+
 WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
 			  const struct auth_session_info *server_info,
 			  struct messaging_context *msg_ctx,
@@ -143,7 +148,6 @@ bool is_printer_published(TALLOC_CTX *mem_ctx,
 			  struct messaging_context *msg_ctx,
 			  const char *servername,
 			  const char *printer,
-			  struct GUID *guid,
 			  struct spoolss_PrinterInfo2 **info2);
 
 WERROR check_published_printers(struct messaging_context *msg_ctx);
diff --git a/source3/printing/nt_printing_ads.c b/source3/printing/nt_printing_ads.c
index 3a2baf4..dcd31b7 100644
--- a/source3/printing/nt_printing_ads.c
+++ b/source3/printing/nt_printing_ads.c
@@ -87,6 +87,80 @@ done:
 	talloc_free(tmp_ctx);
 }
 
+WERROR nt_printer_guid_get(TALLOC_CTX *mem_ctx,
+			   const struct auth_session_info *session_info,
+			   struct messaging_context *msg_ctx,
+			   const char *printer, struct GUID *guid)
+{
+	TALLOC_CTX *tmp_ctx;
+	enum winreg_Type type;
+	DATA_BLOB blob;
+	uint32_t len;
+	NTSTATUS status;
+	WERROR result;
+
+	tmp_ctx = talloc_new(mem_ctx);
+	if (tmp_ctx == NULL) {
+		DEBUG(0, ("out of memory?!\n"));
+		return WERR_NOMEM;
+	}
+
+	result = winreg_get_printer_dataex_internal(tmp_ctx, session_info,
+						    msg_ctx, printer,
+						    SPOOL_DSSPOOLER_KEY,
+						    "objectGUID",
+						    &type,
+						    &blob.data,
+						    &len);
+	if (!W_ERROR_IS_OK(result)) {
+		DEBUG(0, ("Failed to get GUID for printer %s\n", printer));
+		goto out_ctx_free;
+	}
+	blob.length = (size_t)len;
+
+	/* We used to store the guid as REG_BINARY, then swapped
+	   to REG_SZ for Vista compatibility so check for both */
+
+	switch (type) {
+	case REG_SZ: {
+		bool ok;
+		const char *guid_str;
+		ok = pull_reg_sz(tmp_ctx, &blob, &guid_str);
+		if (!ok) {
+			DEBUG(0, ("Failed to unmarshall GUID for printer %s\n",
+				  printer));
+			result = WERR_REG_CORRUPT;
+			goto out_ctx_free;
+		}
+		status = GUID_from_string(guid_str, guid);
+		if (!NT_STATUS_IS_OK(status)) {
+			DEBUG(0, ("bad GUID for printer %s\n", printer));
+			result = ntstatus_to_werror(status);
+			goto out_ctx_free;
+		}
+		break;
+	}
+	case REG_BINARY:
+		if (blob.length != sizeof(struct GUID)) {
+			DEBUG(0, ("bad GUID for printer %s\n", printer));
+			result = WERR_REG_CORRUPT;
+			goto out_ctx_free;
+		}
+		memcpy(guid, blob.data, sizeof(struct GUID));
+		break;
+	default:
+		DEBUG(0,("GUID value stored as invalid type (%d)\n", type));
+		result = WERR_REG_CORRUPT;
+		goto out_ctx_free;
+		break;
+	}
+	result = WERR_OK;
+
+out_ctx_free:
+	talloc_free(tmp_ctx);
+	return result;
+}
+
 static WERROR nt_printer_info_to_mods(TALLOC_CTX *ctx,
 				      struct spoolss_PrinterInfo2 *info2,
 				      ADS_MODLIST *mods)
@@ -355,7 +429,7 @@ WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
 		pinfo2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
 		break;
 	case DSPRINT_UNPUBLISH:
-		pinfo2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
+		pinfo2->attributes &= (~PRINTER_ATTRIBUTE_PUBLISHED);
 		break;
 	default:
 		win_rc = WERR_NOT_SUPPORTED;
@@ -481,15 +555,10 @@ bool is_printer_published(TALLOC_CTX *mem_ctx,
 			  struct messaging_context *msg_ctx,
 			  const char *servername,
 			  const char *printer,
-			  struct GUID *guid,
 			  struct spoolss_PrinterInfo2 **info2)
 {
 	struct spoolss_PrinterInfo2 *pinfo2 = NULL;
-	enum winreg_Type type;
-	uint8_t *data;
-	uint32_t data_size;
 	WERROR result;
-	NTSTATUS status;
 	struct dcerpc_binding_handle *b;
 
 	result = winreg_printer_binding_handle(mem_ctx,
@@ -511,47 +580,6 @@ bool is_printer_published(TALLOC_CTX *mem_ctx,
 		return false;
 	}
 
-	if (!guid) {
-		goto done;
-	}
-
-	/* fetching printer guids really ought to be a separate function. */
-
-	result = winreg_get_printer_dataex(mem_ctx, b,
-					   printer,
-					   SPOOL_DSSPOOLER_KEY, "objectGUID",
-					   &type, &data, &data_size);
-	if (!W_ERROR_IS_OK(result)) {
-		TALLOC_FREE(pinfo2);
-		return false;
-	}
-
-	/* We used to store the guid as REG_BINARY, then swapped
-	   to REG_SZ for Vista compatibility so check for both */
-
-	switch (type) {
-	case REG_SZ:
-		status = GUID_from_string((char *)data, guid);
-		if (!NT_STATUS_IS_OK(status)) {
-			TALLOC_FREE(pinfo2);
-			return false;
-		}
-		break;
-
-	case REG_BINARY:
-		if (data_size != sizeof(struct GUID)) {
-			TALLOC_FREE(pinfo2);
-			return false;
-		}
-		memcpy(guid, data, sizeof(struct GUID));
-		break;
-	default:
-		DEBUG(0,("is_printer_published: GUID value stored as "
-			 "invaluid type (%d)\n", type));
-		break;
-	}
-
-done:
 	if (info2) {
 		*info2 = talloc_move(mem_ctx, &pinfo2);
 	}
@@ -559,6 +587,14 @@ done:
 	return true;
 }
 #else
+WERROR nt_printer_guid_get(TALLOC_CTX *mem_ctx,
+			   const struct auth_session_info *session_info,
+			   struct messaging_context *msg_ctx,
+			   const char *printer, struct GUID *guid)
+{
+	return WERR_NOT_SUPPORTED;
+}
+
 WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
 			  const struct auth_session_info *session_info,
 			  struct messaging_context *msg_ctx,
@@ -578,7 +614,6 @@ bool is_printer_published(TALLOC_CTX *mem_ctx,
 			  struct messaging_context *msg_ctx,
 			  const char *servername,
 			  const char *printer,
-			  struct GUID *guid,
 			  struct spoolss_PrinterInfo2 **info2)
 {
 	return False;
diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c
index 7482443..03c966b 100644
--- a/source3/rpc_server/spoolss/srv_spoolss_nt.c
+++ b/source3/rpc_server/spoolss/srv_spoolss_nt.c
@@ -4177,21 +4177,47 @@ static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
 				      struct spoolss_PrinterInfo7 *r,
 				      int snum)
 {
-	const struct auth_session_info *session_info = get_session_info_system();
-	struct GUID guid;
+	const struct auth_session_info *session_info;
+	char *printer;
+	WERROR werr;
+	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+	if (tmp_ctx == NULL) {
+		return WERR_NOMEM;
+	}
+
+	session_info = get_session_info_system();
+	SMB_ASSERT(session_info != NULL);
 
-	if (is_printer_published(mem_ctx, session_info, msg_ctx,
-				 servername,
-				 lp_servicename(talloc_tos(), snum), &guid, NULL)) {
+	printer = lp_servicename(tmp_ctx, snum);
+	if (printer == NULL) {
+		DEBUG(0, ("invalid printer snum %d\n", snum));
+		werr = WERR_INVALID_PARAM;
+		goto out_tmp_free;
+	}
+
+	if (is_printer_published(tmp_ctx, session_info, msg_ctx,
+				 servername, printer, NULL)) {
+		struct GUID guid;
+		werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
+					   printer, &guid);
+		if (!W_ERROR_IS_OK(werr)) {
+			goto out_tmp_free;
+		}
 		r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
 		r->action = DSPRINT_PUBLISH;
 	} else {
 		r->guid = talloc_strdup(mem_ctx, "");
 		r->action = DSPRINT_UNPUBLISH;
 	}
-	W_ERROR_HAVE_NO_MEMORY(r->guid);
+	if (r->guid == NULL) {
+		werr = WERR_NOMEM;
+		goto out_tmp_free;
+	}
 
-	return WERR_OK;
+	werr = WERR_OK;
+out_tmp_free:
+	talloc_free(tmp_ctx);
+	return werr;
 }
 
 /********************************************************************
diff --git a/source3/smbd/server_reload.c b/source3/smbd/server_reload.c
index 3a8f5bb..1d6f9c2 100644
--- a/source3/smbd/server_reload.c
+++ b/source3/smbd/server_reload.c
@@ -106,7 +106,7 @@ void delete_and_reload_printers(struct tevent_context *ev,
 						 NULL,
 						 lp_servicename(session_info,
 								snum),
-						 NULL, &pinfo2)) {
+						 &pinfo2)) {
 				nt_printer_publish(session_info,
 						   session_info,
 						   msg_ctx,
diff --git a/source4/torture/rpc/spoolss.c b/source4/torture/rpc/spoolss.c
index 5e6c4c7..4c84bc0 100644
--- a/source4/torture/rpc/spoolss.c
+++ b/source4/torture/rpc/spoolss.c
@@ -1247,8 +1247,9 @@ static bool test_SetPrinter(struct torture_context *tctx,
 
 	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");
+	torture_assert(tctx, (W_ERROR_EQUAL(r.out.result, WERR_OK)
+			   || W_ERROR_EQUAL(r.out.result, WERR_IO_PENDING)),
+		       "SetPrinter failed");
 
 	return true;
 }
@@ -8525,6 +8526,147 @@ static bool test_printer_bidi(struct torture_context *tctx,
 	return true;
 }
 
+static bool test_printer_set_publish(struct torture_context *tctx,
+				       struct dcerpc_binding_handle *b,
+				       struct policy_handle *handle)
+{
+	union spoolss_PrinterInfo info;
+	struct spoolss_SetPrinterInfo7 info7;
+	struct spoolss_SetPrinterInfoCtr info_ctr;
+	struct spoolss_DevmodeContainer devmode_ctr;
+	struct sec_desc_buf secdesc_ctr;
+
+	info7.guid = "";
+	info7.action = DSPRINT_PUBLISH;
+
+	ZERO_STRUCT(info_ctr);
+	ZERO_STRUCT(devmode_ctr);
+	ZERO_STRUCT(secdesc_ctr);
+	info_ctr.level = 7;
+	info_ctr.info.info7 = &info7;
+
+	torture_assert(tctx,
+		       test_SetPrinter(tctx, b, handle, &info_ctr,
+				       &devmode_ctr, &secdesc_ctr, 0), "");
+
+	torture_assert(tctx,
+		       test_GetPrinter_level(tctx, b, handle, 2, &info),
+		       "");
+	torture_assert(tctx,
+		       (info.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED),
+		       "info2 publish flag not set");
+	torture_assert(tctx,
+		       test_GetPrinter_level(tctx, b, handle, 7, &info),
+		       "");
+	if (info.info7.action & DSPRINT_PENDING) {
+		torture_comment(tctx, "publish is pending\n");
+		torture_assert_int_equal(tctx,
+					 info.info7.action,
+					 (DSPRINT_PENDING | DSPRINT_PUBLISH),
+					 "info7 publish flag not set");
+	} else {
+		struct GUID guid;
+		torture_assert_int_equal(tctx,
+					 info.info7.action,
+					 DSPRINT_PUBLISH,
+					 "info7 publish flag not set");
+		torture_assert_ntstatus_ok(tctx,
+					   GUID_from_string(info.info7.guid,
+					   &guid),
+					   "invalid published printer GUID");
+	}
+
+	return true;
+}
+
+static bool test_printer_set_unpublish(struct torture_context *tctx,
+				       struct dcerpc_binding_handle *b,
+				       struct policy_handle *handle)
+{
+	union spoolss_PrinterInfo info;
+	struct spoolss_SetPrinterInfo7 info7;
+	struct spoolss_SetPrinterInfoCtr info_ctr;
+	struct spoolss_DevmodeContainer devmode_ctr;
+	struct sec_desc_buf secdesc_ctr;
+
+	info7.action = DSPRINT_UNPUBLISH;
+	info7.guid = "";
+
+	ZERO_STRUCT(info_ctr);
+	ZERO_STRUCT(devmode_ctr);
+	ZERO_STRUCT(secdesc_ctr);
+	info_ctr.level = 7;
+	info_ctr.info.info7 = &info7;
+
+	torture_assert(tctx,
+		       test_SetPrinter(tctx, b, handle, &info_ctr,
+				       &devmode_ctr, &secdesc_ctr, 0), "");
+
+	torture_assert(tctx,
+		       test_GetPrinter_level(tctx, b, handle, 2, &info),
+		       "");
+	torture_assert(tctx,
+		       !(info.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED),
+		       "info2 publish flag still set");
+	torture_assert(tctx,
+		       test_GetPrinter_level(tctx, b, handle, 7, &info),
+		       "");
+
+	if (info.info7.action & DSPRINT_PENDING) {
+		struct GUID guid;
+		torture_comment(tctx, "unpublish is pending\n");
+		torture_assert_int_equal(tctx,
+					 info.info7.action,
+					 (DSPRINT_PENDING | DSPRINT_UNPUBLISH),
+					 "info7 unpublish flag not set");
+		torture_assert_ntstatus_ok(tctx,
+					   GUID_from_string(info.info7.guid,
+					   &guid),
+					   "invalid printer GUID");
+	} else {
+		torture_assert_int_equal(tctx,
+					 info.info7.action, DSPRINT_UNPUBLISH,
+					 "info7 unpublish flag not set");
+	}
+
+	return true;
+}
+
+static bool test_printer_publish_toggle(struct torture_context *tctx,
+					   void *private_data)
+{
+	struct torture_printer_context *t =
+		talloc_get_type_abort(private_data,
+				      struct torture_printer_context);
+	struct dcerpc_pipe *p = t->spoolss_pipe;
+	struct dcerpc_binding_handle *b = p->binding_handle;
+	struct policy_handle *handle = &t->handle;
+	union spoolss_PrinterInfo info7;
+	union spoolss_PrinterInfo info2;
+
+	/* check publish status via level 7 and level 2 */
+	torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 7, &info7),
+		       "");
+	torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info2),
+		       "");
+
+	if (info2.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
+		torture_assert_int_equal(tctx,
+					 info7.info7.action, DSPRINT_PUBLISH,
+					 "info7 publish flag not set");
+		torture_assert(tctx, test_printer_set_unpublish(tctx, b, handle), "");
+		torture_assert(tctx, test_printer_set_publish(tctx, b, handle), "");
+	} else {
+		torture_assert_int_equal(tctx,
+					 info7.info7.action, DSPRINT_UNPUBLISH,
+					 "info7 unpublish flag not set");
+		torture_assert(tctx, test_printer_set_publish(tctx, b, handle), "");
+		torture_assert(tctx, test_printer_set_unpublish(tctx, b, handle), "");
+	}
+
+	return true;
+}
+
 static bool test_driver_info_winreg(struct torture_context *tctx,
 				    void *private_data)
 {
@@ -8568,6 +8710,8 @@ void torture_tcase_printer(struct torture_tcase *tcase)
 	torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
 	torture_tcase_add_simple_test(tcase, "printer_ic", test_printer_ic);
 	torture_tcase_add_simple_test(tcase, "bidi", test_printer_bidi);
+	torture_tcase_add_simple_test(tcase, "publish_toggle",
+				      test_printer_publish_toggle);
 }
 
 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)


-- 
Samba Shared Repository


More information about the samba-cvs mailing list