[SCM] Samba Shared Repository - branch v3-6-test updated

Karolin Seeger kseeger at samba.org
Mon Jan 23 12:51:20 MST 2012


The branch, v3-6-test has been updated
       via  db645b3 WHATSNEW: Add more changes.
       via  c4a3d98 torture: add spoolss overlapping driver deletion tests
       via  31f491c torture: confirm printer driver file removal
       via  b894e62 torture: add spoolss del printer driver test
       via  8e3c0ac s3-spoolss: fix printer_driver_files_in_use() call ordering
       via  54bc662 s3-spoolss: fix printer driver version deletion
       via  c145866 s3-spoolss: prefix print$ path on driver file deletion
       via  29c97b7 spoolss: fix DPD_DELETE_ALL_FILES error return
      from  f71b7a8 WHATSNEW: Add more changes since 3.6.1.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-6-test


- Log -----------------------------------------------------------------
commit db645b334e591133d664a7d1f88e82925ad52c40
Author: Karolin Seeger <kseeger at samba.org>
Date:   Mon Jan 23 20:52:37 2012 +0100

    WHATSNEW: Add more changes.
    
    Karolin

commit c4a3d988a64723a51be4b3ddaddd83708d90ed13
Author: David Disseldorp <ddiss at samba.org>
Date:   Tue Jan 17 17:07:01 2012 +0100

    torture: add spoolss overlapping driver deletion tests
    
    The last 7 patches address bug #8697 (DeletePrinterDriverEx never removes
    printer driver files) and bug #4942 (DeletePrinterDriverEx deletes files
    in use).

commit 31f491c98c07e468e1f0e840f6accb6da3281498
Author: David Disseldorp <ddiss at samba.org>
Date:   Tue Jan 17 15:20:51 2012 +0100

    torture: confirm printer driver file removal

commit b894e6297f36b05259fc6932a7ee1c500bc806e9
Author: David Disseldorp <ddiss at samba.org>
Date:   Mon Jan 16 16:30:17 2012 +0100

    torture: add spoolss del printer driver test
    
    Test handling of DeletePrinterDriverEx when the DPD_DELETE_ALL_FILES
    flag is set.

commit 8e3c0ac2815bc25360bf408c50449d154b841f8a
Author: David Disseldorp <ddiss at samba.org>
Date:   Tue Jan 17 17:06:38 2012 +0100

    s3-spoolss: fix printer_driver_files_in_use() call ordering
    
    printer_driver_files_in_use() performs two tasks: it returns whether any
    of the files in the to-be-deleted driver overlap with other drivers, it
    also trims such files from the info structure passed in.
    
    In processing a DeletePrinterDataEx request with DPD_DELETE_UNUSED_FILES
    set, printer_driver_files_in_use() must be called to ensure files in
    use by other drivers are not removed.
    
    https://bugzilla.samba.org/show_bug.cgi?id=4942

commit 54bc662adb24be9950c827446130b91504965c8c
Author: David Disseldorp <ddiss at samba.org>
Date:   Thu Jan 12 16:27:37 2012 +0100

    s3-spoolss: fix printer driver version deletion
    
    Spoolss delete printer driver code currently makes invalid version
    assumptions based on the architecture requested by the client.
    
    Ugly hacks are in place to cover removal of other versions (2 and 3).
    This change wraps multi version deletion in a simple for loop.

commit c14586647451a878fdc911ee4be699b3e6485b83
Author: David Disseldorp <ddiss at samba.org>
Date:   Wed Jan 11 19:50:36 2012 +0100

    s3-spoolss: prefix print$ path on driver file deletion
    
    Driver file paths stored in the registry do not include the server path
    prefix. delete_driver_files() incorrectly assumes such a prefix.
    
    https://bugzilla.samba.org/show_bug.cgi?id=8697

commit 29c97b7132ac316327123f200a71e70317b2dbb9
Author: David Disseldorp <ddiss at samba.org>
Date:   Tue Jan 10 18:21:42 2012 +0100

    spoolss: fix DPD_DELETE_ALL_FILES error return
    
    If DeletePrinterDriverEx is called with DPD_DELETE_ALL_FILES and files
    assigned to the to-be-deleted driver overlap with other drivers then an
    error is returned. Change the error code here to match Windows 2k8r2.
    
    Signed-off-by: David Disseldorp <ddiss at samba.org>
    Signed-off-by: Andreas Schneider <asn at samba.org>

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

