The Samba-Bugzilla – Attachment 6639 Details for
Bug 8214
printer driver upgrade fails, causing smbd to exit on startup
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
driver upgrade fix using APD_COPY_FROM_DIRECTORY
s3-printing-fix-migrate_driver_cp_from_dir.patch (text/plain), 14.83 KB, created by
David Disseldorp
on 2011-06-27 20:28:19 UTC
(
hide
)
Description:
driver upgrade fix using APD_COPY_FROM_DIRECTORY
Filename:
MIME Type:
Creator:
David Disseldorp
Created:
2011-06-27 20:28:19 UTC
Size:
14.83 KB
patch
obsolete
>From fa6ebf10de3dfe847b204531024893b35806ac75 Mon Sep 17 00:00:00 2001 >From: David Disseldorp <ddiss@suse.de> >Date: Fri, 24 Jun 2011 10:55:08 +0200 >Subject: [PATCH 1/2] s3-printing: fix migrate_driver() > >_spoolss_AddPrinterDriverEx() currently strips all driver paths to base >file names and assumes that these files are staged in the $architecture >subdirectory of the print$ share path. > >This assumption is incorrect when an AddPrinterDriver is issued to >upgrade internal printing tdbs to the new registry format, as performed >by migrate_driver(). > >This fix adds support for APD_COPY_FROM_DIRECTORY which allows fully >qualified file names in an AddPrinterDriverEx request. > >https://bugzilla.samba.org/show_bug.cgi?id=8214 >--- > source3/include/nt_printing.h | 11 ++- > source3/printing/nt_printing.c | 148 ++++++++++++++++---------- > source3/printing/nt_printing_migrate.c | 69 ++++++++---- > source3/rpc_server/spoolss/srv_spoolss_nt.c | 26 +++++- > 4 files changed, 169 insertions(+), 85 deletions(-) > >diff --git a/source3/include/nt_printing.h b/source3/include/nt_printing.h >index ad6262e..ee16145 100644 >--- a/source3/include/nt_printing.h >+++ b/source3/include/nt_printing.h >@@ -172,9 +172,14 @@ bool delete_driver_files(const struct auth_serversupplied_info *server_info, > WERROR move_driver_to_download_area(struct auth_serversupplied_info *session_info, > struct spoolss_AddDriverInfoCtr *r); > >-WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx, >- struct auth_serversupplied_info *session_info, >- struct spoolss_AddDriverInfoCtr *r); >+WERROR get_driver_cversion_struct(TALLOC_CTX *mem_ctx, >+ struct auth_serversupplied_info *session_info, >+ struct spoolss_AddDriverInfoCtr *r); >+ >+WERROR strip_driver_paths_struct(TALLOC_CTX *mem_ctx, >+ struct auth_serversupplied_info *session_info, >+ struct spoolss_AddDriverInfoCtr *r, >+ bool prepend_arch); > > void map_printer_permissions(struct security_descriptor *sd); > >diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c >index 6d4bebb..71c442a 100644 >--- a/source3/printing/nt_printing.c >+++ b/source3/printing/nt_printing.c >@@ -581,7 +581,6 @@ static uint32 get_correct_cversion(struct auth_serversupplied_info *session_info > int cversion = -1; > NTSTATUS nt_status; > struct smb_filename *smb_fname = NULL; >- char *driverpath = NULL; > files_struct *fsp = NULL; > connection_struct *conn = NULL; > char *oldcwd; >@@ -639,16 +638,7 @@ static uint32 get_correct_cversion(struct auth_serversupplied_info *session_info > > /* Open the driver file (Portable Executable format) and determine the > * deriver the cversion. */ >- driverpath = talloc_asprintf(talloc_tos(), >- "%s/%s", >- architecture, >- driverpath_in); >- if (!driverpath) { >- *perr = WERR_NOMEM; >- goto error_exit; >- } >- >- nt_status = driver_unix_convert(conn, driverpath, &smb_fname); >+ nt_status = driver_unix_convert(conn, driverpath_in, &smb_fname); > if (!NT_STATUS_IS_OK(nt_status)) { > *perr = ntstatus_to_werror(nt_status); > goto error_exit; >@@ -753,27 +743,28 @@ static uint32 get_correct_cversion(struct auth_serversupplied_info *session_info > /**************************************************************************** > ****************************************************************************/ > >-#define strip_driver_path(_mem_ctx, _element) do { \ >+#define strip_driver_path(_mem_ctx, _prefix, _element) do { \ >+ char *_p; \ > if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \ >- (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \ >+ (_element) = talloc_asprintf((_mem_ctx), "%s%s", \ >+ (_prefix) ? (_prefix) : "", _p+1); \ > W_ERROR_HAVE_NO_MEMORY((_element)); \ > } \ > } while (0); > >-static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx, >- struct auth_serversupplied_info *session_info, >- const char *architecture, >- const char **driver_path, >- const char **data_file, >- const char **config_file, >- const char **help_file, >- struct spoolss_StringArray *dependent_files, >- enum spoolss_DriverOSVersion *version) >+static WERROR strip_driver_paths(TALLOC_CTX *mem_ctx, >+ struct auth_serversupplied_info *session_info, >+ const char *architecture, >+ const char **driver_path, >+ const char **data_file, >+ const char **config_file, >+ const char **help_file, >+ struct spoolss_StringArray *dependent_files, >+ bool prepend_arch) > { >- const char *short_architecture; > int i; >- WERROR err; >- char *_p; >+ const char *short_architecture; >+ const char *prefix; > > if (!*driver_path || !*data_file) { > return WERR_INVALID_PARAM; >@@ -783,28 +774,68 @@ static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx, > return WERR_INVALID_PARAM; > } > >+ short_architecture = get_short_archi(architecture); >+ if (!short_architecture) { >+ return WERR_UNKNOWN_PRINTER_DRIVER; >+ } >+ >+ if (prepend_arch) { >+ prefix = talloc_asprintf(mem_ctx, "%s\\", short_architecture); >+ } else { >+ prefix = NULL; >+ } >+ > /* clean up the driver name. > * we can get .\driver.dll > * or worse c:\windows\system\driver.dll ! > */ > /* using an intermediate string to not have overlaping memcpy()'s */ > >- strip_driver_path(mem_ctx, *driver_path); >- strip_driver_path(mem_ctx, *data_file); >+ strip_driver_path(mem_ctx, prefix, *driver_path); >+ strip_driver_path(mem_ctx, prefix, *data_file); > if (*config_file) { >- strip_driver_path(mem_ctx, *config_file); >+ strip_driver_path(mem_ctx, prefix, *config_file); > } > if (help_file) { >- strip_driver_path(mem_ctx, *help_file); >+ strip_driver_path(mem_ctx, prefix, *help_file); > } > > if (dependent_files && dependent_files->string) { > for (i=0; dependent_files->string[i]; i++) { >- strip_driver_path(mem_ctx, dependent_files->string[i]); >+ strip_driver_path(mem_ctx, prefix, >+ dependent_files->string[i]); > } > } > >- short_architecture = get_short_archi(architecture); >+ return WERR_OK; >+} >+ >+WERROR get_driver_cversion_struct(TALLOC_CTX *mem_ctx, >+ struct auth_serversupplied_info *session_info, >+ struct spoolss_AddDriverInfoCtr *r) >+{ >+ const char *long_arch; >+ const char *short_architecture; >+ const char *driver_path; >+ enum spoolss_DriverOSVersion *version; >+ WERROR err; >+ >+ switch (r->level) { >+ case 3: >+ long_arch = r->info.info3->architecture; >+ driver_path = r->info.info3->driver_path; >+ version = &r->info.info3->version; >+ break; >+ case 6: >+ long_arch = r->info.info6->architecture; >+ driver_path = r->info.info6->driver_path; >+ version = &r->info.info6->version; >+ break; >+ default: >+ return WERR_NOT_SUPPORTED; >+ } >+ >+ short_architecture = get_short_archi(long_arch); > if (!short_architecture) { > return WERR_UNKNOWN_PRINTER_DRIVER; > } >@@ -822,40 +853,40 @@ static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx, > */ > > *version = get_correct_cversion(session_info, short_architecture, >- *driver_path, &err); >+ driver_path, &err); > if (*version == -1) { > return err; > } >- > return WERR_OK; > } > > /**************************************************************************** > ****************************************************************************/ > >-WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx, >- struct auth_serversupplied_info *session_info, >- struct spoolss_AddDriverInfoCtr *r) >+WERROR strip_driver_paths_struct(TALLOC_CTX *mem_ctx, >+ struct auth_serversupplied_info *session_info, >+ struct spoolss_AddDriverInfoCtr *r, >+ bool prepend_arch) > { > switch (r->level) { > case 3: >- return clean_up_driver_struct_level(mem_ctx, session_info, >- r->info.info3->architecture, >- &r->info.info3->driver_path, >- &r->info.info3->data_file, >- &r->info.info3->config_file, >- &r->info.info3->help_file, >- r->info.info3->dependent_files, >- &r->info.info3->version); >+ return strip_driver_paths(mem_ctx, session_info, >+ r->info.info3->architecture, >+ &r->info.info3->driver_path, >+ &r->info.info3->data_file, >+ &r->info.info3->config_file, >+ &r->info.info3->help_file, >+ r->info.info3->dependent_files, >+ prepend_arch); > case 6: >- return clean_up_driver_struct_level(mem_ctx, session_info, >- r->info.info6->architecture, >- &r->info.info6->driver_path, >- &r->info.info6->data_file, >- &r->info.info6->config_file, >- &r->info.info6->help_file, >- r->info.info6->dependent_files, >- &r->info.info6->version); >+ return strip_driver_paths(mem_ctx, session_info, >+ r->info.info6->architecture, >+ &r->info.info6->driver_path, >+ &r->info.info6->data_file, >+ &r->info.info6->config_file, >+ &r->info.info6->help_file, >+ r->info.info6->dependent_files, >+ prepend_arch); > default: > return WERR_NOT_SUPPORTED; > } >@@ -883,6 +914,7 @@ static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst, > } > > /**************************************************************************** >+ Move a driver file to its corresponding $arch/$driver_version subdirectory > ****************************************************************************/ > > static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx, >@@ -896,19 +928,21 @@ static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx, > struct smb_filename *smb_fname_new = NULL; > char *old_name = NULL; > char *new_name = NULL; >+ char *new_path_prefix; > NTSTATUS status; > WERROR ret; > >- old_name = talloc_asprintf(mem_ctx, "%s/%s", >- short_architecture, driver_file); >+ old_name = talloc_strdup(mem_ctx, driver_file); > W_ERROR_HAVE_NO_MEMORY(old_name); > >- new_name = talloc_asprintf(mem_ctx, "%s/%d/%s", >- short_architecture, driver_version, driver_file); >- if (new_name == NULL) { >+ new_name = old_name; >+ new_path_prefix = talloc_asprintf(mem_ctx, "%s/%d/", >+ short_architecture, driver_version); >+ if (new_path_prefix == NULL) { > TALLOC_FREE(old_name); > return WERR_NOMEM; > } >+ strip_driver_path(mem_ctx, new_path_prefix, new_name); > > if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) { > >diff --git a/source3/printing/nt_printing_migrate.c b/source3/printing/nt_printing_migrate.c >index e122934..ad4b4b1 100644 >--- a/source3/printing/nt_printing_migrate.c >+++ b/source3/printing/nt_printing_migrate.c >@@ -133,6 +133,15 @@ static NTSTATUS migrate_form(TALLOC_CTX *mem_ctx, > return status; > } > >+static char *normalize_drv_path(const char **path) >+{ >+ int ret = strncmp(*path, "\\print$", sizeof("\\print$") - 1); >+ if (ret == 0) { >+ return (char *)(*path + sizeof("\\print$") - 1); >+ } >+ return (char *)*path; >+} >+ > static NTSTATUS migrate_driver(TALLOC_CTX *mem_ctx, > struct rpc_pipe_client *pipe_hnd, > const char *key_name, >@@ -144,11 +153,13 @@ static NTSTATUS migrate_driver(TALLOC_CTX *mem_ctx, > enum ndr_err_code ndr_err; > struct ntprinting_driver r; > struct spoolss_AddDriverInfoCtr d; >- struct spoolss_AddDriverInfo3 d3; >+ struct spoolss_AddDriverInfo6 d6; > struct spoolss_StringArray a; > DATA_BLOB blob; > NTSTATUS status; > WERROR result; >+ char *npath; >+ int i; > > blob = data_blob_const(data, length); > >@@ -169,36 +180,48 @@ static NTSTATUS migrate_driver(TALLOC_CTX *mem_ctx, > return NT_STATUS_NO_MEMORY; > } > >- ZERO_STRUCT(d3); >+ ZERO_STRUCT(d6); > ZERO_STRUCT(a); > >+ for (i = 0; r.dependent_files[i] != NULL; i++) { >+ npath = normalize_drv_path(&r.dependent_files[i]); >+ r.dependent_files[i] = npath; >+ } > a.string = r.dependent_files; > >- d3.architecture = r.environment; >- d3.config_file = r.configfile; >- d3.data_file = r.datafile; >- d3.default_datatype = r.defaultdatatype; >- d3.dependent_files = &a; >- d3.driver_path = r.driverpath; >- d3.help_file = r.helpfile; >- d3.monitor_name = r.monitorname; >- d3.driver_name = r.name; >- d3.version = r.version; >- >- d.level = 3; >- d.info.info3 = &d3; >- >- status = dcerpc_spoolss_AddPrinterDriver(b, >- mem_ctx, >- srv_name_slash, >- &d, >- &result); >+ /* file paths are in \print$\arch\driver_version format */ >+ d6.architecture = r.environment; >+ d6.config_file = normalize_drv_path(&r.configfile); >+ d6.data_file = normalize_drv_path(&r.datafile); >+ d6.default_datatype = r.defaultdatatype; >+ d6.dependent_files = &a; >+ d6.driver_path = normalize_drv_path(&r.driverpath); >+ d6.help_file = normalize_drv_path(&r.helpfile); >+ d6.monitor_name = r.monitorname; >+ d6.driver_name = r.name; >+ d6.version = r.version; >+ >+ d.level = 6; >+ d.info.info6 = &d6; >+ >+ /* >+ * Driver files are already present, use APD_COPY_FROM_DIRECTORY to: >+ * Add the printer driver by using the fully qualified file names that >+ * are specified in the _DRIVER_INFO_6 structure. >+ */ >+ status = dcerpc_spoolss_AddPrinterDriverEx(b, >+ mem_ctx, >+ srv_name_slash, >+ &d, >+ APD_COPY_NEW_FILES >+ | APD_COPY_FROM_DIRECTORY, >+ &result); > if (!NT_STATUS_IS_OK(status)) { > DEBUG(2, ("dcerpc_spoolss_AddPrinterDriver(%s) refused -- %s.\n", >- d3.driver_name, nt_errstr(status))); >+ d6.driver_name, nt_errstr(status))); > } else if (!W_ERROR_IS_OK(result)) { > DEBUG(2, ("AddPrinterDriver(%s) refused -- %s.\n", >- d3.driver_name, win_errstr(result))); >+ d6.driver_name, win_errstr(result))); > status = werror_to_ntstatus(result); > } > >diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c >index 7980072..289b25a 100644 >--- a/source3/rpc_server/spoolss/srv_spoolss_nt.c >+++ b/source3/rpc_server/spoolss/srv_spoolss_nt.c >@@ -8029,7 +8029,8 @@ WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p, > return WERR_INVALID_PARAM; > } > >- if (r->in.flags != APD_COPY_NEW_FILES) { >+ if ((r->in.flags != APD_COPY_NEW_FILES) >+ && (r->in.flags != (APD_COPY_NEW_FILES | APD_COPY_FROM_DIRECTORY))) { > return WERR_ACCESS_DENIED; > } > >@@ -8044,7 +8045,17 @@ WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p, > } > > DEBUG(5,("Cleaning driver's information\n")); >- err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr); >+ if (r->in.flags & APD_COPY_FROM_DIRECTORY) { >+ /* TODO validate paths exist under print$ */ >+ } else { >+ /* assume source driver files are staged in print$\arch\ */ >+ err = strip_driver_paths_struct(p->mem_ctx, p->session_info, >+ r->in.info_ctr, true); >+ if (!W_ERROR_IS_OK(err)) >+ goto done; >+ } >+ err = get_driver_cversion_struct(p->mem_ctx, p->session_info, >+ r->in.info_ctr); > if (!W_ERROR_IS_OK(err)) > goto done; > >@@ -8054,6 +8065,17 @@ WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p, > goto done; > } > >+ /* >+ * Driver paths are stored in the registry stripped of directory >+ * prefixes. The print$\arch\version\ path is reconstructed when >+ * processing GetPrinterDriver requests. >+ */ >+ err = strip_driver_paths_struct(p->mem_ctx, p->session_info, >+ r->in.info_ctr, false); >+ if (!W_ERROR_IS_OK(err)) { >+ goto done; >+ } >+ > err = winreg_add_driver(p->mem_ctx, > get_session_info_system(), > p->msg_ctx, >-- >1.7.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 8214
:
6550
|
6554
| 6639 |
6677