{NULL, "", -1 }
};
+static bool print_driver_directories_init(void)
+{
+ int service, i;
+ char *driver_path;
+ bool ok;
+ TALLOC_CTX *mem_ctx = talloc_stackframe();
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
+
+ const char *dir_list[] = {
+ "W32X86/PCC",
+ "x64/PCC",
+ "color"
+ };
+
+ service = lp_servicenumber("print$");
+ if (service < 0) {
+ /* We don't have a print$ share */
+ DEBUG(5, ("No print$ share has been configured.\n"));
+ talloc_free(mem_ctx);
+ return true;
+ }
+
+ driver_path = lp_path(mem_ctx, lp_sub, service);
+ if (driver_path == NULL) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ ok = directory_create_or_exist(driver_path, 0755);
+ if (!ok) {
+ DEBUG(1, ("Failed to create printer driver directory %s\n",
+ driver_path));
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ for (i = 0; archi_table[i].long_archi != NULL; i++) {
+ const char *arch_path;
+
+ arch_path = talloc_asprintf(mem_ctx,
+ "%s/%s",
+ driver_path,
+ archi_table[i].short_archi);
+ if (arch_path == NULL) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ ok = directory_create_or_exist(arch_path, 0755);
+ if (!ok) {
+ DEBUG(1, ("Failed to create printer driver "
+ "architecture directory %s\n",
+ arch_path));
+ talloc_free(mem_ctx);
+ return false;
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(dir_list); i++) {
+ const char *path;
+
+ path = talloc_asprintf(mem_ctx,
+ "%s/%s",
+ driver_path,
+ dir_list[i]);
+ if (path == NULL) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ ok = directory_create_or_exist(path, 0755);
+ if (!ok) {
+ DEBUG(1, ("Failed to create printer driver "
+ "architecture directory %s\n",
+ path));
+ talloc_free(mem_ctx);
+ return false;
+ }
+ }
+
+ driver_path = state_path(talloc_tos(), "DriverStore");
+ if (driver_path == NULL) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ ok = directory_create_or_exist(driver_path, 0755);
+ if (!ok) {
+ DEBUG(1,("failed to create path %s\n", driver_path));
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ driver_path = state_path(talloc_tos(), "DriverStore/FileRepository");
+ if (driver_path == NULL) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ ok = directory_create_or_exist(driver_path, 0755);
+ if (!ok) {
+ DEBUG(1,("failed to create path %s\n", driver_path));
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ driver_path = state_path(talloc_tos(), "DriverStore/Temp");
+ if (driver_path == NULL) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ ok = directory_create_or_exist(driver_path, 0755);
+ if (!ok) {
+ DEBUG(1,("failed to create path %s\n", driver_path));
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ talloc_free(mem_ctx);
+ return true;
+}
+
+/****************************************************************************
+ Forward a MSG_PRINTER_DRVUPGRADE message from another smbd to the
+ background lpq updater.
+****************************************************************************/
+
+static void forward_drv_upgrade_printer_msg(struct messaging_context *msg,
+ void *private_data,
+ uint32_t msg_type,
+ struct server_id server_id,
+ DATA_BLOB *data)
+{
+ extern pid_t background_lpq_updater_pid;
+
+ if (background_lpq_updater_pid == -1) {
+ DEBUG(3,("no background lpq queue updater\n"));
+ return;
+ }
+
+ messaging_send_buf(msg,
+ pid_to_procid(background_lpq_updater_pid),
+ MSG_PRINTER_DRVUPGRADE,
+ data->data,
+ data->length);
+}
+
/****************************************************************************
Open the NT printing tdbs. Done once before fork().
****************************************************************************/
{
WERROR win_rc;
+ if (!print_driver_directories_init()) {
+ return false;
+ }
+
if (!nt_printing_tdb_upgrade()) {
return false;
}
/*
* register callback to handle updating printers as new
- * drivers are installed
+ * drivers are installed. Forwards to background lpq updater.
*/
messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
- do_drv_upgrade_printer);
-
- /* of course, none of the message callbacks matter if you don't
- tell messages.c that you interested in receiving PRINT_GENERAL
- msgs. This is done in serverid_register() */
+ forward_drv_upgrade_printer_msg);
if ( lp_security() == SEC_ADS ) {
win_rc = check_published_printers(msg_ctx);
}
/****************************************************************************
- Version information in Microsoft files is held in a VS_VERSION_INFO structure.
- There are two case to be covered here: PE (Portable Executable) and NE (New
- Executable) files. Both files support the same INFO structure, but PE files
- store the signature in unicode, and NE files store it as !unicode.
- returns -1 on error, 1 on version info found, and 0 on no version info found.
+ Read data from fsp on the vfs.
****************************************************************************/
-static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
+static ssize_t printing_pread_data(files_struct *fsp,
+ char *buf,
+ off_t *poff,
+ size_t byte_count)
{
- int i;
- char *buf = NULL;
- ssize_t byte_count;
+ size_t total=0;
+ off_t in_pos = *poff;
- if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
- DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
- fname, DOS_HEADER_SIZE));
- goto error_exit;
+ /* Don't allow integer wrap on read. */
+ if (in_pos + byte_count < in_pos) {
+ return -1;
}
- if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
- DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
- fname, (unsigned long)byte_count));
- goto no_version_info;
- }
+ while (total < byte_count) {
+ ssize_t ret = read_file(fsp,
+ buf + total,
+ in_pos,
+ byte_count - total);
- /* Is this really a DOS header? */
- if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
- DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
- fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
- goto no_version_info;
+ if (ret == 0) {
+ *poff = in_pos;
+ return total;
+ }
+ if (ret == -1) {
+ if (errno == EINTR) {
+ continue;
+ } else {
+ return -1;
+ }
+ }
+ in_pos += ret;
+ total += ret;
}
+ *poff = in_pos;
+ return (ssize_t)total;
+}
- /* Skip OEM header (if any) and the DOS stub to start of Windows header */
- if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (off_t)-1) {
- DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
- fname, errno));
- /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
- goto no_version_info;
- }
+/****************************************************************************
+ Detect the major and minor version of a PE file.
+ Returns:
- /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
- if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
- DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
- fname, (unsigned long)byte_count));
- /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
- goto no_version_info;
+ 1 if file is a PE file and we got version numbers,
+ 0 if this file is a PE file and we couldn't get the version numbers,
+ -1 on error.
+
+ NB. buf is passed into and freed inside this function. This is a
+ bad API design, but fixing this is a task for another day.
+****************************************************************************/
+
+static int handle_pe_file(files_struct *fsp,
+ off_t in_pos,
+ char *fname,
+ char *buf,
+ uint32_t *major,
+ uint32_t *minor)
+{
+ unsigned int i;
+ unsigned int num_sections;
+ unsigned int section_table_bytes;
+ ssize_t byte_count;
+ off_t rel_pos;
+ int ret = -1;
+
+ /* Just skip over optional header to get to section table */
+ rel_pos = SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-
+ (NE_HEADER_SIZE-PE_HEADER_SIZE);
+
+ if (in_pos + rel_pos < in_pos) {
+ /* Integer wrap. */
+ goto out;
}
+ in_pos = rel_pos + in_pos;
- /* The header may be a PE (Portable Executable) or an NE (New Executable) */
- if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
- unsigned int num_sections;
- unsigned int section_table_bytes;
-
- /* Just skip over optional header to get to section table */
- if (SMB_VFS_LSEEK(fsp,
- SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
- SEEK_CUR) == (off_t)-1) {
- DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
- fname, errno));
- goto error_exit;
- }
+ /* get the section table */
+ num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
- /* get the section table */
- num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
- section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
- if (section_table_bytes == 0)
- goto error_exit;
+ if (num_sections >= (UINT_MAX / PE_HEADER_SECT_HEADER_SIZE)) {
+ /* Integer wrap. */
+ goto out;
+ }
- SAFE_FREE(buf);
- if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
- DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
- fname, section_table_bytes));
- goto error_exit;
- }
+ section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
+ if (section_table_bytes == 0) {
+ goto out;
+ }
- if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
- DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
- fname, (unsigned long)byte_count));
- goto error_exit;
- }
+ SAFE_FREE(buf);
+ buf = (char *)SMB_MALLOC(section_table_bytes);
+ if (buf == NULL) {
+ DBG_ERR("PE file [%s] section table malloc "
+ "failed bytes = %d\n",
+ fname,
+ section_table_bytes);
+ goto out;
+ }
+
+ byte_count = printing_pread_data(fsp, buf, &in_pos, section_table_bytes);
+ if (byte_count < section_table_bytes) {
+ DBG_NOTICE("PE file [%s] Section header too short, "
+ "bytes read = %lu\n",
+ fname,
+ (unsigned long)byte_count);
+ goto out;
+ }
- /* Iterate the section table looking for the resource section ".rsrc" */
- for (i = 0; i < num_sections; i++) {
- int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
+ /*
+ * Iterate the section table looking for
+ * the resource section ".rsrc"
+ */
+ for (i = 0; i < num_sections; i++) {
+ int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
+
+ if (strcmp(".rsrc",
+ &buf[sec_offset+ PE_HEADER_SECT_NAME_OFFSET]) == 0) {
+ unsigned int section_pos = IVAL(buf,
+ sec_offset+
+ PE_HEADER_SECT_PTR_DATA_OFFSET);
+ unsigned int section_bytes = IVAL(buf,
+ sec_offset+
+ PE_HEADER_SECT_SIZE_DATA_OFFSET);
+
+ if (section_bytes == 0) {
+ goto out;
+ }
- if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
- unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
- unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
+ SAFE_FREE(buf);
+ buf=(char *)SMB_MALLOC(section_bytes);
+ if (buf == NULL) {
+ DBG_ERR("PE file [%s] version malloc "
+ "failed bytes = %d\n",
+ fname,
+ section_bytes);
+ goto out;
+ }
- if (section_bytes == 0)
- goto error_exit;
+ /*
+ * Read from the start of the .rsrc
+ * section info
+ */
+ in_pos = section_pos;
+
+ byte_count = printing_pread_data(fsp,
+ buf,
+ &in_pos,
+ section_bytes);
+ if (byte_count < section_bytes) {
+ DBG_NOTICE("PE file "
+ "[%s] .rsrc section too short, "
+ "bytes read = %lu\n",
+ fname,
+ (unsigned long)byte_count);
+ goto out;
+ }
- SAFE_FREE(buf);
- if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
- DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
- fname, section_bytes));
- goto error_exit;
- }
+ if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE) {
+ goto out;
+ }
- /* Seek to the start of the .rsrc section info */
- if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (off_t)-1) {
- DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
- fname, errno));
- goto error_exit;
+ for (i=0;
+ i< section_bytes - VS_VERSION_INFO_UNICODE_SIZE;
+ i++) {
+ /*
+ * Scan for 1st 3 unicoded bytes
+ * followed by word aligned magic
+ * value.
+ */
+ int mpos;
+ bool magic_match = false;
+
+ if (buf[i] == 'V' &&
+ buf[i+1] == '\0' &&
+ buf[i+2] == 'S') {
+ magic_match = true;
}
- if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
- DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
- fname, (unsigned long)byte_count));
- goto error_exit;
+ if (magic_match == false) {
+ continue;
}
- if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
- goto error_exit;
-
- for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
- /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
- if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
- /* Align to next long address */
- int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
-
- if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
- *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
- *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
-
- DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
- fname, *major, *minor,
- (*major>>16)&0xffff, *major&0xffff,
- (*minor>>16)&0xffff, *minor&0xffff));
- SAFE_FREE(buf);
- return 1;
- }
- }
+ /* Align to next long address */
+ mpos = (i + sizeof(VS_SIGNATURE)*2 +
+ 3) & 0xfffffffc;
+
+ if (IVAL(buf,mpos) == VS_MAGIC_VALUE) {
+ *major = IVAL(buf,
+ mpos+ VS_MAJOR_OFFSET);
+ *minor = IVAL(buf,
+ mpos+ VS_MINOR_OFFSET);
+
+ DBG_INFO("PE file [%s] Version = "
+ "%08x:%08x (%d.%d.%d.%d)\n",
+ fname,
+ *major,
+ *minor,
+ (*major>>16)&0xffff,
+ *major&0xffff,
+ (*minor>>16)&0xffff,
+ *minor&0xffff);
+ ret = 1;
+ goto out;
}
}
}
+ }
- /* Version info not found, fall back to origin date/time */
- DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
- SAFE_FREE(buf);
- return 0;
+ /* Version info not found, fall back to origin date/time */
+ DBG_DEBUG("PE file [%s] has no version info\n", fname);
+ ret = 0;
- } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
- if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
- DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
- fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
- /* At this point, we assume the file is in error. It still could be somthing
- * else besides a NE file, but it unlikely at this point. */
- goto error_exit;
- }
+ out:
- /* Allocate a bit more space to speed up things */
- SAFE_FREE(buf);
- if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
- DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
- fname, PE_HEADER_SIZE));
- goto error_exit;
+ SAFE_FREE(buf);
+ return ret;
+}
+
+/****************************************************************************
+ Detect the major and minor version of an NE file.
+ Returns:
+
+ 1 if file is an NE file and we got version numbers,
+ 0 if this file is an NE file and we couldn't get the version numbers,
+ -1 on error.
+
+ NB. buf is passed into and freed inside this function. This is a
+ bad API design, but fixing this is a task for another day.
+****************************************************************************/
+
+static int handle_ne_file(files_struct *fsp,
+ off_t in_pos,
+ char *fname,
+ char *buf,
+ uint32_t *major,
+ uint32_t *minor)
+{
+ unsigned int i;
+ ssize_t byte_count;
+ int ret = -1;
+
+ if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
+ DBG_NOTICE("NE file [%s] wrong target OS = 0x%x\n",
+ fname,
+ CVAL(buf,NE_HEADER_TARGET_OS_OFFSET));
+ /*
+ * At this point, we assume the file is in error.
+ * It still could be something else besides a NE file,
+ * but it unlikely at this point.
+ */
+ goto out;
+ }
+
+ /* Allocate a bit more space to speed up things */
+ SAFE_FREE(buf);
+ buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE);
+ if (buf == NULL) {
+ DBG_ERR("NE file [%s] malloc failed bytes = %d\n",
+ fname,
+ PE_HEADER_SIZE);
+ goto out;
+ }
+
+ /*
+ * This is a HACK! I got tired of trying to sort through the
+ * messy 'NE' file format. If anyone wants to clean this up
+ * please have at it, but this works. 'NE' files will
+ * eventually fade away. JRR
+ */
+ byte_count = printing_pread_data(fsp, buf, &in_pos, VS_NE_BUF_SIZE);
+ while (byte_count > 0) {
+ /*
+ * Cover case that should not occur in a well
+ * formed 'NE' .dll file
+ */
+ if (byte_count-VS_VERSION_INFO_SIZE <= 0) {
+ break;
}
- /* This is a HACK! I got tired of trying to sort through the messy
- * 'NE' file format. If anyone wants to clean this up please have at
- * it, but this works. 'NE' files will eventually fade away. JRR */
- while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
- /* Cover case that should not occur in a well formed 'NE' .dll file */
- if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
-
- for(i=0; i<byte_count; i++) {
- /* Fast skip past data that can't possibly match */
- if (buf[i] != 'V') continue;
-
- /* Potential match data crosses buf boundry, move it to beginning
- * of buf, and fill the buf with as much as it will hold. */
- if (i>byte_count-VS_VERSION_INFO_SIZE) {
- int bc;
-
- memcpy(buf, &buf[i], byte_count-i);
- if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
- (byte_count-i))) < 0) {
-
- DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
- fname, errno));
- goto error_exit;
- }
+ for(i=0; i<byte_count; i++) {
+ /*
+ * Fast skip past data that can't
+ * possibly match
+ */
+ if (buf[i] != 'V') {
+ byte_count = printing_pread_data(fsp,
+ buf,
+ &in_pos,
+ VS_NE_BUF_SIZE);
+ continue;
+ }
- byte_count = bc + (byte_count - i);
- if (byte_count<VS_VERSION_INFO_SIZE) break;
+ /*
+ * Potential match data crosses buf boundry,
+ * move it to beginning of buf, and fill the
+ * buf with as much as it will hold.
+ */
+ if (i>byte_count-VS_VERSION_INFO_SIZE) {
+ ssize_t amount_read;
+ ssize_t amount_unused = byte_count-i;
+
+ memmove(buf, &buf[i], amount_unused);
+ amount_read = printing_pread_data(fsp,
+ &buf[amount_unused],
+ &in_pos,
+ VS_NE_BUF_SIZE- amount_unused);
+ if (amount_read < 0) {
+ DBG_ERR("NE file [%s] Read "
+ "error, errno=%d\n",
+ fname,
+ errno);
+ goto out;
+ }
+
+ if (amount_read + amount_unused <
+ amount_read) {
+ /* Check for integer wrap. */
+ break;
+ }
- i = 0;
+ byte_count = amount_read +
+ amount_unused;
+ if (byte_count < VS_VERSION_INFO_SIZE) {
+ break;
}
- /* Check that the full signature string and the magic number that
- * follows exist (not a perfect solution, but the chances that this
- * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
- * twice, as it is simpler to read the code. */
- if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
- /* Compute skip alignment to next long address */
- int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
- sizeof(VS_SIGNATURE)) & 3;
- if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
-
- *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
- *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
- DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
- fname, *major, *minor,
- (*major>>16)&0xffff, *major&0xffff,
- (*minor>>16)&0xffff, *minor&0xffff));
- SAFE_FREE(buf);
- return 1;
+ i = 0;
+ }
+
+ /*
+ * Check that the full signature string and
+ * the magic number that follows exist (not
+ * a perfect solution, but the chances that this
+ * occurs in code is, well, remote. Yes I know
+ * I'm comparing the 'V' twice, as it is
+ * simpler to read the code.
+ */
+ if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
+ /*
+ * Compute skip alignment to next
+ * long address.
+ */
+ off_t cpos = in_pos;
+ int skip = -(cpos - (byte_count - i) +
+ sizeof(VS_SIGNATURE)) & 3;
+ if (IVAL(buf,
+ i+sizeof(VS_SIGNATURE)+skip)
+ != 0xfeef04bd) {
+ byte_count = printing_pread_data(fsp,
+ buf,
+ &in_pos,
+ VS_NE_BUF_SIZE);
+ continue;
}
+
+ *major = IVAL(buf,
+ i+sizeof(VS_SIGNATURE)+
+ skip+VS_MAJOR_OFFSET);
+ *minor = IVAL(buf,
+ i+sizeof(VS_SIGNATURE)+
+ skip+VS_MINOR_OFFSET);
+ DBG_INFO("NE file [%s] Version "
+ "= %08x:%08x (%d.%d.%d.%d)\n",
+ fname,
+ *major,
+ *minor,
+ (*major>>16)&0xffff,
+ *major&0xffff,
+ (*minor>>16)&0xffff,
+ *minor&0xffff);
+ ret = 1;
+ goto out;
}
}
+ }
- /* Version info not found, fall back to origin date/time */
- DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
- SAFE_FREE(buf);
- return 0;
+ /* Version info not found, fall back to origin date/time */
+ DBG_ERR("NE file [%s] Version info not found\n", fname);
+ ret = 0;
+
+ out:
+
+ SAFE_FREE(buf);
+ return ret;
+}
+
+/****************************************************************************
+ Version information in Microsoft files is held in a VS_VERSION_INFO structure.
+ There are two case to be covered here: PE (Portable Executable) and NE (New
+ Executable) files. Both files support the same INFO structure, but PE files
+ store the signature in unicode, and NE files store it as !unicode.
+ returns -1 on error, 1 on version info found, and 0 on no version info found.
+****************************************************************************/
+
+static int get_file_version(files_struct *fsp,
+ char *fname,
+ uint32_t *major,
+ uint32_t *minor)
+{
+ char *buf = NULL;
+ ssize_t byte_count;
+ off_t in_pos = fsp->fh->pos;
+
+ buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE);
+ if (buf == NULL) {
+ DBG_ERR("PE file [%s] DOS Header malloc failed bytes = %d\n",
+ fname,
+ DOS_HEADER_SIZE);
+ goto error_exit;
+ }
+
+ byte_count = printing_pread_data(fsp, buf, &in_pos, DOS_HEADER_SIZE);
+ if (byte_count < DOS_HEADER_SIZE) {
+ DBG_NOTICE("File [%s] DOS header too short, bytes read = %lu\n",
+ fname,
+ (unsigned long)byte_count);
+ goto no_version_info;
+ }
+
+ /* Is this really a DOS header? */
+ if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
+ DBG_INFO("File [%s] bad DOS magic = 0x%x\n",
+ fname,
+ SVAL(buf,DOS_HEADER_MAGIC_OFFSET));
+ goto no_version_info;
+ }
- } else
- /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
- DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
- fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
+ /*
+ * Skip OEM header (if any) and the
+ * DOS stub to start of Windows header.
+ */
+ in_pos = SVAL(buf,DOS_HEADER_LFANEW_OFFSET);
+
+ /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
+ byte_count = printing_pread_data(fsp, buf, &in_pos, NE_HEADER_SIZE);
+ if (byte_count < NE_HEADER_SIZE) {
+ DBG_NOTICE("File [%s] Windows header too short, "
+ "bytes read = %lu\n",
+ fname,
+ (unsigned long)byte_count);
+ /*
+ * Assume this isn't an error...
+ * the file just looks sort of like a PE/NE file
+ */
+ goto no_version_info;
+ }
+
+ /*
+ * The header may be a PE (Portable Executable)
+ * or an NE (New Executable).
+ */
+ if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
+ return handle_pe_file(fsp,
+ in_pos,
+ fname,
+ buf,
+ major,
+ minor);
+ } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) ==
+ NE_HEADER_SIGNATURE) {
+ return handle_ne_file(fsp,
+ in_pos,
+ fname,
+ buf,
+ major,
+ minor);
+ } else {
+ /*
+ * Assume this isn't an error... the file just
+ * looks sort of like a PE/NE file.
+ */
+ DBG_NOTICE("File [%s] unknown file format, signature = 0x%x\n",
+ fname,
+ IVAL(buf,PE_HEADER_SIGNATURE_OFFSET));
+ /* Fallthrough into no_version_info: */
+ }
no_version_info:
SAFE_FREE(buf);
{
bool use_version = true;
- uint32 new_major;
- uint32 new_minor;
+ uint32_t new_major;
+ uint32_t new_minor;
time_t new_create_time;
- uint32 old_major;
- uint32 old_minor;
+ uint32_t old_major;
+ uint32_t old_minor;
time_t old_create_time;
struct smb_filename *smb_fname = NULL;
0, /* create_options */
FILE_ATTRIBUTE_NORMAL, /* file_attributes */
INTERNAL_OPEN_ONLY, /* oplock_request */
+ NULL, /* lease */
0, /* allocation_size */
0, /* private_flags */
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- NULL); /* pinfo */
+ NULL, /* pinfo */
+ NULL, NULL); /* create context */
if (!NT_STATUS_IS_OK(status)) {
/* Old file not found, so by definition new file is in fact newer */
0, /* create_options */
FILE_ATTRIBUTE_NORMAL, /* file_attributes */
INTERNAL_OPEN_ONLY, /* oplock_request */
+ NULL, /* lease */
0, /* allocation_size */
0, /* private_flags */
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- NULL); /* pinfo */
+ NULL, /* pinfo */
+ NULL, NULL); /* create context */
if (!NT_STATUS_IS_OK(status)) {
/* New file not found, this shouldn't occur if the caller did its job */
/****************************************************************************
Determine the correct cVersion associated with an architecture and driver
****************************************************************************/
-static uint32 get_correct_cversion(struct auth_session_info *session_info,
+static uint32_t get_correct_cversion(const struct auth_session_info *session_info,
const char *architecture,
const char *driverpath_in,
+ const char *driver_directory,
WERROR *perr)
{
+ TALLOC_CTX *frame = talloc_stackframe();
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
int cversion = -1;
NTSTATUS nt_status;
struct smb_filename *smb_fname = NULL;
- char *driverpath = NULL;
files_struct *fsp = NULL;
+ struct conn_struct_tos *c = NULL;
connection_struct *conn = NULL;
- char *oldcwd;
char *printdollar = NULL;
+ char *printdollar_path = NULL;
+ char *working_dir = NULL;
int printdollar_snum;
- *perr = WERR_INVALID_PARAM;
+ *perr = WERR_INVALID_PARAMETER;
/* If architecture is Windows 95/98/ME, the version is always 0. */
if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
*perr = WERR_OK;
+ TALLOC_FREE(frame);
return 0;
}
if (strcmp(architecture, SPL_ARCH_X64) == 0) {
DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
*perr = WERR_OK;
+ TALLOC_FREE(frame);
return 3;
}
- printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
+ printdollar_snum = find_service(frame, "print$", &printdollar);
if (!printdollar) {
- *perr = WERR_NOMEM;
+ *perr = WERR_NOT_ENOUGH_MEMORY;
+ TALLOC_FREE(frame);
return -1;
}
if (printdollar_snum == -1) {
- *perr = WERR_NO_SUCH_SHARE;
+ *perr = WERR_BAD_NET_NAME;
+ TALLOC_FREE(frame);
+ return -1;
+ }
+
+ printdollar_path = lp_path(frame, lp_sub, printdollar_snum);
+ if (printdollar_path == NULL) {
+ *perr = WERR_NOT_ENOUGH_MEMORY;
+ TALLOC_FREE(frame);
return -1;
}
- nt_status = create_conn_struct(talloc_tos(),
- server_event_context(),
- server_messaging_context(),
- &conn,
- printdollar_snum,
- lp_pathname(talloc_tos(), printdollar_snum),
- session_info, &oldcwd);
+ working_dir = talloc_asprintf(frame,
+ "%s/%s",
+ printdollar_path,
+ architecture);
+ /*
+ * If the driver has been uploaded into a temorpary driver
+ * directory, switch to the driver directory.
+ */
+ if (driver_directory != NULL) {
+ working_dir = talloc_asprintf(frame, "%s/%s/%s",
+ printdollar_path,
+ architecture,
+ driver_directory);
+ }
+
+ nt_status = create_conn_struct_tos_cwd(global_messaging_context(),
+ printdollar_snum,
+ working_dir,
+ session_info,
+ &c);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0,("get_correct_cversion: create_conn_struct "
"returned %s\n", nt_errstr(nt_status)));
*perr = ntstatus_to_werror(nt_status);
+ TALLOC_FREE(frame);
return -1;
}
+ conn = c->conn;
nt_status = set_conn_force_user_group(conn, printdollar_snum);
if (!NT_STATUS_IS_OK(nt_status)) {
goto error_free_conn;
}
- if (!become_user_by_session(conn, session_info)) {
+ if (!become_user_without_service_by_session(conn, session_info)) {
DEBUG(0, ("failed to become user\n"));
*perr = WERR_ACCESS_DENIED;
goto error_free_conn;
}
- /* 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);
+ /*
+ * We switch to the directory where the driver files are located,
+ * so only work on the file names
+ */
+ 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;
nt_status = vfs_file_exist(conn, smb_fname);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(3,("get_correct_cversion: vfs_file_exist failed\n"));
- *perr = WERR_BADFILE;
+ *perr = WERR_FILE_NOT_FOUND;
goto error_exit;
}
0, /* create_options */
FILE_ATTRIBUTE_NORMAL, /* file_attributes */
INTERNAL_OPEN_ONLY, /* oplock_request */
+ NULL, /* lease */
0, /* private_flags */
0, /* allocation_size */
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- NULL); /* pinfo */
+ NULL, /* pinfo */
+ NULL, NULL); /* create context */
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
*perr = WERR_ACCESS_DENIED;
goto error_exit;
} else {
- uint32 major;
- uint32 minor;
+ uint32_t major;
+ uint32_t minor;
int ret;
ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
if (ret == -1) {
- *perr = WERR_INVALID_PARAM;
+ *perr = WERR_INVALID_PARAMETER;
goto error_exit;
} else if (!ret) {
DEBUG(6,("get_correct_cversion: Version info not "
"found [%s]\n",
smb_fname_str_dbg(smb_fname)));
- *perr = WERR_INVALID_PARAM;
+ *perr = WERR_INVALID_PARAMETER;
goto error_exit;
}
*perr = WERR_OK;
error_exit:
- unbecome_user();
+ unbecome_user_without_service();
error_free_conn:
- TALLOC_FREE(smb_fname);
if (fsp != NULL) {
close_file(NULL, fsp, NORMAL_CLOSE);
}
- if (conn != NULL) {
- vfs_ChDir(conn, oldcwd);
- SMB_VFS_DISCONNECT(conn);
- conn_free(conn);
- }
if (!W_ERROR_IS_OK(*perr)) {
cversion = -1;
}
+ TALLOC_FREE(frame);
return cversion;
}
} while (0);
static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
- struct auth_session_info *session_info,
+ const struct auth_session_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)
+ enum spoolss_DriverOSVersion *version,
+ uint32_t flags,
+ const char **driver_directory)
{
const char *short_architecture;
int i;
char *_p;
if (!*driver_path || !*data_file) {
- return WERR_INVALID_PARAM;
+ return WERR_INVALID_PARAMETER;
}
if (!strequal(architecture, SPOOLSS_ARCHITECTURE_4_0) && !*config_file) {
- return WERR_INVALID_PARAM;
+ return WERR_INVALID_PARAMETER;
+ }
+
+ if (flags & APD_COPY_FROM_DIRECTORY) {
+ char *path;
+ char *q;
+
+ /*
+ * driver_path is set to:
+ *
+ * \\PRINTSRV\print$\x64\{279245b0-a8bd-4431-bf6f-baee92ac15c0}\pscript5.dll
+ */
+ path = talloc_strdup(mem_ctx, *driver_path);
+ if (path == NULL) {
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+
+ /* Remove pscript5.dll */
+ q = strrchr_m(path, '\\');
+ if (q == NULL) {
+ return WERR_INVALID_PARAMETER;
+ }
+ *q = '\0';
+
+ /* Get \{279245b0-a8bd-4431-bf6f-baee92ac15c0} */
+ q = strrchr_m(path, '\\');
+ if (q == NULL) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ /*
+ * Set driver_directory to:
+ *
+ * {279245b0-a8bd-4431-bf6f-baee92ac15c0}
+ *
+ * This is the directory where all the files have been uploaded
+ */
+ *driver_directory = q + 1;
}
/* clean up the driver name.
* NT2K: cversion=3
*/
- *version = get_correct_cversion(session_info, short_architecture,
- *driver_path, &err);
+ *version = get_correct_cversion(session_info,
+ short_architecture,
+ *driver_path,
+ *driver_directory,
+ &err);
if (*version == -1) {
return err;
}
****************************************************************************/
WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
- struct auth_session_info *session_info,
- struct spoolss_AddDriverInfoCtr *r)
+ const struct auth_session_info *session_info,
+ const struct spoolss_AddDriverInfoCtr *r,
+ uint32_t flags,
+ const char **driver_directory)
{
switch (r->level) {
case 3:
&r->info.info3->config_file,
&r->info.info3->help_file,
r->info.info3->dependent_files,
- &r->info.info3->version);
+ &r->info.info3->version,
+ flags,
+ driver_directory);
case 6:
return clean_up_driver_struct_level(mem_ctx, session_info,
r->info.info6->architecture,
&r->info.info6->config_file,
&r->info.info6->help_file,
r->info.info6->dependent_files,
- &r->info.info6->version);
+ &r->info.info6->version,
+ flags,
+ driver_directory);
+ case 8:
+ return clean_up_driver_struct_level(mem_ctx, session_info,
+ r->info.info8->architecture,
+ &r->info.info8->driver_path,
+ &r->info.info8->data_file,
+ &r->info.info8->config_file,
+ &r->info.info8->help_file,
+ r->info.info8->dependent_files,
+ &r->info.info8->version,
+ flags,
+ driver_directory);
default:
return WERR_NOT_SUPPORTED;
}
dst->dependent_files = src->dependent_files;
}
+static void convert_level_8_to_level3(struct spoolss_AddDriverInfo3 *dst,
+ const struct spoolss_AddDriverInfo8 *src)
+{
+ dst->version = src->version;
+
+ dst->driver_name = src->driver_name;
+ dst->architecture = src->architecture;
+ dst->driver_path = src->driver_path;
+ dst->data_file = src->data_file;
+ dst->config_file = src->config_file;
+ dst->help_file = src->help_file;
+ dst->monitor_name = src->monitor_name;
+ dst->default_datatype = src->default_datatype;
+ dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
+ dst->dependent_files = src->dependent_files;
+}
+
/****************************************************************************
****************************************************************************/
const char *driver_file,
const char *short_architecture,
uint32_t driver_version,
- uint32_t version)
+ uint32_t version,
+ const char *driver_directory)
{
struct smb_filename *smb_fname_old = NULL;
struct smb_filename *smb_fname_new = NULL;
NTSTATUS status;
WERROR ret;
- old_name = talloc_asprintf(mem_ctx, "%s/%s",
- short_architecture, driver_file);
- W_ERROR_HAVE_NO_MEMORY(old_name);
+ if (driver_directory != NULL) {
+ old_name = talloc_asprintf(mem_ctx,
+ "%s/%s/%s",
+ short_architecture,
+ driver_directory,
+ driver_file);
+ } else {
+ old_name = talloc_asprintf(mem_ctx,
+ "%s/%s",
+ short_architecture,
+ driver_file);
+ }
+ if (old_name == NULL) {
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
short_architecture, driver_version, driver_file);
if (new_name == NULL) {
TALLOC_FREE(old_name);
- return WERR_NOMEM;
+ return WERR_NOT_ENOUGH_MEMORY;
}
if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
status = driver_unix_convert(conn, old_name, &smb_fname_old);
if (!NT_STATUS_IS_OK(status)) {
- ret = WERR_NOMEM;
+ ret = WERR_NOT_ENOUGH_MEMORY;
goto out;
}
/* Setup a synthetic smb_filename struct */
smb_fname_new = talloc_zero(mem_ctx, struct smb_filename);
if (!smb_fname_new) {
- ret = WERR_NOMEM;
+ ret = WERR_NOT_ENOUGH_MEMORY;
goto out;
}
"to rename [%s] to [%s]: %s\n",
smb_fname_old->base_name, new_name,
nt_errstr(status)));
- ret = WERR_ACCESS_DENIED;
+ ret = WERR_APP_INIT_FAILURE;
goto out;
}
}
return ret;
}
-WERROR move_driver_to_download_area(struct auth_session_info *session_info,
- struct spoolss_AddDriverInfoCtr *r)
+WERROR move_driver_to_download_area(const struct auth_session_info *session_info,
+ const struct spoolss_AddDriverInfoCtr *r,
+ const char *driver_directory)
{
+ TALLOC_CTX *frame = talloc_stackframe();
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
struct spoolss_AddDriverInfo3 *driver;
struct spoolss_AddDriverInfo3 converted_driver;
const char *short_architecture;
struct smb_filename *smb_dname = NULL;
char *new_dir = NULL;
+ struct conn_struct_tos *c = NULL;
connection_struct *conn = NULL;
NTSTATUS nt_status;
int i;
- TALLOC_CTX *ctx = talloc_tos();
int ver = 0;
- char *oldcwd;
char *printdollar = NULL;
int printdollar_snum;
WERROR err = WERR_OK;
convert_level_6_to_level3(&converted_driver, r->info.info6);
driver = &converted_driver;
break;
+ case 8:
+ convert_level_8_to_level3(&converted_driver, r->info.info8);
+ driver = &converted_driver;
+ break;
default:
DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
- return WERR_UNKNOWN_LEVEL;
+ TALLOC_FREE(frame);
+ return WERR_INVALID_LEVEL;
}
short_architecture = get_short_archi(driver->architecture);
if (!short_architecture) {
+ TALLOC_FREE(frame);
return WERR_UNKNOWN_PRINTER_DRIVER;
}
- printdollar_snum = find_service(ctx, "print$", &printdollar);
+ printdollar_snum = find_service(frame, "print$", &printdollar);
if (!printdollar) {
- return WERR_NOMEM;
+ TALLOC_FREE(frame);
+ return WERR_NOT_ENOUGH_MEMORY;
}
if (printdollar_snum == -1) {
- return WERR_NO_SUCH_SHARE;
+ TALLOC_FREE(frame);
+ return WERR_BAD_NET_NAME;
}
- nt_status = create_conn_struct(talloc_tos(),
- server_event_context(),
- server_messaging_context(),
- &conn,
- printdollar_snum,
- lp_pathname(talloc_tos(), printdollar_snum),
- session_info, &oldcwd);
+ nt_status = create_conn_struct_tos_cwd(global_messaging_context(),
+ printdollar_snum,
+ lp_path(frame, lp_sub, printdollar_snum),
+ session_info,
+ &c);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0,("move_driver_to_download_area: create_conn_struct "
"returned %s\n", nt_errstr(nt_status)));
err = ntstatus_to_werror(nt_status);
+ TALLOC_FREE(frame);
return err;
}
+ conn = c->conn;
nt_status = set_conn_force_user_group(conn, printdollar_snum);
if (!NT_STATUS_IS_OK(nt_status)) {
goto err_free_conn;
}
- if (!become_user_by_session(conn, session_info)) {
+ if (!become_user_without_service_by_session(conn, session_info)) {
DEBUG(0, ("failed to become user\n"));
err = WERR_ACCESS_DENIED;
goto err_free_conn;
}
- new_dir = talloc_asprintf(ctx,
+ new_dir = talloc_asprintf(frame,
"%s/%d",
short_architecture,
driver->version);
if (!new_dir) {
- err = WERR_NOMEM;
+ err = WERR_NOT_ENOUGH_MEMORY;
goto err_exit;
}
nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
if (!NT_STATUS_IS_OK(nt_status)) {
- err = WERR_NOMEM;
+ err = WERR_NOT_ENOUGH_MEMORY;
goto err_exit;
}
if (driver->driver_path && strlen(driver->driver_path)) {
- err = move_driver_file_to_download_area(ctx,
+ err = move_driver_file_to_download_area(frame,
conn,
driver->driver_path,
short_architecture,
driver->version,
- ver);
+ ver,
+ driver_directory);
if (!W_ERROR_IS_OK(err)) {
goto err_exit;
}
if (driver->data_file && strlen(driver->data_file)) {
if (!strequal(driver->data_file, driver->driver_path)) {
- err = move_driver_file_to_download_area(ctx,
+ err = move_driver_file_to_download_area(frame,
conn,
driver->data_file,
short_architecture,
driver->version,
- ver);
+ ver,
+ driver_directory);
if (!W_ERROR_IS_OK(err)) {
goto err_exit;
}
if (!strequal(driver->config_file, driver->driver_path) &&
!strequal(driver->config_file, driver->data_file)) {
- err = move_driver_file_to_download_area(ctx,
+ err = move_driver_file_to_download_area(frame,
conn,
driver->config_file,
short_architecture,
driver->version,
- ver);
+ ver,
+ driver_directory);
if (!W_ERROR_IS_OK(err)) {
goto err_exit;
}
!strequal(driver->help_file, driver->data_file) &&
!strequal(driver->help_file, driver->config_file)) {
- err = move_driver_file_to_download_area(ctx,
+ err = move_driver_file_to_download_area(frame,
conn,
driver->help_file,
short_architecture,
driver->version,
- ver);
+ ver,
+ driver_directory);
if (!W_ERROR_IS_OK(err)) {
goto err_exit;
}
}
}
- err = move_driver_file_to_download_area(ctx,
+ err = move_driver_file_to_download_area(frame,
conn,
driver->dependent_files->string[i],
short_architecture,
driver->version,
- ver);
+ ver,
+ driver_directory);
if (!W_ERROR_IS_OK(err)) {
goto err_exit;
}
err = WERR_OK;
err_exit:
- unbecome_user();
+ unbecome_user_without_service();
err_free_conn:
- TALLOC_FREE(smb_dname);
-
- if (conn != NULL) {
- vfs_ChDir(conn, oldcwd);
- SMB_VFS_DISCONNECT(conn);
- conn_free(conn);
- }
-
+ TALLOC_FREE(frame);
return err;
}
struct dcerpc_binding_handle *b,
const struct spoolss_DriverInfo8 *r)
{
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
int snum;
int n_services = lp_numservices();
- bool in_use = False;
+ bool in_use = false;
struct spoolss_PrinterInfo2 *pinfo2 = NULL;
WERROR result;
/* loop through the printers.tdb and check for the drivername */
for (snum=0; snum<n_services && !in_use; snum++) {
- if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
+ if (!lp_snum_ok(snum) || !lp_printable(snum)) {
continue;
}
result = winreg_get_printer(mem_ctx, b,
- lp_servicename(talloc_tos(), snum),
+ lp_servicename(talloc_tos(), lp_sub, snum),
&pinfo2);
if (!W_ERROR_IS_OK(result)) {
continue; /* skip */
}
if (strequal(r->driver_name, pinfo2->drivername)) {
- in_use = True;
+ in_use = true;
}
TALLOC_FREE(pinfo2);
/* we can still remove the driver if there is one of
"Windows NT x86" version 2 or 3 left */
- if (!strequal("Windows NT x86", r->architecture)) {
+ if (strequal(SPOOLSS_ARCHITECTURE_NT_X86, r->architecture)) {
+ if (r->version == 2) {
+ werr = winreg_get_driver(mem_ctx, b,
+ r->architecture,
+ r->driver_name,
+ 3, &driver);
+ } else if (r->version == 3) {
+ werr = winreg_get_driver(mem_ctx, b,
+ r->architecture,
+ r->driver_name,
+ 2, &driver);
+ } else {
+ DBG_ERR("Unknown driver version (%d)\n",
+ r->version);
+ werr = WERR_UNKNOWN_PRINTER_DRIVER;
+ }
+ } else if (strequal(SPOOLSS_ARCHITECTURE_x64, r->architecture)) {
werr = winreg_get_driver(mem_ctx, b,
- "Windows NT x86",
+ SPOOLSS_ARCHITECTURE_NT_X86,
r->driver_name,
DRIVER_ANY_VERSION,
&driver);
- } else if (r->version == 2) {
- werr = winreg_get_driver(mem_ctx, b,
- "Windows NT x86",
- r->driver_name,
- 3, &driver);
- } else if (r->version == 3) {
- werr = winreg_get_driver(mem_ctx, b,
- "Windows NT x86",
- r->driver_name,
- 2, &driver);
} else {
- DEBUG(0, ("printer_driver_in_use: ERROR!"
- " unknown driver version (%d)\n",
- r->version));
+ DBG_ERR("Unknown driver architecture: %s\n",
+ r->architecture);
werr = WERR_UNKNOWN_PRINTER_DRIVER;
}
if ( W_ERROR_IS_OK(werr) ) {
/* it's ok to remove the driver, we have other architctures left */
- in_use = False;
+ in_use = false;
talloc_free(driver);
}
}
struct spoolss_DriverInfo8 *info)
{
int i;
- uint32 version;
+ uint32_t version;
struct spoolss_DriverInfo8 *driver;
bool in_use = false;
uint32_t num_drivers;
goto err_out;
}
- status = create_synthetic_smb_fname(tmp_ctx, print_dlr_path,
- NULL, NULL, &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
+ smb_fname = synthetic_smb_fname(tmp_ctx,
+ print_dlr_path,
+ NULL,
+ NULL,
+ 0,
+ 0);
+ if (smb_fname == NULL) {
goto err_out;
}
bool delete_driver_files(const struct auth_session_info *session_info,
const struct spoolss_DriverInfo8 *r)
{
+ TALLOC_CTX *frame = talloc_stackframe();
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
const char *short_arch;
- connection_struct *conn;
+ struct conn_struct_tos *c = NULL;
+ connection_struct *conn = NULL;
NTSTATUS nt_status;
- char *oldcwd;
char *printdollar = NULL;
int printdollar_snum;
bool ret = false;
if (!r) {
+ TALLOC_FREE(frame);
return false;
}
DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
r->driver_name, r->version));
- printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
+ printdollar_snum = find_service(frame, "print$", &printdollar);
if (!printdollar) {
+ TALLOC_FREE(frame);
return false;
}
if (printdollar_snum == -1) {
+ TALLOC_FREE(frame);
return false;
}
- nt_status = create_conn_struct(talloc_tos(),
- server_event_context(),
- server_messaging_context(),
- &conn,
- printdollar_snum,
- lp_pathname(talloc_tos(), printdollar_snum),
- session_info, &oldcwd);
+ nt_status = create_conn_struct_tos_cwd(global_messaging_context(),
+ printdollar_snum,
+ lp_path(frame, lp_sub, printdollar_snum),
+ session_info,
+ &c);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0,("delete_driver_files: create_conn_struct "
"returned %s\n", nt_errstr(nt_status)));
+ TALLOC_FREE(frame);
return false;
}
+ conn = c->conn;
nt_status = set_conn_force_user_group(conn, printdollar_snum);
if (!NT_STATUS_IS_OK(nt_status)) {
goto err_free_conn;
}
- if (!become_user_by_session(conn, session_info)) {
+ if (!become_user_without_service_by_session(conn, session_info)) {
DEBUG(0, ("failed to become user\n"));
ret = false;
goto err_free_conn;
ret = true;
err_out:
- unbecome_user();
+ unbecome_user_without_service();
err_free_conn:
- if (conn != NULL) {
- vfs_ChDir(conn, oldcwd);
- SMB_VFS_DISCONNECT(conn);
- conn_free(conn);
- }
+ TALLOC_FREE(frame);
return ret;
}
3) "printer admins" (may result in numerous calls to winbind)
****************************************************************************/
-bool print_access_check(const struct auth_session_info *session_info,
- struct messaging_context *msg_ctx, int snum,
- int access_type)
+WERROR print_access_check(const struct auth_session_info *session_info,
+ struct messaging_context *msg_ctx, int snum,
+ int access_type)
{
struct spoolss_security_descriptor *secdesc = NULL;
- uint32 access_granted;
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
+ uint32_t access_granted;
size_t sd_size;
NTSTATUS status;
WERROR result;
/* Always allow root or SE_PRINT_OPERATROR to do anything */
- if (session_info->unix_token->uid == sec_initial_uid()
- || security_token_has_privilege(session_info->security_token, SEC_PRIV_PRINT_OPERATOR)) {
- return True;
+ if ((session_info->unix_token->uid == sec_initial_uid())
+ || security_token_has_privilege(session_info->security_token,
+ SEC_PRIV_PRINT_OPERATOR)) {
+ return WERR_OK;
}
/* Get printer name */
- pname = lp_printername(talloc_tos(), snum);
+ pname = lp_printername(talloc_tos(), lp_sub, snum);
if (!pname || !*pname) {
- errno = EACCES;
- return False;
+ return WERR_ACCESS_DENIED;
}
/* Get printer security descriptor */
if(!(mem_ctx = talloc_init("print_access_check"))) {
- errno = ENOMEM;
- return False;
+ return WERR_NOT_ENOUGH_MEMORY;
}
result = winreg_get_printer_secdesc_internal(mem_ctx,
&secdesc);
if (!W_ERROR_IS_OK(result)) {
talloc_destroy(mem_ctx);
- errno = ENOMEM;
- return False;
+ return WERR_NOT_ENOUGH_MEMORY;
}
if (access_type == JOB_ACCESS_ADMINISTER) {
false);
if (!NT_STATUS_IS_OK(status)) {
talloc_destroy(mem_ctx);
- errno = map_errno_from_nt_status(status);
- return False;
+ return ntstatus_to_werror(status);
}
map_job_permissions(secdesc);
talloc_destroy(mem_ctx);
- if (!NT_STATUS_IS_OK(status)) {
- errno = EACCES;
- }
-
- return NT_STATUS_IS_OK(status);
+ return ntstatus_to_werror(status);
}
/****************************************************************************
bool ok = False;
time_t now = time(NULL);
struct tm *t;
- uint32 mins;
+ uint32_t mins;
result = winreg_get_printer_internal(NULL, session_info, msg_ctx,
servicename, &pinfo2);
}
t = gmtime(&now);
- mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
+ mins = (uint32_t)t->tm_hour*60 + (uint32_t)t->tm_min;
if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
ok = True;