Summary of changes:
 WHATSNEW.txt                                |    2 +
 source3/printing/nt_printing.c              |   81 ++++----
 source3/rpc_server/spoolss/srv_spoolss_nt.c |  304 ++++++++++++---------------
 source4/torture/rpc/spoolss.c               |  260 +++++++++++++++++++++++
 4 files changed, 429 insertions(+), 218 deletions(-)


Changeset truncated at 500 lines:

diff --git a/WHATSNEW.txt b/WHATSNEW.txt
index 8567e03..14deaf3 100644
--- a/WHATSNEW.txt
+++ b/WHATSNEW.txt
@@ -74,9 +74,11 @@ o   Günther Deschner <gd at samba.org>
 
 
 o   David Disseldorp <ddiss at suse.de>
+    * BUG 4942: DeletePrinterDriverEx deletes files in use.
     * BUG 8575: Add systemd service files.
     * BUG 8606: Fix intermittent print job failures caused by character
       conversion errors.
+    * BUG 8697: Make DeletePrinterDriverEx remove printer driver files.
 
 
 o   Björn Jacke <bj at sernet.de>
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c
index d6b8bb1..b0d4e81 100644
--- a/source3/printing/nt_printing.c
+++ b/source3/printing/nt_printing.c
@@ -1493,20 +1493,30 @@ bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
 }
 
 static NTSTATUS driver_unlink_internals(connection_struct *conn,
-					const char *name)
+					const char *short_arch,
+					int vers,
+					const char *fname)
 {
+	TALLOC_CTX *tmp_ctx = talloc_new(conn);
 	struct smb_filename *smb_fname = NULL;
-	NTSTATUS status;
+	char *print_dlr_path;
+	NTSTATUS status = NT_STATUS_NO_MEMORY;
+
+	print_dlr_path = talloc_asprintf(tmp_ctx, "%s/%d/%s",
+					 short_arch, vers, fname);
+	if (print_dlr_path == NULL) {
+		goto err_out;
+	}
 
-	status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
-	    &smb_fname);
+	status = create_synthetic_smb_fname(tmp_ctx, print_dlr_path,
+					    NULL, NULL, &smb_fname);
 	if (!NT_STATUS_IS_OK(status)) {
-		return status;
+		goto err_out;
 	}
 
 	status = unlink_internals(conn, NULL, 0, smb_fname, false);
-
-	TALLOC_FREE(smb_fname);
+err_out:
+	talloc_free(tmp_ctx);
 	return status;
 }
 
@@ -1519,9 +1529,7 @@ static NTSTATUS driver_unlink_internals(connection_struct *conn,
 bool delete_driver_files(const struct auth_serversupplied_info *session_info,
 			 const struct spoolss_DriverInfo8 *r)
 {
-	int i = 0;
-	char *s;
-	const char *file;
+	const char *short_arch;
 	connection_struct *conn;
 	NTSTATUS nt_status;
 	char *oldcwd;
@@ -1572,55 +1580,40 @@ bool delete_driver_files(const struct auth_serversupplied_info *session_info,
 		goto err_out;
 	}
 
-	/* now delete the files; must strip the '\print$' string from
-	   fron of path                                                */
+	short_arch = get_short_archi(r->architecture);
+	if (short_arch == NULL) {
+		DEBUG(0, ("bad architecture %s\n", r->architecture));
+		ret = false;
+		goto err_out;
+	}
+
+	/* now delete the files */
 
 	if (r->driver_path && r->driver_path[0]) {
-		if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
-			file = s;
-			DEBUG(10,("deleting driverfile [%s]\n", s));
-			driver_unlink_internals(conn, file);
-		}
+		DEBUG(10,("deleting driverfile [%s]\n", r->driver_path));
+		driver_unlink_internals(conn, short_arch, r->version, r->driver_path);
 	}
 
 	if (r->config_file && r->config_file[0]) {
-		if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
-			file = s;
-			DEBUG(10,("deleting configfile [%s]\n", s));
-			driver_unlink_internals(conn, file);
-		}
+		DEBUG(10,("deleting configfile [%s]\n", r->config_file));
+		driver_unlink_internals(conn, short_arch, r->version, r->config_file);
 	}
 
 	if (r->data_file && r->data_file[0]) {
-		if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
-			file = s;
-			DEBUG(10,("deleting datafile [%s]\n", s));
-			driver_unlink_internals(conn, file);
-		}
+		DEBUG(10,("deleting datafile [%s]\n", r->data_file));
+		driver_unlink_internals(conn, short_arch, r->version, r->data_file);
 	}
 
 	if (r->help_file && r->help_file[0]) {
-		if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
-			file = s;
-			DEBUG(10,("deleting helpfile [%s]\n", s));
-			driver_unlink_internals(conn, file);
-		}
+		DEBUG(10,("deleting helpfile [%s]\n", r->help_file));
+		driver_unlink_internals(conn, short_arch, r->version, r->help_file);
 	}
 
-	/* check if we are done removing files */
-
 	if (r->dependent_files) {
+		int i = 0;
 		while (r->dependent_files[i] && r->dependent_files[i][0]) {
-			char *p;
-
-			/* bypass the "\print$" portion of the path */
-
-			if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
-				file = p;
-				DEBUG(10,("deleting dependent file [%s]\n", file));
-				driver_unlink_internals(conn, file);
-			}
-
+			DEBUG(10,("deleting dependent file [%s]\n", r->dependent_files[i]));
+			driver_unlink_internals(conn, short_arch, r->version, r->dependent_files[i]);
 			i++;
 		}
 	}
diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c
index bfec3cc..ea99d10 100644
--- a/source3/rpc_server/spoolss/srv_spoolss_nt.c
+++ b/source3/rpc_server/spoolss/srv_spoolss_nt.c
@@ -2042,6 +2042,12 @@ static const struct print_architecture_table_node archi_table[]= {
 	{NULL,                   "",		-1 }
 };
 
+static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
+				   SPOOLSS_DRIVER_VERSION_NT35,
+				   SPOOLSS_DRIVER_VERSION_NT4,
+				   SPOOLSS_DRIVER_VERSION_200X,
+				   -1};
+
 static int get_version_id(const char *arch)
 {
 	int i;
@@ -2064,10 +2070,12 @@ WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
 {
 
 	struct spoolss_DriverInfo8 *info = NULL;
-	struct spoolss_DriverInfo8 *info_win2k = NULL;
 	int				version;
 	WERROR				status;
 	struct dcerpc_binding_handle *b;
+	TALLOC_CTX *tmp_ctx = NULL;
+	int i;
+	bool found;
 
 	/* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
 	   and not a printer admin, then fail */
@@ -2089,73 +2097,115 @@ WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
 	if ((version = get_version_id(r->in.architecture)) == -1)
 		return WERR_INVALID_ENVIRONMENT;
 
-	status = winreg_printer_binding_handle(p->mem_ctx,
+	tmp_ctx = talloc_new(p->mem_ctx);
+	if (!tmp_ctx) {
+		return WERR_NOMEM;
+	}
+
+	status = winreg_printer_binding_handle(tmp_ctx,
 					       get_session_info_system(),
 					       p->msg_ctx,
 					       &b);
 	if (!W_ERROR_IS_OK(status)) {
-		return status;
+		goto done;
 	}
 
-	status = winreg_get_driver(p->mem_ctx, b,
-				   r->in.architecture, r->in.driver,
-				   version, &info);
-	if (!W_ERROR_IS_OK(status)) {
-		/* try for Win2k driver if "Windows NT x86" */
-
-		if ( version == 2 ) {
-			version = 3;
-
-			status = winreg_get_driver(p->mem_ctx, b,
-						   r->in.architecture,
-						   r->in.driver,
-						   version, &info);
-			if (!W_ERROR_IS_OK(status)) {
-				status = WERR_UNKNOWN_PRINTER_DRIVER;
-				goto done;
-			}
+	for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
+		status = winreg_get_driver(tmp_ctx, b,
+					   r->in.architecture, r->in.driver,
+					   drv_cversion[i], &info);
+		if (!W_ERROR_IS_OK(status)) {
+			DEBUG(5, ("skipping del of driver with version %d\n",
+				  drv_cversion[i]));
+			continue;
 		}
-		/* otherwise it was a failure */
-		else {
-			status = WERR_UNKNOWN_PRINTER_DRIVER;
+		found = true;
+
+		if (printer_driver_in_use(tmp_ctx, get_session_info_system(),
+					  p->msg_ctx, info)) {
+			status = WERR_PRINTER_DRIVER_IN_USE;
 			goto done;
 		}
 
+		status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
+		if (!W_ERROR_IS_OK(status)) {
+			DEBUG(0, ("failed del of driver with version %d\n",
+				  drv_cversion[i]));
+			goto done;
+		}
+	}
+	if (found == false) {
+		DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
+		status = WERR_UNKNOWN_PRINTER_DRIVER;
+	} else {
+		status = WERR_OK;
 	}
 
-	if (printer_driver_in_use(p->mem_ctx,
-				  get_session_info_system(),
-				  p->msg_ctx,
-				  info)) {
+done:
+	talloc_free(tmp_ctx);
+	return status;
+}
+
+static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
+				  struct pipes_struct *p,
+				  struct spoolss_DeletePrinterDriverEx *r,
+				  struct dcerpc_binding_handle *b,
+				  struct spoolss_DriverInfo8 *info)
+{
+	WERROR status;
+	bool delete_files;
+
+	if (printer_driver_in_use(mem_ctx, get_session_info_system(),
+				  p->msg_ctx, info)) {
 		status = WERR_PRINTER_DRIVER_IN_USE;
 		goto done;
 	}
 
-	if (version == 2) {
-		status = winreg_get_driver(p->mem_ctx, b,
-					   r->in.architecture,
-					   r->in.driver, 3, &info_win2k);
-		if (W_ERROR_IS_OK(status)) {
-			/* if we get to here, we now have 2 driver info structures to remove */
-			/* remove the Win2k driver first*/
+	/*
+	 * we have a couple of cases to consider.
+	 * (1) Are any files in use?  If so and DPD_DELETE_ALL_FILES is set,
+	 *     then the delete should fail if **any** files overlap with
+	 *     other drivers
+	 * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
+	 *     non-overlapping files
+	 * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
+	 *     is set, then do not delete any files
+	 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
+	 */
 
-			status = winreg_del_driver(p->mem_ctx, b,
-						   info_win2k, 3);
-			talloc_free(info_win2k);
+	delete_files = r->in.delete_flags
+			& (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
 
-			/* this should not have failed---if it did, report to client */
-			if (!W_ERROR_IS_OK(status)) {
-				goto done;
-			}
+	if (delete_files) {
+		bool in_use = printer_driver_files_in_use(mem_ctx,
+						get_session_info_system(),
+							  b,
+							  info);
+		if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
+			status = WERR_PRINTER_DRIVER_IN_USE;
+			goto done;
 		}
+		/*
+		 * printer_driver_files_in_use() has trimmed overlapping files
+		 * from info so they are not removed on DPD_DELETE_UNUSED_FILES
+		 */
 	}
 
-	status = winreg_del_driver(p->mem_ctx, b,
-				   info, version);
+	status = winreg_del_driver(mem_ctx, b, info, info->version);
+	if (!W_ERROR_IS_OK(status)) {
+		goto done;
+	}
 
-done:
-	talloc_free(info);
+	/*
+	 * now delete any associated files if delete_files is
+	 * true. Even if this part failes, we return succes
+	 * because the driver doesn not exist any more
+	 */
+	if (delete_files) {
+		delete_driver_files(get_session_info_system(), info);
+	}
 
+done:
 	return status;
 }
 
@@ -2166,12 +2216,12 @@ done:
 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
 				      struct spoolss_DeletePrinterDriverEx *r)
 {
-	struct spoolss_DriverInfo8	*info = NULL;
-	struct spoolss_DriverInfo8	*info_win2k = NULL;
-	int				version;
-	bool				delete_files;
+	struct spoolss_DriverInfo8 *info = NULL;
 	WERROR				status;
 	struct dcerpc_binding_handle *b;
+	TALLOC_CTX *tmp_ctx = NULL;
+	int i;
+	bool found;
 
 	/* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
 	   and not a printer admin, then fail */
@@ -2188,151 +2238,57 @@ WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
 	}
 
 	/* check that we have a valid driver name first */
-	if ((version = get_version_id(r->in.architecture)) == -1) {
+	if (get_version_id(r->in.architecture) == -1) {
 		/* this is what NT returns */
 		return WERR_INVALID_ENVIRONMENT;
 	}
 
-	if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
-		version = r->in.version;
+	tmp_ctx = talloc_new(p->mem_ctx);
+	if (!tmp_ctx) {
+		return WERR_NOMEM;
+	}
 
-	status = winreg_printer_binding_handle(p->mem_ctx,
+	status = winreg_printer_binding_handle(tmp_ctx,
 					       get_session_info_system(),
 					       p->msg_ctx,
 					       &b);
 	if (!W_ERROR_IS_OK(status)) {
-		return status;
+		goto done;
 	}
 
-	status = winreg_get_driver(p->mem_ctx, b,
-				   r->in.architecture,
-				   r->in.driver,
-				   version,
-				   &info);
-	if (!W_ERROR_IS_OK(status)) {
-		status = WERR_UNKNOWN_PRINTER_DRIVER;
-
-		/*
-		 * if the client asked for a specific version,
-		 * or this is something other than Windows NT x86,
-		 * then we've failed
-		 */
-
-		if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
-			goto done;
-
-		/* try for Win2k driver if "Windows NT x86" */
+	for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
+		if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
+		 && (drv_cversion[i] != r->in.version)) {
+			continue;
+		}
 
-		version = 3;
-		status = winreg_get_driver(info, b,
-					   r->in.architecture,
-					   r->in.driver,
-					   version, &info);
+		/* check if a driver with this version exists before delete */
+		status = winreg_get_driver(tmp_ctx, b,
+					   r->in.architecture, r->in.driver,
+					   drv_cversion[i], &info);
 		if (!W_ERROR_IS_OK(status)) {
-			status = WERR_UNKNOWN_PRINTER_DRIVER;
-			goto done;
+			DEBUG(5, ("skipping del of driver with version %d\n",
+				  drv_cversion[i]));
+			continue;
 		}
-	}
-
-	if (printer_driver_in_use(info,
-				  get_session_info_system(),
-				  p->msg_ctx,
-				  info)) {
-		status = WERR_PRINTER_DRIVER_IN_USE;
-		goto done;
-	}
-
-	/*
-	 * we have a couple of cases to consider.
-	 * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
-	 *     then the delete should fail if **any** files overlap with
-	 *     other drivers
-	 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
-	 *     non-overlapping files
-	 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
-	 *     is set, the do not delete any files
-	 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
-	 */
-
-	delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
-
-	/* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
-
-	if (delete_files &&
-	    (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
-	    printer_driver_files_in_use(info,
-					get_session_info_system(),
-					p->msg_ctx,
-					info)) {
-		/* no idea of the correct error here */
-		status = WERR_ACCESS_DENIED;
-		goto done;
-	}
-
-
-	/* also check for W32X86/3 if necessary; maybe we already have? */
-
-	if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
-		status = winreg_get_driver(info, b,
-					   r->in.architecture,
-					   r->in.driver, 3, &info_win2k);
-		if (W_ERROR_IS_OK(status)) {
-
-			if (delete_files &&
-			    (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
-			    printer_driver_files_in_use(info,
-							get_session_info_system(),
-							p->msg_ctx,
-							info_win2k)) {
-				/* no idea of the correct error here */
-				talloc_free(info_win2k);
-				status = WERR_ACCESS_DENIED;
-				goto done;
-			}
-
-			/* if we get to here, we now have 2 driver info structures to remove */
-			/* remove the Win2k driver first*/
-
-			status = winreg_del_driver(info, b,
-						   info_win2k,
-						   3);
-
-			/* this should not have failed---if it did, report to client */
-
-			if (!W_ERROR_IS_OK(status)) {
-				goto done;
-			}
+		found = true;
 
-			/*
-			 * now delete any associated files if delete_files is
-			 * true. Even if this part failes, we return succes
-			 * because the driver doesn not exist any more
-			 */
-			if (delete_files) {
-				delete_driver_files(get_session_info_system(),
-						    info_win2k);
-			}


-- 
Samba Shared Repository


More information about the samba-cvs mailing list