LCOV - code coverage report
Current view: top level - source3/printing - nt_printing.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 92 1044 8.8 %
Date: 2024-04-13 12:30:31 Functions: 6 30 20.0 %

          Line data    Source code
       1             : /*
       2             :  *  Unix SMB/CIFS implementation.
       3             :  *  RPC Pipe client / server routines
       4             :  *  Copyright (C) Andrew Tridgell              1992-2000,
       5             :  *  Copyright (C) Jean François Micouleau      1998-2000.
       6             :  *  Copyright (C) Gerald Carter                2002-2005.
       7             :  *
       8             :  *  This program is free software; you can redistribute it and/or modify
       9             :  *  it under the terms of the GNU General Public License as published by
      10             :  *  the Free Software Foundation; either version 3 of the License, or
      11             :  *  (at your option) any later version.
      12             :  *
      13             :  *  This program is distributed in the hope that it will be useful,
      14             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :  *  GNU General Public License for more details.
      17             :  *
      18             :  *  You should have received a copy of the GNU General Public License
      19             :  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
      20             :  */
      21             : 
      22             : #include "includes.h"
      23             : #include "printing/nt_printing_tdb.h"
      24             : #include "printing/queue_process.h"
      25             : #include "../librpc/gen_ndr/ndr_spoolss.h"
      26             : #include "rpc_server/spoolss/srv_spoolss_util.h"
      27             : #include "nt_printing.h"
      28             : #include "secrets.h"
      29             : #include "../librpc/gen_ndr/netlogon.h"
      30             : #include "../libcli/security/security.h"
      31             : #include "passdb/machine_sid.h"
      32             : #include "smbd/smbd.h"
      33             : #include "auth.h"
      34             : #include "messages.h"
      35             : #include "rpc_server/spoolss/srv_spoolss_nt.h"
      36             : #include "rpc_client/cli_winreg_spoolss.h"
      37             : #include "lib/util/string_wrappers.h"
      38             : #include "lib/global_contexts.h"
      39             : 
      40             : /* Map generic permissions to printer object specific permissions */
      41             : 
      42             : const struct generic_mapping printer_generic_mapping = {
      43             :         PRINTER_READ,
      44             :         PRINTER_WRITE,
      45             :         PRINTER_EXECUTE,
      46             :         PRINTER_ALL_ACCESS
      47             : };
      48             : 
      49             : /* Map generic permissions to print server object specific permissions */
      50             : 
      51             : const struct generic_mapping printserver_generic_mapping = {
      52             :         SERVER_READ,
      53             :         SERVER_WRITE,
      54             :         SERVER_EXECUTE,
      55             :         SERVER_ALL_ACCESS
      56             : };
      57             : 
      58             : /* Map generic permissions to job object specific permissions */
      59             : 
      60             : const struct generic_mapping job_generic_mapping = {
      61             :         JOB_READ,
      62             :         JOB_WRITE,
      63             :         JOB_EXECUTE,
      64             :         JOB_ALL_ACCESS
      65             : };
      66             : 
      67          28 : static bool print_driver_directories_init(void)
      68             : {
      69           0 :         int service;
      70           0 :         size_t i;
      71           0 :         char *driver_path;
      72           0 :         bool ok;
      73          28 :         TALLOC_CTX *mem_ctx = talloc_stackframe();
      74           0 :         const struct loadparm_substitution *lp_sub =
      75          28 :                 loadparm_s3_global_substitution();
      76             : 
      77          28 :         const char *dir_list[] = {
      78             :                 "W32X86/PCC",
      79             :                 "x64/PCC",
      80             :                 "ARM64",
      81             :                 "color"
      82             :         };
      83             : 
      84          28 :         service = lp_servicenumber("print$");
      85          28 :         if (service < 0) {
      86             :                 /* We don't have a print$ share */
      87           0 :                 DEBUG(5, ("No print$ share has been configured.\n"));
      88           0 :                 talloc_free(mem_ctx);
      89           0 :                 return true;
      90             :         }
      91             : 
      92          28 :         driver_path = lp_path(mem_ctx, lp_sub, service);
      93          28 :         if (driver_path == NULL) {
      94           0 :                 talloc_free(mem_ctx);
      95           0 :                 return false;
      96             :         }
      97             : 
      98          28 :         ok = directory_create_or_exist(driver_path, 0755);
      99          28 :         if (!ok) {
     100           0 :                 DEBUG(1, ("Failed to create printer driver directory %s\n",
     101             :                           driver_path));
     102           0 :                 talloc_free(mem_ctx);
     103           0 :                 return false;
     104             :         }
     105             : 
     106         280 :         for (i = 0; archi_table[i].long_archi != NULL; i++) {
     107           0 :                 const char *arch_path;
     108             : 
     109         252 :                 arch_path = talloc_asprintf(mem_ctx,
     110             :                                             "%s/%s",
     111             :                                             driver_path,
     112         252 :                                             archi_table[i].short_archi);
     113         252 :                 if (arch_path == NULL) {
     114           0 :                         talloc_free(mem_ctx);
     115           0 :                         return false;
     116             :                 }
     117             : 
     118         252 :                 ok = directory_create_or_exist(arch_path, 0755);
     119         252 :                 if (!ok) {
     120           0 :                         DEBUG(1, ("Failed to create printer driver "
     121             :                                   "architecture directory %s\n",
     122             :                                   arch_path));
     123           0 :                         talloc_free(mem_ctx);
     124           0 :                         return false;
     125             :                 }
     126             :         }
     127             : 
     128         140 :         for (i = 0; i < ARRAY_SIZE(dir_list); i++) {
     129           0 :                 const char *path;
     130             : 
     131         112 :                 path = talloc_asprintf(mem_ctx,
     132             :                                        "%s/%s",
     133             :                                        driver_path,
     134             :                                        dir_list[i]);
     135         112 :                 if (path == NULL) {
     136           0 :                         talloc_free(mem_ctx);
     137           0 :                         return false;
     138             :                 }
     139             : 
     140         112 :                 ok = directory_create_or_exist(path, 0755);
     141         112 :                 if (!ok) {
     142           0 :                         DEBUG(1, ("Failed to create printer driver "
     143             :                                   "architecture directory %s\n",
     144             :                                   path));
     145           0 :                         talloc_free(mem_ctx);
     146           0 :                         return false;
     147             :                 }
     148             :         }
     149             : 
     150          28 :         driver_path = state_path(talloc_tos(), "DriverStore");
     151          28 :         if (driver_path == NULL) {
     152           0 :                 talloc_free(mem_ctx);
     153           0 :                 return false;
     154             :         }
     155             : 
     156          28 :         ok = directory_create_or_exist(driver_path, 0755);
     157          28 :         if (!ok) {
     158           0 :                 DEBUG(1,("failed to create path %s\n", driver_path));
     159           0 :                 talloc_free(mem_ctx);
     160           0 :                 return false;
     161             :         }
     162             : 
     163          28 :         driver_path = state_path(talloc_tos(), "DriverStore/FileRepository");
     164          28 :         if (driver_path == NULL) {
     165           0 :                 talloc_free(mem_ctx);
     166           0 :                 return false;
     167             :         }
     168             : 
     169          28 :         ok = directory_create_or_exist(driver_path, 0755);
     170          28 :         if (!ok) {
     171           0 :                 DEBUG(1,("failed to create path %s\n", driver_path));
     172           0 :                 talloc_free(mem_ctx);
     173           0 :                 return false;
     174             :         }
     175             : 
     176          28 :         driver_path = state_path(talloc_tos(), "DriverStore/Temp");
     177          28 :         if (driver_path == NULL) {
     178           0 :                 talloc_free(mem_ctx);
     179           0 :                 return false;
     180             :         }
     181             : 
     182          28 :         ok = directory_create_or_exist(driver_path, 0755);
     183          28 :         if (!ok) {
     184           0 :                 DEBUG(1,("failed to create path %s\n", driver_path));
     185           0 :                 talloc_free(mem_ctx);
     186           0 :                 return false;
     187             :         }
     188             : 
     189          28 :         talloc_free(mem_ctx);
     190          28 :         return true;
     191             : }
     192             : 
     193             : /****************************************************************************
     194             :  Forward a MSG_PRINTER_DRVUPGRADE message from another smbd to the
     195             :  background lpq updater.
     196             : ****************************************************************************/
     197             : 
     198           0 : static void forward_drv_upgrade_printer_msg(struct messaging_context *msg,
     199             :                                 void *private_data,
     200             :                                 uint32_t msg_type,
     201             :                                 struct server_id server_id,
     202             :                                 DATA_BLOB *data)
     203             : {
     204           0 :         send_to_bgqd(msg, msg_type, data->data, data->length);
     205           0 : }
     206             : 
     207             : /****************************************************************************
     208             :  Open the NT printing tdbs. Done once before fork().
     209             : ****************************************************************************/
     210             : 
     211          28 : bool nt_printing_init(struct messaging_context *msg_ctx)
     212             : {
     213           0 :         WERROR win_rc;
     214             : 
     215          28 :         if (!print_driver_directories_init()) {
     216           0 :                 return false;
     217             :         }
     218             : 
     219          28 :         if (!nt_printing_tdb_upgrade()) {
     220           0 :                 return false;
     221             :         }
     222             : 
     223             :         /*
     224             :          * register callback to handle updating printers as new
     225             :          * drivers are installed. Forwards to background lpq updater.
     226             :          */
     227          28 :         messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
     228             :                         forward_drv_upgrade_printer_msg);
     229             : 
     230          28 :         if ( lp_security() == SEC_ADS ) {
     231           2 :                 win_rc = check_published_printers(msg_ctx);
     232           2 :                 if (!W_ERROR_IS_OK(win_rc))
     233           0 :                         DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
     234             :         }
     235             : 
     236          28 :         return true;
     237             : }
     238             : 
     239             : /*******************************************************************
     240             :  Function to allow filename parsing "the old way".
     241             : ********************************************************************/
     242             : 
     243           0 : static NTSTATUS driver_unix_convert(connection_struct *conn,
     244             :                                     const char *old_name,
     245             :                                     struct files_struct **pdirfsp,
     246             :                                     struct smb_filename **psmb_fname)
     247             : {
     248           0 :         NTSTATUS status;
     249           0 :         TALLOC_CTX *ctx = talloc_tos();
     250           0 :         char *name = talloc_strdup(ctx, old_name);
     251             : 
     252           0 :         if (!name) {
     253           0 :                 return NT_STATUS_NO_MEMORY;
     254             :         }
     255           0 :         unix_format(name);
     256           0 :         name = unix_clean_name(ctx, name);
     257           0 :         if (!name) {
     258           0 :                 return NT_STATUS_NO_MEMORY;
     259             :         }
     260           0 :         trim_string(name,"/","/");
     261             : 
     262           0 :         status = filename_convert_dirfsp(ctx,
     263             :                                          conn,
     264             :                                          name,
     265             :                                          0, /* ucf_flags */
     266             :                                          0, /* twrp */
     267             :                                          pdirfsp,
     268             :                                          psmb_fname);
     269           0 :         if (!NT_STATUS_IS_OK(status)) {
     270           0 :                 return status;
     271             :         }
     272             : 
     273           0 :         return NT_STATUS_OK;
     274             : }
     275             : 
     276             : /****************************************************************************
     277             :  Function to do the mapping between the long architecture name and
     278             :  the short one.
     279             : ****************************************************************************/
     280             : 
     281         256 : const char *get_short_archi(const char *long_archi)
     282             : {
     283         256 :         int i=-1;
     284             : 
     285         256 :         DEBUG(107,("Getting architecture dependent directory\n"));
     286           0 :         do {
     287        1656 :                 i++;
     288        1908 :         } while ( (archi_table[i].long_archi!=NULL ) &&
     289        1652 :                   strcasecmp_m(long_archi, archi_table[i].long_archi) );
     290             : 
     291         256 :         if (archi_table[i].long_archi==NULL) {
     292           4 :                 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
     293           4 :                 return NULL;
     294             :         }
     295             : 
     296             :         /* this might be client code - but shouldn't this be an fstrcpy etc? */
     297             : 
     298         252 :         DEBUGADD(108,("index: [%d]\n", i));
     299         252 :         DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
     300         252 :         DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
     301             : 
     302         252 :         return archi_table[i].short_archi;
     303             : }
     304             : 
     305             : /****************************************************************************
     306             :  Read data from fsp on the vfs.
     307             : ****************************************************************************/
     308             : 
     309           0 : static ssize_t printing_pread_data(files_struct *fsp,
     310             :                                 char *buf,
     311             :                                 off_t *poff,
     312             :                                 size_t byte_count)
     313             : {
     314           0 :         size_t total=0;
     315           0 :         off_t in_pos = *poff;
     316             : 
     317             :         /* Don't allow integer wrap on read. */
     318           0 :         if (in_pos + byte_count < in_pos) {
     319           0 :                 return -1;
     320             :         }
     321             : 
     322           0 :         while (total < byte_count) {
     323           0 :                 ssize_t ret = read_file(fsp,
     324             :                                         buf + total,
     325             :                                         in_pos,
     326             :                                         byte_count - total);
     327             : 
     328           0 :                 if (ret == 0) {
     329           0 :                         *poff = in_pos;
     330           0 :                         return total;
     331             :                 }
     332           0 :                 if (ret == -1) {
     333           0 :                         if (errno == EINTR) {
     334           0 :                                 continue;
     335             :                         } else {
     336           0 :                                 return -1;
     337             :                         }
     338             :                 }
     339           0 :                 in_pos += ret;
     340           0 :                 total += ret;
     341             :         }
     342           0 :         *poff = in_pos;
     343           0 :         return (ssize_t)total;
     344             : }
     345             : 
     346             : /****************************************************************************
     347             :  Detect the major and minor version of a PE file.
     348             :  Returns:
     349             : 
     350             :  1 if file is a PE file and we got version numbers,
     351             :  0 if this file is a PE file and we couldn't get the version numbers,
     352             :  -1 on error.
     353             : 
     354             :  NB. buf is passed into and freed inside this function. This is a
     355             :  bad API design, but fixing this is a task for another day.
     356             : ****************************************************************************/
     357             : 
     358           0 : static int handle_pe_file(files_struct *fsp,
     359             :                                 off_t in_pos,
     360             :                                 char *fname,
     361             :                                 char *buf,
     362             :                                 uint32_t *major,
     363             :                                 uint32_t *minor)
     364             : {
     365           0 :         unsigned int i;
     366           0 :         unsigned int num_sections;
     367           0 :         unsigned int section_table_bytes;
     368           0 :         ssize_t byte_count;
     369           0 :         off_t rel_pos;
     370           0 :         int ret = -1;
     371             : 
     372             :         /* Just skip over optional header to get to section table */
     373           0 :         rel_pos = SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-
     374             :                 (NE_HEADER_SIZE-PE_HEADER_SIZE);
     375             : 
     376           0 :         if (in_pos + rel_pos < in_pos) {
     377             :                 /* Integer wrap. */
     378           0 :                 goto out;
     379             :         }
     380           0 :         in_pos = rel_pos + in_pos;
     381             : 
     382             :         /* get the section table */
     383           0 :         num_sections        = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
     384             : 
     385           0 :         if (num_sections >= (UINT_MAX / PE_HEADER_SECT_HEADER_SIZE)) {
     386             :                 /* Integer wrap. */
     387           0 :                 goto out;
     388             :         }
     389             : 
     390           0 :         section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
     391           0 :         if (section_table_bytes == 0) {
     392           0 :                 goto out;
     393             :         }
     394             : 
     395           0 :         SAFE_FREE(buf);
     396           0 :         buf = (char *)SMB_MALLOC(section_table_bytes);
     397           0 :         if (buf == NULL) {
     398           0 :                 DBG_ERR("PE file [%s] section table malloc "
     399             :                         "failed bytes = %d\n",
     400             :                         fname,
     401             :                         section_table_bytes);
     402           0 :                 goto out;
     403             :         }
     404             : 
     405           0 :         byte_count = printing_pread_data(fsp, buf, &in_pos, section_table_bytes);
     406           0 :         if (byte_count < section_table_bytes) {
     407           0 :                 DBG_NOTICE("PE file [%s] Section header too short, "
     408             :                         "bytes read = %lu\n",
     409             :                         fname,
     410             :                         (unsigned long)byte_count);
     411           0 :                 goto out;
     412             :         }
     413             : 
     414             :         /*
     415             :          * Iterate the section table looking for
     416             :          * the resource section ".rsrc"
     417             :          */
     418           0 :         for (i = 0; i < num_sections; i++) {
     419           0 :                 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
     420             : 
     421           0 :                 if (strcmp(".rsrc",
     422           0 :                         &buf[sec_offset+ PE_HEADER_SECT_NAME_OFFSET]) == 0) {
     423           0 :                         unsigned int section_pos = IVAL(buf,
     424             :                                         sec_offset+
     425             :                                         PE_HEADER_SECT_PTR_DATA_OFFSET);
     426           0 :                         unsigned int section_bytes = IVAL(buf,
     427             :                                         sec_offset+
     428             :                                         PE_HEADER_SECT_SIZE_DATA_OFFSET);
     429             : 
     430           0 :                         if (section_bytes == 0) {
     431           0 :                                 goto out;
     432             :                         }
     433             : 
     434           0 :                         SAFE_FREE(buf);
     435           0 :                         buf=(char *)SMB_MALLOC(section_bytes);
     436           0 :                         if (buf == NULL) {
     437           0 :                                 DBG_ERR("PE file [%s] version malloc "
     438             :                                         "failed bytes = %d\n",
     439             :                                         fname,
     440             :                                         section_bytes);
     441           0 :                                 goto out;
     442             :                         }
     443             : 
     444             :                         /*
     445             :                          * Read from the start of the .rsrc
     446             :                          * section info
     447             :                          */
     448           0 :                         in_pos = section_pos;
     449             : 
     450           0 :                         byte_count = printing_pread_data(fsp,
     451             :                                                 buf,
     452             :                                                 &in_pos,
     453             :                                                 section_bytes);
     454           0 :                         if (byte_count < section_bytes) {
     455           0 :                                 DBG_NOTICE("PE file "
     456             :                                         "[%s] .rsrc section too short, "
     457             :                                         "bytes read = %lu\n",
     458             :                                          fname,
     459             :                                         (unsigned long)byte_count);
     460           0 :                                 goto out;
     461             :                         }
     462             : 
     463           0 :                         if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE) {
     464           0 :                                 goto out;
     465             :                         }
     466             : 
     467           0 :                         for (i=0;
     468           0 :                                 i< section_bytes - VS_VERSION_INFO_UNICODE_SIZE;
     469           0 :                                         i++) {
     470             :                                 /*
     471             :                                  * Scan for 1st 3 unicoded bytes
     472             :                                  * followed by word aligned magic
     473             :                                  * value.
     474             :                                  */
     475           0 :                                 int mpos;
     476           0 :                                 bool magic_match = false;
     477             : 
     478           0 :                                 if (buf[i] == 'V' &&
     479           0 :                                                 buf[i+1] == '\0' &&
     480           0 :                                                 buf[i+2] == 'S') {
     481           0 :                                         magic_match = true;
     482             :                                 }
     483             : 
     484           0 :                                 if (magic_match == false) {
     485           0 :                                         continue;
     486             :                                 }
     487             : 
     488             :                                 /* Align to next long address */
     489           0 :                                 mpos = (i + sizeof(VS_SIGNATURE)*2 +
     490           0 :                                         3) & 0xfffffffc;
     491             : 
     492           0 :                                 if (IVAL(buf,mpos) == VS_MAGIC_VALUE) {
     493           0 :                                         *major = IVAL(buf,
     494             :                                                         mpos+ VS_MAJOR_OFFSET);
     495           0 :                                         *minor = IVAL(buf,
     496             :                                                         mpos+ VS_MINOR_OFFSET);
     497             : 
     498           0 :                                         DBG_INFO("PE file [%s] Version = "
     499             :                                                 "%08x:%08x (%d.%d.%d.%d)\n",
     500             :                                                 fname,
     501             :                                                 *major,
     502             :                                                 *minor,
     503             :                                                 (*major>>16)&0xffff,
     504             :                                                 *major&0xffff,
     505             :                                                 (*minor>>16)&0xffff,
     506             :                                                 *minor&0xffff);
     507           0 :                                         ret = 1;
     508           0 :                                         goto out;
     509             :                                 }
     510             :                         }
     511             :                 }
     512             :         }
     513             : 
     514             :         /* Version info not found, fall back to origin date/time */
     515           0 :         DBG_DEBUG("PE file [%s] has no version info\n", fname);
     516           0 :         ret = 0;
     517             : 
     518           0 :   out:
     519             : 
     520           0 :         SAFE_FREE(buf);
     521           0 :         return ret;
     522             : }
     523             : 
     524             : /****************************************************************************
     525             :  Detect the major and minor version of an NE file.
     526             :  Returns:
     527             : 
     528             :  1 if file is an NE file and we got version numbers,
     529             :  0 if this file is an NE file and we couldn't get the version numbers,
     530             :  -1 on error.
     531             : 
     532             :  NB. buf is passed into and freed inside this function. This is a
     533             :  bad API design, but fixing this is a task for another day.
     534             : ****************************************************************************/
     535             : 
     536           0 : static int handle_ne_file(files_struct *fsp,
     537             :                                 off_t in_pos,
     538             :                                 char *fname,
     539             :                                 char *buf,
     540             :                                 uint32_t *major,
     541             :                                 uint32_t *minor)
     542             : {
     543           0 :         unsigned int i;
     544           0 :         ssize_t byte_count;
     545           0 :         int ret = -1;
     546             : 
     547           0 :         if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
     548           0 :                 DBG_NOTICE("NE file [%s] wrong target OS = 0x%x\n",
     549             :                         fname,
     550             :                         CVAL(buf,NE_HEADER_TARGET_OS_OFFSET));
     551             :                 /*
     552             :                  * At this point, we assume the file is in error.
     553             :                  * It still could be something else besides a NE file,
     554             :                  * but it unlikely at this point.
     555             :                  */
     556           0 :                 goto out;
     557             :         }
     558             : 
     559             :         /* Allocate a bit more space to speed up things */
     560           0 :         SAFE_FREE(buf);
     561           0 :         buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE);
     562           0 :         if (buf == NULL) {
     563           0 :                 DBG_ERR("NE file [%s] malloc failed bytes  = %d\n",
     564             :                         fname,
     565             :                         PE_HEADER_SIZE);
     566           0 :                 goto out;
     567             :         }
     568             : 
     569             :         /*
     570             :          * This is a HACK! I got tired of trying to sort through the
     571             :          * messy 'NE' file format. If anyone wants to clean this up
     572             :          * please have at it, but this works. 'NE' files will
     573             :          * eventually fade away. JRR
     574             :          */
     575           0 :         byte_count = printing_pread_data(fsp, buf, &in_pos, VS_NE_BUF_SIZE);
     576           0 :         while (byte_count > 0) {
     577             :                 /*
     578             :                  * Cover case that should not occur in a well
     579             :                  * formed 'NE' .dll file
     580             :                  */
     581           0 :                 if (byte_count-VS_VERSION_INFO_SIZE <= 0) {
     582           0 :                         break;
     583             :                 }
     584             : 
     585           0 :                 for(i=0; i<byte_count; i++) {
     586             :                         /*
     587             :                          * Fast skip past data that can't
     588             :                          * possibly match
     589             :                          */
     590           0 :                         if (buf[i] != 'V') {
     591           0 :                                 byte_count = printing_pread_data(fsp,
     592             :                                                 buf,
     593             :                                                 &in_pos,
     594             :                                                 VS_NE_BUF_SIZE);
     595           0 :                                 continue;
     596             :                         }
     597             : 
     598             :                         /*
     599             :                          * Potential match data crosses buf boundary,
     600             :                          * move it to beginning of buf, and fill the
     601             :                          * buf with as much as it will hold.
     602             :                          */
     603           0 :                         if (i>byte_count-VS_VERSION_INFO_SIZE) {
     604           0 :                                 ssize_t amount_read;
     605           0 :                                 ssize_t amount_unused = byte_count-i;
     606             : 
     607           0 :                                 memmove(buf, &buf[i], amount_unused);
     608           0 :                                 amount_read = printing_pread_data(fsp,
     609             :                                                 &buf[amount_unused],
     610             :                                                 &in_pos,
     611           0 :                                                 VS_NE_BUF_SIZE- amount_unused);
     612           0 :                                 if (amount_read < 0) {
     613           0 :                                         DBG_ERR("NE file [%s] Read "
     614             :                                                 "error, errno=%d\n",
     615             :                                                 fname,
     616             :                                                 errno);
     617           0 :                                         goto out;
     618             :                                 }
     619             : 
     620           0 :                                 if (amount_read + amount_unused <
     621             :                                                 amount_read) {
     622             :                                         /* Check for integer wrap. */
     623           0 :                                         break;
     624             :                                 }
     625             : 
     626           0 :                                 byte_count = amount_read +
     627             :                                              amount_unused;
     628           0 :                                 if (byte_count < VS_VERSION_INFO_SIZE) {
     629           0 :                                         break;
     630             :                                 }
     631             : 
     632           0 :                                 i = 0;
     633             :                         }
     634             : 
     635             :                         /*
     636             :                          * Check that the full signature string and
     637             :                          * the magic number that follows exist (not
     638             :                          * a perfect solution, but the chances that this
     639             :                          * occurs in code is, well, remote. Yes I know
     640             :                          * I'm comparing the 'V' twice, as it is
     641             :                          * simpler to read the code.
     642             :                          */
     643           0 :                         if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
     644             :                                 /*
     645             :                                  * Compute skip alignment to next
     646             :                                  * long address.
     647             :                                  */
     648           0 :                                 off_t cpos = in_pos;
     649           0 :                                 int skip = -(cpos - (byte_count - i) +
     650           0 :                                          sizeof(VS_SIGNATURE)) & 3;
     651           0 :                                 if (IVAL(buf,
     652             :                                         i+sizeof(VS_SIGNATURE)+skip)
     653             :                                                 != 0xfeef04bd) {
     654           0 :                                         byte_count = printing_pread_data(fsp,
     655             :                                                         buf,
     656             :                                                         &in_pos,
     657             :                                                         VS_NE_BUF_SIZE);
     658           0 :                                         continue;
     659             :                                 }
     660             : 
     661           0 :                                 *major = IVAL(buf,
     662             :                                         i+sizeof(VS_SIGNATURE)+
     663             :                                         skip+VS_MAJOR_OFFSET);
     664           0 :                                 *minor = IVAL(buf,
     665             :                                         i+sizeof(VS_SIGNATURE)+
     666             :                                         skip+VS_MINOR_OFFSET);
     667           0 :                                 DBG_INFO("NE file [%s] Version "
     668             :                                         "= %08x:%08x (%d.%d.%d.%d)\n",
     669             :                                         fname,
     670             :                                         *major,
     671             :                                         *minor,
     672             :                                         (*major>>16)&0xffff,
     673             :                                         *major&0xffff,
     674             :                                         (*minor>>16)&0xffff,
     675             :                                         *minor&0xffff);
     676           0 :                                 ret = 1;
     677           0 :                                 goto out;
     678             :                         }
     679             :                 }
     680             :         }
     681             : 
     682             :         /* Version info not found, fall back to origin date/time */
     683           0 :         DBG_ERR("NE file [%s] Version info not found\n", fname);
     684           0 :         ret = 0;
     685             : 
     686           0 :   out:
     687             : 
     688           0 :         SAFE_FREE(buf);
     689           0 :         return ret;
     690             : }
     691             : 
     692             : /****************************************************************************
     693             :  Version information in Microsoft files is held in a VS_VERSION_INFO structure.
     694             :  There are two case to be covered here: PE (Portable Executable) and NE (New
     695             :  Executable) files. Both files support the same INFO structure, but PE files
     696             :  store the signature in unicode, and NE files store it as !unicode.
     697             :  returns -1 on error, 1 on version info found, and 0 on no version info found.
     698             : ****************************************************************************/
     699             : 
     700           0 : static int get_file_version(files_struct *fsp,
     701             :                                 char *fname,
     702             :                                 uint32_t *major,
     703             :                                 uint32_t *minor)
     704             : {
     705           0 :         char    *buf = NULL;
     706           0 :         ssize_t byte_count;
     707           0 :         off_t in_pos = fh_get_pos(fsp->fh);
     708             : 
     709           0 :         buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE);
     710           0 :         if (buf == NULL) {
     711           0 :                 DBG_ERR("PE file [%s] DOS Header malloc failed bytes = %d\n",
     712             :                         fname,
     713             :                         DOS_HEADER_SIZE);
     714           0 :                 goto error_exit;
     715             :         }
     716             : 
     717           0 :         byte_count = printing_pread_data(fsp, buf, &in_pos, DOS_HEADER_SIZE);
     718           0 :         if (byte_count < DOS_HEADER_SIZE) {
     719           0 :                 DBG_NOTICE("File [%s] DOS header too short, bytes read = %lu\n",
     720             :                          fname,
     721             :                         (unsigned long)byte_count);
     722           0 :                 goto no_version_info;
     723             :         }
     724             : 
     725             :         /* Is this really a DOS header? */
     726           0 :         if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
     727           0 :                 DBG_INFO("File [%s] bad DOS magic = 0x%x\n",
     728             :                         fname,
     729             :                         SVAL(buf,DOS_HEADER_MAGIC_OFFSET));
     730           0 :                 goto no_version_info;
     731             :         }
     732             : 
     733             :         /*
     734             :          * Skip OEM header (if any) and the
     735             :          * DOS stub to start of Windows header.
     736             :          */
     737           0 :         in_pos = SVAL(buf,DOS_HEADER_LFANEW_OFFSET);
     738             : 
     739             :         /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
     740           0 :         byte_count = printing_pread_data(fsp, buf, &in_pos, NE_HEADER_SIZE);
     741           0 :         if (byte_count < NE_HEADER_SIZE) {
     742           0 :                 DBG_NOTICE("File [%s] Windows header too short, "
     743             :                         "bytes read = %lu\n",
     744             :                         fname,
     745             :                         (unsigned long)byte_count);
     746             :                 /*
     747             :                  * Assume this isn't an error...
     748             :                  * the file just looks sort of like a PE/NE file
     749             :                  */
     750           0 :                 goto no_version_info;
     751             :         }
     752             : 
     753             :         /*
     754             :          * The header may be a PE (Portable Executable)
     755             :          * or an NE (New Executable).
     756             :          */
     757           0 :         if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
     758           0 :                 return handle_pe_file(fsp,
     759             :                                         in_pos,
     760             :                                         fname,
     761             :                                         buf,
     762             :                                         major,
     763             :                                         minor);
     764           0 :         } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) ==
     765             :                         NE_HEADER_SIGNATURE) {
     766           0 :                 return handle_ne_file(fsp,
     767             :                                         in_pos,
     768             :                                         fname,
     769             :                                         buf,
     770             :                                         major,
     771             :                                         minor);
     772             :         } else {
     773             :                 /*
     774             :                  * Assume this isn't an error... the file just
     775             :                  * looks sort of like a PE/NE file.
     776             :                  */
     777           0 :                 DBG_NOTICE("File [%s] unknown file format, signature = 0x%x\n",
     778             :                         fname,
     779             :                         IVAL(buf,PE_HEADER_SIGNATURE_OFFSET));
     780             :                 /* Fallthrough into no_version_info: */
     781             :         }
     782             : 
     783           0 :         no_version_info:
     784           0 :                 SAFE_FREE(buf);
     785           0 :                 return 0;
     786             : 
     787           0 :         error_exit:
     788           0 :                 SAFE_FREE(buf);
     789           0 :                 return -1;
     790             : }
     791             : 
     792             : /****************************************************************************
     793             : Drivers for Microsoft systems contain multiple files. Often, multiple drivers
     794             : share one or more files. During the MS installation process files are checked
     795             : to insure that only a newer version of a shared file is installed over an
     796             : older version. There are several possibilities for this comparison. If there
     797             : is no previous version, the new one is newer (obviously). If either file is
     798             : missing the version info structure, compare the creation date (on Unix use
     799             : the modification date). Otherwise chose the numerically larger version number.
     800             : ****************************************************************************/
     801             : 
     802           0 : static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
     803             : {
     804           0 :         bool use_version = true;
     805             : 
     806           0 :         uint32_t new_major;
     807           0 :         uint32_t new_minor;
     808           0 :         time_t new_create_time;
     809             : 
     810           0 :         uint32_t old_major;
     811           0 :         uint32_t old_minor;
     812           0 :         time_t old_create_time;
     813             : 
     814           0 :         struct smb_filename *smb_fname = NULL;
     815           0 :         files_struct    *fsp = NULL;
     816           0 :         struct files_struct *dirfsp = NULL;
     817           0 :         SMB_STRUCT_STAT st;
     818             : 
     819           0 :         NTSTATUS status;
     820           0 :         int ret;
     821             : 
     822           0 :         SET_STAT_INVALID(st);
     823           0 :         new_create_time = (time_t)0;
     824           0 :         old_create_time = (time_t)0;
     825             : 
     826             :         /* Get file version info (if available) for previous file (if it exists) */
     827           0 :         status = driver_unix_convert(conn, old_file, &dirfsp, &smb_fname);
     828           0 :         if (!NT_STATUS_IS_OK(status)) {
     829           0 :                 goto error_exit;
     830             :         }
     831             : 
     832           0 :         status = openat_pathref_fsp(conn->cwd_fsp, smb_fname);
     833           0 :         if (!NT_STATUS_IS_OK(status)) {
     834           0 :                 ret = 1;
     835           0 :                 goto done;
     836             :         }
     837             : 
     838           0 :         status = SMB_VFS_CREATE_FILE(
     839             :                 conn,                                   /* conn */
     840             :                 NULL,                                   /* req */
     841             :                 dirfsp,                                 /* dirfsp */
     842             :                 smb_fname,                              /* fname */
     843             :                 FILE_GENERIC_READ,                      /* access_mask */
     844             :                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
     845             :                 FILE_OPEN,                              /* create_disposition*/
     846             :                 0,                                      /* create_options */
     847             :                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
     848             :                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
     849             :                 NULL,                                   /* lease */
     850             :                 0,                                      /* allocation_size */
     851             :                 0,                                      /* private_flags */
     852             :                 NULL,                                   /* sd */
     853             :                 NULL,                                   /* ea_list */
     854             :                 &fsp,                                       /* result */
     855             :                 NULL,                                   /* pinfo */
     856             :                 NULL, NULL);                            /* create context */
     857             : 
     858           0 :         if (!NT_STATUS_IS_OK(status)) {
     859             :                 /* Old file not found, so by definition new file is in fact newer */
     860           0 :                 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
     861             :                           "errno = %d\n", smb_fname_str_dbg(smb_fname),
     862             :                           errno));
     863           0 :                 ret = 1;
     864           0 :                 goto done;
     865             : 
     866             :         }
     867             : 
     868           0 :         ret = get_file_version(fsp, old_file, &old_major, &old_minor);
     869           0 :         if (ret == -1) {
     870           0 :                 goto error_exit;
     871             :         }
     872             : 
     873           0 :         if (!ret) {
     874           0 :                 DEBUG(6,("file_version_is_newer: Version info not found [%s], "
     875             :                          "use mod time\n",
     876             :                          old_file));
     877           0 :                 use_version = false;
     878           0 :                 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
     879           0 :                         goto error_exit;
     880             :                 }
     881           0 :                 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
     882           0 :                 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
     883             :                             (long)old_create_time));
     884             :         }
     885             : 
     886           0 :         close_file_free(NULL, &fsp, NORMAL_CLOSE);
     887             : 
     888             :         /* Get file version info (if available) for new file */
     889           0 :         status = driver_unix_convert(conn, new_file, &dirfsp, &smb_fname);
     890           0 :         if (!NT_STATUS_IS_OK(status)) {
     891           0 :                 goto error_exit;
     892             :         }
     893             : 
     894           0 :         status = openat_pathref_fsp(conn->cwd_fsp, smb_fname);
     895           0 :         if (!NT_STATUS_IS_OK(status)) {
     896           0 :                 DBG_NOTICE("Can't open new file [%s], errno = %d\n",
     897             :                            smb_fname_str_dbg(smb_fname), errno);
     898           0 :                 goto error_exit;
     899             :         }
     900             : 
     901           0 :         status = SMB_VFS_CREATE_FILE(
     902             :                 conn,                                   /* conn */
     903             :                 NULL,                                   /* req */
     904             :                 dirfsp,                                 /* dirfsp */
     905             :                 smb_fname,                              /* fname */
     906             :                 FILE_GENERIC_READ,                      /* access_mask */
     907             :                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
     908             :                 FILE_OPEN,                              /* create_disposition*/
     909             :                 0,                                      /* create_options */
     910             :                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
     911             :                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
     912             :                 NULL,                                   /* lease */
     913             :                 0,                                      /* allocation_size */
     914             :                 0,                                      /* private_flags */
     915             :                 NULL,                                   /* sd */
     916             :                 NULL,                                   /* ea_list */
     917             :                 &fsp,                                       /* result */
     918             :                 NULL,                                   /* pinfo */
     919             :                 NULL, NULL);                            /* create context */
     920             : 
     921           0 :         if (!NT_STATUS_IS_OK(status)) {
     922             :                 /* New file not found, this shouldn't occur if the caller did its job */
     923           0 :                 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
     924             :                          "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
     925           0 :                 goto error_exit;
     926             : 
     927             :         }
     928             : 
     929           0 :         ret = get_file_version(fsp, new_file, &new_major, &new_minor);
     930           0 :         if (ret == -1) {
     931           0 :                 goto error_exit;
     932             :         }
     933             : 
     934           0 :         if (!ret) {
     935           0 :                 DEBUG(6,("file_version_is_newer: Version info not found [%s], "
     936             :                          "use mod time\n",
     937             :                          new_file));
     938           0 :                 use_version = false;
     939           0 :                 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
     940           0 :                         goto error_exit;
     941             :                 }
     942           0 :                 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
     943           0 :                 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
     944             :                             (long)new_create_time));
     945             :         }
     946             : 
     947           0 :         close_file_free(NULL, &fsp, NORMAL_CLOSE);
     948             : 
     949           0 :         if (use_version && (new_major != old_major || new_minor != old_minor)) {
     950             :                 /* Compare versions and choose the larger version number */
     951           0 :                 if (new_major > old_major ||
     952           0 :                         (new_major == old_major && new_minor > old_minor)) {
     953             : 
     954           0 :                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
     955           0 :                         ret = 1;
     956           0 :                         goto done;
     957             :                 }
     958             :                 else {
     959           0 :                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
     960           0 :                         ret = 0;
     961           0 :                         goto done;
     962             :                 }
     963             : 
     964             :         } else {
     965             :                 /* Compare modification time/dates and choose the newest time/date */
     966           0 :                 if (new_create_time > old_create_time) {
     967           0 :                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
     968           0 :                         ret = 1;
     969           0 :                         goto done;
     970             :                 }
     971             :                 else {
     972           0 :                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
     973           0 :                         ret = 0;
     974           0 :                         goto done;
     975             :                 }
     976             :         }
     977             : 
     978           0 :  error_exit:
     979           0 :         if(fsp)
     980           0 :                 close_file_free(NULL, &fsp, NORMAL_CLOSE);
     981           0 :         ret = -1;
     982           0 :  done:
     983           0 :         TALLOC_FREE(smb_fname);
     984           0 :         return ret;
     985             : }
     986             : 
     987             : /****************************************************************************
     988             : Determine the correct cVersion associated with an architecture and driver
     989             : ****************************************************************************/
     990           0 : static uint32_t get_correct_cversion(const struct auth_session_info *session_info,
     991             :                                    const char *architecture,
     992             :                                    const char *driverpath_in,
     993             :                                    const char *driver_directory,
     994             :                                    WERROR *perr)
     995             : {
     996           0 :         TALLOC_CTX *frame = talloc_stackframe();
     997           0 :         const struct loadparm_substitution *lp_sub =
     998           0 :                 loadparm_s3_global_substitution();
     999           0 :         int cversion = -1;
    1000           0 :         NTSTATUS          nt_status;
    1001           0 :         struct smb_filename *smb_fname = NULL;
    1002           0 :         files_struct      *fsp = NULL;
    1003           0 :         struct files_struct *dirfsp = NULL;
    1004           0 :         struct conn_struct_tos *c = NULL;
    1005           0 :         connection_struct *conn = NULL;
    1006           0 :         char *printdollar = NULL;
    1007           0 :         char *printdollar_path = NULL;
    1008           0 :         char *working_dir = NULL;
    1009           0 :         int printdollar_snum;
    1010           0 :         uint32_t major, minor;
    1011           0 :         int ret;
    1012             : 
    1013           0 :         *perr = WERR_INVALID_PARAMETER;
    1014             : 
    1015             :         /* If architecture is Windows 95/98/ME, the version is always 0. */
    1016           0 :         if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
    1017           0 :                 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
    1018           0 :                 *perr = WERR_OK;
    1019           0 :                 TALLOC_FREE(frame);
    1020           0 :                 return 0;
    1021             :         }
    1022             : 
    1023             :         /* If architecture is Windows x64, the version is always 3. */
    1024           0 :         if (strcmp(architecture, SPL_ARCH_X64) == 0 ||
    1025           0 :                 strcmp(architecture, SPL_ARCH_ARM64) == 0) {
    1026           0 :                 DBG_DEBUG("get_correct_cversion: this architecture must be, cversion = 3\n");
    1027           0 :                 *perr = WERR_OK;
    1028           0 :                 TALLOC_FREE(frame);
    1029           0 :                 return 3;
    1030             :         }
    1031             : 
    1032           0 :         printdollar_snum = find_service(frame, "print$", &printdollar);
    1033           0 :         if (!printdollar) {
    1034           0 :                 *perr = WERR_NOT_ENOUGH_MEMORY;
    1035           0 :                 TALLOC_FREE(frame);
    1036           0 :                 return -1;
    1037             :         }
    1038           0 :         if (printdollar_snum == -1) {
    1039           0 :                 *perr = WERR_BAD_NET_NAME;
    1040           0 :                 TALLOC_FREE(frame);
    1041           0 :                 return -1;
    1042             :         }
    1043             : 
    1044           0 :         printdollar_path = lp_path(frame, lp_sub, printdollar_snum);
    1045           0 :         if (printdollar_path == NULL) {
    1046           0 :                 *perr = WERR_NOT_ENOUGH_MEMORY;
    1047           0 :                 TALLOC_FREE(frame);
    1048           0 :                 return -1;
    1049             :         }
    1050             : 
    1051           0 :         working_dir = talloc_asprintf(frame,
    1052             :                                       "%s/%s",
    1053             :                                       printdollar_path,
    1054             :                                       architecture);
    1055             :         /*
    1056             :          * If the driver has been uploaded into a temorpary driver
    1057             :          * directory, switch to the driver directory.
    1058             :          */
    1059           0 :         if (driver_directory != NULL) {
    1060           0 :                 working_dir = talloc_asprintf(frame, "%s/%s/%s",
    1061             :                                               printdollar_path,
    1062             :                                               architecture,
    1063             :                                               driver_directory);
    1064             :         }
    1065             : 
    1066           0 :         nt_status = create_conn_struct_tos_cwd(global_messaging_context(),
    1067             :                                                printdollar_snum,
    1068             :                                                working_dir,
    1069             :                                                session_info,
    1070             :                                                &c);
    1071           0 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1072           0 :                 DEBUG(0,("get_correct_cversion: create_conn_struct "
    1073             :                          "returned %s\n", nt_errstr(nt_status)));
    1074           0 :                 *perr = ntstatus_to_werror(nt_status);
    1075           0 :                 TALLOC_FREE(frame);
    1076           0 :                 return -1;
    1077             :         }
    1078           0 :         conn = c->conn;
    1079             : 
    1080           0 :         nt_status = set_conn_force_user_group(conn, printdollar_snum);
    1081           0 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1082           0 :                 DEBUG(0, ("failed set force user / group\n"));
    1083           0 :                 *perr = ntstatus_to_werror(nt_status);
    1084           0 :                 goto error_free_conn;
    1085             :         }
    1086             : 
    1087           0 :         if (!become_user_without_service_by_session(conn, session_info)) {
    1088           0 :                 DEBUG(0, ("failed to become user\n"));
    1089           0 :                 *perr = WERR_ACCESS_DENIED;
    1090           0 :                 goto error_free_conn;
    1091             :         }
    1092             : 
    1093             :         /*
    1094             :          * We switch to the directory where the driver files are located,
    1095             :          * so only work on the file names
    1096             :          */
    1097           0 :         nt_status = driver_unix_convert(conn,
    1098             :                                         driverpath_in,
    1099             :                                         &dirfsp,
    1100             :                                         &smb_fname);
    1101           0 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1102           0 :                 *perr = ntstatus_to_werror(nt_status);
    1103           0 :                 goto error_exit;
    1104             :         }
    1105             : 
    1106           0 :         nt_status = vfs_file_exist(conn, smb_fname);
    1107           0 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1108           0 :                 DEBUG(3,("get_correct_cversion: vfs_file_exist failed\n"));
    1109           0 :                 *perr = WERR_FILE_NOT_FOUND;
    1110           0 :                 goto error_exit;
    1111             :         }
    1112             : 
    1113           0 :         nt_status = openat_pathref_fsp(conn->cwd_fsp, smb_fname);
    1114           0 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1115           0 :                 DBG_NOTICE("Can't open file [%s]: %s\n",
    1116             :                            smb_fname_str_dbg(smb_fname),
    1117             :                            nt_errstr(nt_status));
    1118           0 :                 *perr = WERR_ACCESS_DENIED;
    1119           0 :                 goto error_exit;
    1120             :         }
    1121             : 
    1122           0 :         nt_status = SMB_VFS_CREATE_FILE(
    1123             :                 conn,                                   /* conn */
    1124             :                 NULL,                                   /* req */
    1125             :                 dirfsp,                                 /* dirfsp */
    1126             :                 smb_fname,                              /* fname */
    1127             :                 FILE_GENERIC_READ,                      /* access_mask */
    1128             :                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
    1129             :                 FILE_OPEN,                              /* create_disposition*/
    1130             :                 0,                                      /* create_options */
    1131             :                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
    1132             :                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
    1133             :                 NULL,                                   /* lease */
    1134             :                 0,                                      /* private_flags */
    1135             :                 0,                                      /* allocation_size */
    1136             :                 NULL,                                   /* sd */
    1137             :                 NULL,                                   /* ea_list */
    1138             :                 &fsp,                                       /* result */
    1139             :                 NULL,                                   /* pinfo */
    1140             :                 NULL, NULL);                            /* create context */
    1141             : 
    1142           0 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1143           0 :                 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
    1144             :                          "%d\n", smb_fname_str_dbg(smb_fname), errno));
    1145           0 :                 *perr = WERR_ACCESS_DENIED;
    1146           0 :                 goto error_exit;
    1147             :         }
    1148             : 
    1149           0 :         ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
    1150           0 :         if (ret == -1) {
    1151           0 :                 *perr = WERR_INVALID_PARAMETER;
    1152           0 :                 goto error_exit;
    1153           0 :         } else if (!ret) {
    1154           0 :                 DEBUG(6,("get_correct_cversion: Version info not "
    1155             :                          "found [%s]\n",
    1156             :                          smb_fname_str_dbg(smb_fname)));
    1157           0 :                 *perr = WERR_INVALID_PARAMETER;
    1158           0 :                 goto error_exit;
    1159             :         }
    1160             : 
    1161             :         /*
    1162             :          * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
    1163             :          * for more details. Version in this case is not just the version of the
    1164             :          * file, but the version in the sense of kernel mode (2) vs. user mode
    1165             :          * (3) drivers. Other bits of the version fields are the version info.
    1166             :          * JRR 010716
    1167             :          */
    1168           0 :         cversion = major & 0x0000ffff;
    1169           0 :         switch (cversion) {
    1170           0 :         case 2: /* WinNT drivers */
    1171             :         case 3: /* Win2K drivers */
    1172           0 :                 break;
    1173             : 
    1174           0 :         default:
    1175           0 :                 DEBUG(6,("get_correct_cversion: cversion "
    1176             :                          "invalid [%s]  cversion = %d\n",
    1177             :                          smb_fname_str_dbg(smb_fname),
    1178             :                          cversion));
    1179           0 :                 goto error_exit;
    1180             :         }
    1181             : 
    1182           0 :         DEBUG(10,("get_correct_cversion: Version info found [%s] major"
    1183             :                   " = 0x%x  minor = 0x%x\n",
    1184             :                   smb_fname_str_dbg(smb_fname), major, minor));
    1185             : 
    1186           0 :         DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
    1187             :                   smb_fname_str_dbg(smb_fname), cversion));
    1188           0 :         *perr = WERR_OK;
    1189             : 
    1190           0 :  error_exit:
    1191           0 :         unbecome_user_without_service();
    1192           0 :  error_free_conn:
    1193           0 :         if (fsp != NULL) {
    1194           0 :                 close_file_free(NULL, &fsp, NORMAL_CLOSE);
    1195             :         }
    1196           0 :         if (!W_ERROR_IS_OK(*perr)) {
    1197           0 :                 cversion = -1;
    1198             :         }
    1199             : 
    1200           0 :         TALLOC_FREE(frame);
    1201           0 :         return cversion;
    1202             : }
    1203             : 
    1204             : /****************************************************************************
    1205             : ****************************************************************************/
    1206             : 
    1207             : #define strip_driver_path(_mem_ctx, _element) do { \
    1208             :         if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
    1209             :                 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
    1210             :                 W_ERROR_HAVE_NO_MEMORY((_element)); \
    1211             :         } \
    1212             : } while (0);
    1213             : 
    1214           0 : static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
    1215             :                                            const struct auth_session_info *session_info,
    1216             :                                            const char *architecture,
    1217             :                                            const char **driver_path,
    1218             :                                            const char **data_file,
    1219             :                                            const char **config_file,
    1220             :                                            const char **help_file,
    1221             :                                            struct spoolss_StringArray *dependent_files,
    1222             :                                            enum spoolss_DriverOSVersion *version,
    1223             :                                            uint32_t flags,
    1224             :                                            const char **driver_directory)
    1225             : {
    1226           0 :         const char *short_architecture;
    1227           0 :         int i;
    1228           0 :         WERROR err;
    1229           0 :         char *_p;
    1230             : 
    1231           0 :         if (!*driver_path || !*data_file) {
    1232           0 :                 return WERR_INVALID_PARAMETER;
    1233             :         }
    1234             : 
    1235           0 :         if (!strequal(architecture, SPOOLSS_ARCHITECTURE_4_0) && !*config_file) {
    1236           0 :                 return WERR_INVALID_PARAMETER;
    1237             :         }
    1238             : 
    1239           0 :         if (flags & APD_COPY_FROM_DIRECTORY) {
    1240           0 :                 char *path;
    1241           0 :                 char *q;
    1242             : 
    1243             :                 /*
    1244             :                  * driver_path is set to:
    1245             :                  *
    1246             :                  * \\PRINTSRV\print$\x64\{279245b0-a8bd-4431-bf6f-baee92ac15c0}\pscript5.dll
    1247             :                  */
    1248           0 :                 path = talloc_strdup(mem_ctx, *driver_path);
    1249           0 :                 if (path == NULL) {
    1250           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    1251             :                 }
    1252             : 
    1253             :                 /* Remove pscript5.dll */
    1254           0 :                 q = strrchr_m(path, '\\');
    1255           0 :                 if (q == NULL) {
    1256           0 :                         return WERR_INVALID_PARAMETER;
    1257             :                 }
    1258           0 :                 *q = '\0';
    1259             : 
    1260             :                 /* Get \{279245b0-a8bd-4431-bf6f-baee92ac15c0} */
    1261           0 :                 q = strrchr_m(path, '\\');
    1262           0 :                 if (q == NULL) {
    1263           0 :                         return WERR_INVALID_PARAMETER;
    1264             :                 }
    1265             : 
    1266             :                 /*
    1267             :                  * Set driver_directory to:
    1268             :                  *
    1269             :                  * {279245b0-a8bd-4431-bf6f-baee92ac15c0}
    1270             :                  *
    1271             :                  * This is the directory where all the files have been uploaded
    1272             :                  */
    1273           0 :                 *driver_directory = q + 1;
    1274             :         }
    1275             : 
    1276             :         /* clean up the driver name.
    1277             :          * we can get .\driver.dll
    1278             :          * or worse c:\windows\system\driver.dll !
    1279             :          */
    1280             :         /* using an intermediate string to not have overlapping memcpy()'s */
    1281             : 
    1282           0 :         strip_driver_path(mem_ctx, *driver_path);
    1283           0 :         strip_driver_path(mem_ctx, *data_file);
    1284           0 :         if (*config_file) {
    1285           0 :                 strip_driver_path(mem_ctx, *config_file);
    1286             :         }
    1287           0 :         if (help_file) {
    1288           0 :                 strip_driver_path(mem_ctx, *help_file);
    1289             :         }
    1290             : 
    1291           0 :         if (dependent_files && dependent_files->string) {
    1292           0 :                 for (i=0; dependent_files->string[i]; i++) {
    1293           0 :                         strip_driver_path(mem_ctx, dependent_files->string[i]);
    1294             :                 }
    1295             :         }
    1296             : 
    1297           0 :         short_architecture = get_short_archi(architecture);
    1298           0 :         if (!short_architecture) {
    1299           0 :                 return WERR_UNKNOWN_PRINTER_DRIVER;
    1300             :         }
    1301             : 
    1302             :         /* jfm:7/16/2000 the client always sends the cversion=0.
    1303             :          * The server should check which version the driver is by reading
    1304             :          * the PE header of driver->driverpath.
    1305             :          *
    1306             :          * For Windows 95/98 the version is 0 (so the value sent is correct)
    1307             :          * For Windows NT (the architecture doesn't matter)
    1308             :          *      NT 3.1: cversion=0
    1309             :          *      NT 3.5/3.51: cversion=1
    1310             :          *      NT 4: cversion=2
    1311             :          *      NT2K: cversion=3
    1312             :          */
    1313             : 
    1314           0 :         *version = get_correct_cversion(session_info,
    1315             :                                         short_architecture,
    1316             :                                         *driver_path,
    1317             :                                         *driver_directory,
    1318             :                                         &err);
    1319           0 :         if (*version == -1) {
    1320           0 :                 return err;
    1321             :         }
    1322             : 
    1323           0 :         return WERR_OK;
    1324             : }
    1325             : 
    1326             : /****************************************************************************
    1327             : ****************************************************************************/
    1328             : 
    1329           0 : WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
    1330             :                               const struct auth_session_info *session_info,
    1331             :                               const struct spoolss_AddDriverInfoCtr *r,
    1332             :                               uint32_t flags,
    1333             :                               const char **driver_directory)
    1334             : {
    1335           0 :         switch (r->level) {
    1336           0 :         case 3:
    1337           0 :                 return clean_up_driver_struct_level(mem_ctx, session_info,
    1338           0 :                                                     r->info.info3->architecture,
    1339           0 :                                                     &r->info.info3->driver_path,
    1340           0 :                                                     &r->info.info3->data_file,
    1341           0 :                                                     &r->info.info3->config_file,
    1342           0 :                                                     &r->info.info3->help_file,
    1343           0 :                                                     r->info.info3->dependent_files,
    1344           0 :                                                     &r->info.info3->version,
    1345             :                                                     flags,
    1346             :                                                     driver_directory);
    1347           0 :         case 6:
    1348           0 :                 return clean_up_driver_struct_level(mem_ctx, session_info,
    1349           0 :                                                     r->info.info6->architecture,
    1350           0 :                                                     &r->info.info6->driver_path,
    1351           0 :                                                     &r->info.info6->data_file,
    1352           0 :                                                     &r->info.info6->config_file,
    1353           0 :                                                     &r->info.info6->help_file,
    1354           0 :                                                     r->info.info6->dependent_files,
    1355           0 :                                                     &r->info.info6->version,
    1356             :                                                     flags,
    1357             :                                                     driver_directory);
    1358           0 :         case 8:
    1359           0 :                 return clean_up_driver_struct_level(mem_ctx, session_info,
    1360           0 :                                                     r->info.info8->architecture,
    1361           0 :                                                     &r->info.info8->driver_path,
    1362           0 :                                                     &r->info.info8->data_file,
    1363           0 :                                                     &r->info.info8->config_file,
    1364           0 :                                                     &r->info.info8->help_file,
    1365           0 :                                                     r->info.info8->dependent_files,
    1366           0 :                                                     &r->info.info8->version,
    1367             :                                                     flags,
    1368             :                                                     driver_directory);
    1369           0 :         default:
    1370           0 :                 return WERR_NOT_SUPPORTED;
    1371             :         }
    1372             : }
    1373             : 
    1374             : /****************************************************************************
    1375             :  This function sucks and should be replaced. JRA.
    1376             : ****************************************************************************/
    1377             : 
    1378           0 : static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
    1379             :                                       const struct spoolss_AddDriverInfo6 *src)
    1380             : {
    1381           0 :         dst->version         = src->version;
    1382             : 
    1383           0 :         dst->driver_name     = src->driver_name;
    1384           0 :         dst->architecture    = src->architecture;
    1385           0 :         dst->driver_path     = src->driver_path;
    1386           0 :         dst->data_file               = src->data_file;
    1387           0 :         dst->config_file     = src->config_file;
    1388           0 :         dst->help_file               = src->help_file;
    1389           0 :         dst->monitor_name    = src->monitor_name;
    1390           0 :         dst->default_datatype        = src->default_datatype;
    1391           0 :         dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
    1392           0 :         dst->dependent_files = src->dependent_files;
    1393           0 : }
    1394             : 
    1395           0 : static void convert_level_8_to_level3(struct spoolss_AddDriverInfo3 *dst,
    1396             :                                       const struct spoolss_AddDriverInfo8 *src)
    1397             : {
    1398           0 :         dst->version         = src->version;
    1399             : 
    1400           0 :         dst->driver_name     = src->driver_name;
    1401           0 :         dst->architecture    = src->architecture;
    1402           0 :         dst->driver_path     = src->driver_path;
    1403           0 :         dst->data_file               = src->data_file;
    1404           0 :         dst->config_file     = src->config_file;
    1405           0 :         dst->help_file               = src->help_file;
    1406           0 :         dst->monitor_name    = src->monitor_name;
    1407           0 :         dst->default_datatype        = src->default_datatype;
    1408           0 :         dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
    1409           0 :         dst->dependent_files = src->dependent_files;
    1410           0 : }
    1411             : 
    1412             : /****************************************************************************
    1413             : ****************************************************************************/
    1414             : 
    1415           0 : static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
    1416             :                                                 connection_struct *conn,
    1417             :                                                 const char *driver_file,
    1418             :                                                 const char *short_architecture,
    1419             :                                                 uint32_t driver_version,
    1420             :                                                 uint32_t version,
    1421             :                                                 const char *driver_directory)
    1422             : {
    1423           0 :         struct smb_filename *smb_fname_old = NULL;
    1424           0 :         struct smb_filename *smb_fname_new = NULL;
    1425           0 :         char *old_name = NULL;
    1426           0 :         char *new_name = NULL;
    1427           0 :         NTSTATUS status;
    1428           0 :         WERROR ret;
    1429             : 
    1430           0 :         if (driver_directory != NULL) {
    1431           0 :                 old_name = talloc_asprintf(mem_ctx,
    1432             :                                            "%s/%s/%s",
    1433             :                                            short_architecture,
    1434             :                                            driver_directory,
    1435             :                                            driver_file);
    1436             :         } else {
    1437           0 :                 old_name = talloc_asprintf(mem_ctx,
    1438             :                                            "%s/%s",
    1439             :                                            short_architecture,
    1440             :                                            driver_file);
    1441             :         }
    1442           0 :         if (old_name == NULL) {
    1443           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1444             :         }
    1445             : 
    1446           0 :         new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
    1447             :                                    short_architecture, driver_version, driver_file);
    1448           0 :         if (new_name == NULL) {
    1449           0 :                 TALLOC_FREE(old_name);
    1450           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1451             :         }
    1452             : 
    1453           0 :         if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
    1454           0 :                 struct files_struct *dirfsp = NULL;
    1455             : 
    1456           0 :                 status = driver_unix_convert(conn,
    1457             :                                              old_name,
    1458             :                                              &dirfsp,
    1459             :                                              &smb_fname_old);
    1460           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1461           0 :                         ret = WERR_NOT_ENOUGH_MEMORY;
    1462           0 :                         goto out;
    1463             :                 }
    1464             : 
    1465             :                 /* Setup a synthetic smb_filename struct */
    1466           0 :                 smb_fname_new = talloc_zero(mem_ctx, struct smb_filename);
    1467           0 :                 if (!smb_fname_new) {
    1468           0 :                         ret = WERR_NOT_ENOUGH_MEMORY;
    1469           0 :                         goto out;
    1470             :                 }
    1471             : 
    1472           0 :                 smb_fname_new->base_name = new_name;
    1473             : 
    1474           0 :                 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
    1475             :                           "'%s'\n", smb_fname_old->base_name,
    1476             :                           smb_fname_new->base_name));
    1477             : 
    1478           0 :                 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
    1479             :                                    FILE_OVERWRITE_IF);
    1480             : 
    1481           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1482           0 :                         DEBUG(0,("move_driver_file_to_download_area: Unable "
    1483             :                                  "to rename [%s] to [%s]: %s\n",
    1484             :                                  smb_fname_old->base_name, new_name,
    1485             :                                  nt_errstr(status)));
    1486           0 :                         ret = WERR_APP_INIT_FAILURE;
    1487           0 :                         goto out;
    1488             :                 }
    1489             :         }
    1490             : 
    1491           0 :         ret = WERR_OK;
    1492           0 :  out:
    1493           0 :         TALLOC_FREE(smb_fname_old);
    1494           0 :         TALLOC_FREE(smb_fname_new);
    1495           0 :         return ret;
    1496             : }
    1497             : 
    1498           0 : WERROR move_driver_to_download_area(const struct auth_session_info *session_info,
    1499             :                                     const struct spoolss_AddDriverInfoCtr *r,
    1500             :                                     const char *driver_directory)
    1501             : {
    1502           0 :         TALLOC_CTX *frame = talloc_stackframe();
    1503           0 :         const struct loadparm_substitution *lp_sub =
    1504           0 :                 loadparm_s3_global_substitution();
    1505           0 :         struct spoolss_AddDriverInfo3 *driver;
    1506           0 :         struct spoolss_AddDriverInfo3 converted_driver;
    1507           0 :         const char *short_architecture;
    1508           0 :         struct files_struct *dirfsp = NULL;
    1509           0 :         struct smb_filename *smb_dname = NULL;
    1510           0 :         char *new_dir = NULL;
    1511           0 :         struct conn_struct_tos *c = NULL;
    1512           0 :         connection_struct *conn = NULL;
    1513           0 :         NTSTATUS nt_status;
    1514           0 :         int i;
    1515           0 :         int ver = 0;
    1516           0 :         char *printdollar = NULL;
    1517           0 :         int printdollar_snum;
    1518           0 :         WERROR err = WERR_OK;
    1519             : 
    1520           0 :         switch (r->level) {
    1521           0 :         case 3:
    1522           0 :                 driver = r->info.info3;
    1523           0 :                 break;
    1524           0 :         case 6:
    1525           0 :                 convert_level_6_to_level3(&converted_driver, r->info.info6);
    1526           0 :                 driver = &converted_driver;
    1527           0 :                 break;
    1528           0 :         case 8:
    1529           0 :                 convert_level_8_to_level3(&converted_driver, r->info.info8);
    1530           0 :                 driver = &converted_driver;
    1531           0 :                 break;
    1532           0 :         default:
    1533           0 :                 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
    1534           0 :                 TALLOC_FREE(frame);
    1535           0 :                 return WERR_INVALID_LEVEL;
    1536             :         }
    1537             : 
    1538           0 :         short_architecture = get_short_archi(driver->architecture);
    1539           0 :         if (!short_architecture) {
    1540           0 :                 TALLOC_FREE(frame);
    1541           0 :                 return WERR_UNKNOWN_PRINTER_DRIVER;
    1542             :         }
    1543             : 
    1544           0 :         printdollar_snum = find_service(frame, "print$", &printdollar);
    1545           0 :         if (!printdollar) {
    1546           0 :                 TALLOC_FREE(frame);
    1547           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1548             :         }
    1549           0 :         if (printdollar_snum == -1) {
    1550           0 :                 TALLOC_FREE(frame);
    1551           0 :                 return WERR_BAD_NET_NAME;
    1552             :         }
    1553             : 
    1554           0 :         nt_status = create_conn_struct_tos_cwd(global_messaging_context(),
    1555             :                                                printdollar_snum,
    1556           0 :                                                lp_path(frame, lp_sub, printdollar_snum),
    1557             :                                                session_info,
    1558             :                                                &c);
    1559           0 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1560           0 :                 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
    1561             :                          "returned %s\n", nt_errstr(nt_status)));
    1562           0 :                 err = ntstatus_to_werror(nt_status);
    1563           0 :                 TALLOC_FREE(frame);
    1564           0 :                 return err;
    1565             :         }
    1566           0 :         conn = c->conn;
    1567             : 
    1568           0 :         nt_status = set_conn_force_user_group(conn, printdollar_snum);
    1569           0 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1570           0 :                 DEBUG(0, ("failed set force user / group\n"));
    1571           0 :                 err = ntstatus_to_werror(nt_status);
    1572           0 :                 goto err_free_conn;
    1573             :         }
    1574             : 
    1575           0 :         if (!become_user_without_service_by_session(conn, session_info)) {
    1576           0 :                 DEBUG(0, ("failed to become user\n"));
    1577           0 :                 err = WERR_ACCESS_DENIED;
    1578           0 :                 goto err_free_conn;
    1579             :         }
    1580             : 
    1581           0 :         new_dir = talloc_asprintf(frame,
    1582             :                                 "%s/%d",
    1583             :                                 short_architecture,
    1584           0 :                                 driver->version);
    1585           0 :         if (!new_dir) {
    1586           0 :                 err = WERR_NOT_ENOUGH_MEMORY;
    1587           0 :                 goto err_exit;
    1588             :         }
    1589           0 :         nt_status = driver_unix_convert(conn, new_dir, &dirfsp, &smb_dname);
    1590           0 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1591           0 :                 err = WERR_NOT_ENOUGH_MEMORY;
    1592           0 :                 goto err_exit;
    1593             :         }
    1594             : 
    1595           0 :         DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
    1596             : 
    1597           0 :         nt_status = create_directory(conn, NULL, dirfsp, smb_dname);
    1598           0 :         if (!NT_STATUS_IS_OK(nt_status)
    1599           0 :          && !NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_COLLISION)) {
    1600           0 :                 DEBUG(0, ("failed to create driver destination directory: %s\n",
    1601             :                           nt_errstr(nt_status)));
    1602           0 :                 err = ntstatus_to_werror(nt_status);
    1603           0 :                 goto err_exit;
    1604             :         }
    1605             : 
    1606             :         /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
    1607             :          * listed for this driver which has already been moved, skip it (note:
    1608             :          * drivers may list the same file name several times. Then check if the
    1609             :          * file already exists in archi\version\, if so, check that the version
    1610             :          * info (or time stamps if version info is unavailable) is newer (or the
    1611             :          * date is later). If it is, move it to archi\version\filexxx.yyy.
    1612             :          * Otherwise, delete the file.
    1613             :          *
    1614             :          * If a file is not moved to archi\version\ because of an error, all the
    1615             :          * rest of the 'unmoved' driver files are removed from archi\. If one or
    1616             :          * more of the driver's files was already moved to archi\version\, it
    1617             :          * potentially leaves the driver in a partially updated state. Version
    1618             :          * trauma will most likely occur if an client attempts to use any printer
    1619             :          * bound to the driver. Perhaps a rewrite to make sure the moves can be
    1620             :          * done is appropriate... later JRR
    1621             :          */
    1622             : 
    1623           0 :         DEBUG(5,("Moving files now !\n"));
    1624             : 
    1625           0 :         if (driver->driver_path && strlen(driver->driver_path)) {
    1626             : 
    1627           0 :                 err = move_driver_file_to_download_area(frame,
    1628             :                                                         conn,
    1629             :                                                         driver->driver_path,
    1630             :                                                         short_architecture,
    1631           0 :                                                         driver->version,
    1632             :                                                         ver,
    1633             :                                                         driver_directory);
    1634           0 :                 if (!W_ERROR_IS_OK(err)) {
    1635           0 :                         goto err_exit;
    1636             :                 }
    1637             :         }
    1638             : 
    1639           0 :         if (driver->data_file && strlen(driver->data_file)) {
    1640           0 :                 if (!strequal(driver->data_file, driver->driver_path)) {
    1641             : 
    1642           0 :                         err = move_driver_file_to_download_area(frame,
    1643             :                                                                 conn,
    1644             :                                                                 driver->data_file,
    1645             :                                                                 short_architecture,
    1646           0 :                                                                 driver->version,
    1647             :                                                                 ver,
    1648             :                                                                 driver_directory);
    1649           0 :                         if (!W_ERROR_IS_OK(err)) {
    1650           0 :                                 goto err_exit;
    1651             :                         }
    1652             :                 }
    1653             :         }
    1654             : 
    1655           0 :         if (driver->config_file && strlen(driver->config_file)) {
    1656           0 :                 if (!strequal(driver->config_file, driver->driver_path) &&
    1657           0 :                     !strequal(driver->config_file, driver->data_file)) {
    1658             : 
    1659           0 :                         err = move_driver_file_to_download_area(frame,
    1660             :                                                                 conn,
    1661             :                                                                 driver->config_file,
    1662             :                                                                 short_architecture,
    1663           0 :                                                                 driver->version,
    1664             :                                                                 ver,
    1665             :                                                                 driver_directory);
    1666           0 :                         if (!W_ERROR_IS_OK(err)) {
    1667           0 :                                 goto err_exit;
    1668             :                         }
    1669             :                 }
    1670             :         }
    1671             : 
    1672           0 :         if (driver->help_file && strlen(driver->help_file)) {
    1673           0 :                 if (!strequal(driver->help_file, driver->driver_path) &&
    1674           0 :                     !strequal(driver->help_file, driver->data_file) &&
    1675           0 :                     !strequal(driver->help_file, driver->config_file)) {
    1676             : 
    1677           0 :                         err = move_driver_file_to_download_area(frame,
    1678             :                                                                 conn,
    1679             :                                                                 driver->help_file,
    1680             :                                                                 short_architecture,
    1681           0 :                                                                 driver->version,
    1682             :                                                                 ver,
    1683             :                                                                 driver_directory);
    1684           0 :                         if (!W_ERROR_IS_OK(err)) {
    1685           0 :                                 goto err_exit;
    1686             :                         }
    1687             :                 }
    1688             :         }
    1689             : 
    1690           0 :         if (driver->dependent_files && driver->dependent_files->string) {
    1691           0 :                 for (i=0; driver->dependent_files->string[i]; i++) {
    1692           0 :                         if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
    1693           0 :                             !strequal(driver->dependent_files->string[i], driver->data_file) &&
    1694           0 :                             !strequal(driver->dependent_files->string[i], driver->config_file) &&
    1695           0 :                             !strequal(driver->dependent_files->string[i], driver->help_file)) {
    1696             :                                 int j;
    1697           0 :                                 for (j=0; j < i; j++) {
    1698           0 :                                         if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
    1699           0 :                                                 goto NextDriver;
    1700             :                                         }
    1701             :                                 }
    1702             : 
    1703           0 :                                 err = move_driver_file_to_download_area(frame,
    1704             :                                                                         conn,
    1705           0 :                                                                         driver->dependent_files->string[i],
    1706             :                                                                         short_architecture,
    1707           0 :                                                                         driver->version,
    1708             :                                                                         ver,
    1709             :                                                                         driver_directory);
    1710           0 :                                 if (!W_ERROR_IS_OK(err)) {
    1711           0 :                                         goto err_exit;
    1712             :                                 }
    1713             :                         }
    1714           0 :                 NextDriver: ;
    1715             :                 }
    1716             :         }
    1717             : 
    1718           0 :         err = WERR_OK;
    1719           0 :  err_exit:
    1720           0 :         unbecome_user_without_service();
    1721           0 :  err_free_conn:
    1722           0 :         TALLOC_FREE(frame);
    1723           0 :         return err;
    1724             : }
    1725             : 
    1726             : /****************************************************************************
    1727             :   Determine whether or not a particular driver is currently assigned
    1728             :   to a printer
    1729             : ****************************************************************************/
    1730             : 
    1731           0 : bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
    1732             :                            struct dcerpc_binding_handle *b,
    1733             :                            const struct spoolss_DriverInfo8 *r)
    1734             : {
    1735           0 :         const struct loadparm_substitution *lp_sub =
    1736           0 :                 loadparm_s3_global_substitution();
    1737           0 :         int snum;
    1738           0 :         int n_services = lp_numservices();
    1739           0 :         bool in_use = false;
    1740           0 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    1741           0 :         WERROR result;
    1742             : 
    1743           0 :         if (!r) {
    1744           0 :                 return false;
    1745             :         }
    1746             : 
    1747           0 :         DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
    1748             : 
    1749             :         /* loop through the printers.tdb and check for the drivername */
    1750             : 
    1751           0 :         for (snum=0; snum<n_services && !in_use; snum++) {
    1752           0 :                 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
    1753           0 :                         continue;
    1754             :                 }
    1755             : 
    1756           0 :                 result = winreg_get_printer(mem_ctx, b,
    1757           0 :                                             lp_servicename(talloc_tos(), lp_sub, snum),
    1758             :                                             &pinfo2);
    1759           0 :                 if (!W_ERROR_IS_OK(result)) {
    1760           0 :                         continue; /* skip */
    1761             :                 }
    1762             : 
    1763           0 :                 if (strequal(r->driver_name, pinfo2->drivername)) {
    1764           0 :                         in_use = true;
    1765             :                 }
    1766             : 
    1767           0 :                 TALLOC_FREE(pinfo2);
    1768             :         }
    1769             : 
    1770           0 :         DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
    1771             : 
    1772           0 :         if ( in_use ) {
    1773           0 :                 struct spoolss_DriverInfo8 *driver = NULL;
    1774           0 :                 WERROR werr;
    1775             : 
    1776           0 :                 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
    1777             : 
    1778             :                 /* we can still remove the driver if there is one of
    1779             :                    "Windows NT x86" version 2 or 3 left */
    1780             : 
    1781           0 :                 if (strequal(SPOOLSS_ARCHITECTURE_NT_X86, r->architecture)) {
    1782           0 :                         if (r->version == 2) {
    1783           0 :                                 werr = winreg_get_driver(mem_ctx, b,
    1784           0 :                                                          r->architecture,
    1785           0 :                                                          r->driver_name,
    1786             :                                                          3, &driver);
    1787           0 :                         } else if (r->version == 3) {
    1788           0 :                                 werr = winreg_get_driver(mem_ctx, b,
    1789           0 :                                                          r->architecture,
    1790           0 :                                                          r->driver_name,
    1791             :                                                          2, &driver);
    1792             :                         } else {
    1793           0 :                                 DBG_ERR("Unknown driver version (%d)\n",
    1794             :                                         r->version);
    1795           0 :                                 werr = WERR_UNKNOWN_PRINTER_DRIVER;
    1796             :                         }
    1797           0 :                 } else if (strequal(SPOOLSS_ARCHITECTURE_x64, r->architecture)) {
    1798           0 :                         werr = winreg_get_driver(mem_ctx, b,
    1799             :                                                  SPOOLSS_ARCHITECTURE_NT_X86,
    1800           0 :                                                  r->driver_name,
    1801             :                                                  DRIVER_ANY_VERSION,
    1802             :                                                  &driver);
    1803             :                 } else {
    1804           0 :                         DBG_ERR("Unknown driver architecture: %s\n",
    1805             :                                 r->architecture);
    1806           0 :                         werr = WERR_UNKNOWN_PRINTER_DRIVER;
    1807             :                 }
    1808             : 
    1809             :                 /* now check the error code */
    1810             : 
    1811           0 :                 if ( W_ERROR_IS_OK(werr) ) {
    1812             :                         /* it's ok to remove the driver, we have other architectures left */
    1813           0 :                         in_use = false;
    1814           0 :                         talloc_free(driver);
    1815             :                 }
    1816             :         }
    1817             : 
    1818             :         /* report that the driver is not in use by default */
    1819             : 
    1820           0 :         return in_use;
    1821             : }
    1822             : 
    1823             : 
    1824             : /**********************************************************************
    1825             :  Check to see if a ogiven file is in use by *info
    1826             :  *********************************************************************/
    1827             : 
    1828           0 : static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
    1829             : {
    1830           0 :         int i = 0;
    1831             : 
    1832           0 :         if ( !info )
    1833           0 :                 return False;
    1834             : 
    1835             :         /* mz: skip files that are in the list but already deleted */
    1836           0 :         if (!file || !file[0]) {
    1837           0 :                 return false;
    1838             :         }
    1839             : 
    1840           0 :         if (strequal(file, info->driver_path))
    1841           0 :                 return True;
    1842             : 
    1843           0 :         if (strequal(file, info->data_file))
    1844           0 :                 return True;
    1845             : 
    1846           0 :         if (strequal(file, info->config_file))
    1847           0 :                 return True;
    1848             : 
    1849           0 :         if (strequal(file, info->help_file))
    1850           0 :                 return True;
    1851             : 
    1852             :         /* see of there are any dependent files to examine */
    1853             : 
    1854           0 :         if (!info->dependent_files)
    1855           0 :                 return False;
    1856             : 
    1857           0 :         while (info->dependent_files[i] && *info->dependent_files[i]) {
    1858           0 :                 if (strequal(file, info->dependent_files[i]))
    1859           0 :                         return True;
    1860           0 :                 i++;
    1861             :         }
    1862             : 
    1863           0 :         return False;
    1864             : 
    1865             : }
    1866             : 
    1867             : /**********************************************************************
    1868             :  Utility function to remove the dependent file pointed to by the
    1869             :  input parameter from the list
    1870             :  *********************************************************************/
    1871             : 
    1872           0 : static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
    1873             : {
    1874             : 
    1875             :         /* bump everything down a slot */
    1876             : 
    1877           0 :         while (files && files[idx+1]) {
    1878           0 :                 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
    1879           0 :                 idx++;
    1880             :         }
    1881             : 
    1882           0 :         files[idx] = NULL;
    1883             : 
    1884           0 :         return;
    1885             : }
    1886             : 
    1887             : /**********************************************************************
    1888             :  Check if any of the files used by src are also used by drv
    1889             :  *********************************************************************/
    1890             : 
    1891           0 : static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
    1892             :                                    struct spoolss_DriverInfo8 *src,
    1893             :                                    const struct spoolss_DriverInfo8 *drv)
    1894             : {
    1895           0 :         bool    in_use = False;
    1896           0 :         int     i = 0;
    1897             : 
    1898           0 :         if ( !src || !drv )
    1899           0 :                 return False;
    1900             : 
    1901             :         /* check each file.  Remove it from the src structure if it overlaps */
    1902             : 
    1903           0 :         if (drv_file_in_use(src->driver_path, drv)) {
    1904           0 :                 in_use = True;
    1905           0 :                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
    1906           0 :                 src->driver_path = talloc_strdup(mem_ctx, "");
    1907           0 :                 if (!src->driver_path) { return false; }
    1908             :         }
    1909             : 
    1910           0 :         if (drv_file_in_use(src->data_file, drv)) {
    1911           0 :                 in_use = True;
    1912           0 :                 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
    1913           0 :                 src->data_file = talloc_strdup(mem_ctx, "");
    1914           0 :                 if (!src->data_file) { return false; }
    1915             :         }
    1916             : 
    1917           0 :         if (drv_file_in_use(src->config_file, drv)) {
    1918           0 :                 in_use = True;
    1919           0 :                 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
    1920           0 :                 src->config_file = talloc_strdup(mem_ctx, "");
    1921           0 :                 if (!src->config_file) { return false; }
    1922             :         }
    1923             : 
    1924           0 :         if (drv_file_in_use(src->help_file, drv)) {
    1925           0 :                 in_use = True;
    1926           0 :                 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
    1927           0 :                 src->help_file = talloc_strdup(mem_ctx, "");
    1928           0 :                 if (!src->help_file) { return false; }
    1929             :         }
    1930             : 
    1931             :         /* are there any dependentfiles to examine? */
    1932             : 
    1933           0 :         if (!src->dependent_files)
    1934           0 :                 return in_use;
    1935             : 
    1936           0 :         while (src->dependent_files[i] && *src->dependent_files[i]) {
    1937           0 :                 if (drv_file_in_use(src->dependent_files[i], drv)) {
    1938           0 :                         in_use = True;
    1939           0 :                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
    1940           0 :                         trim_dependent_file(mem_ctx, src->dependent_files, i);
    1941             :                 } else
    1942           0 :                         i++;
    1943             :         }
    1944             : 
    1945           0 :         return in_use;
    1946             : }
    1947             : 
    1948             : /****************************************************************************
    1949             :   Determine whether or not a particular driver files are currently being
    1950             :   used by any other driver.
    1951             : 
    1952             :   Return value is True if any files were in use by other drivers
    1953             :   and False otherwise.
    1954             : 
    1955             :   Upon return, *info has been modified to only contain the driver files
    1956             :   which are not in use
    1957             : 
    1958             :   Fix from mz:
    1959             : 
    1960             :   This needs to check all drivers to ensure that all files in use
    1961             :   have been removed from *info, not just the ones in the first
    1962             :   match.
    1963             : ****************************************************************************/
    1964             : 
    1965           0 : bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
    1966             :                                  struct dcerpc_binding_handle *b,
    1967             :                                  struct spoolss_DriverInfo8 *info)
    1968             : {
    1969           0 :         uint32_t                                version;
    1970           0 :         struct spoolss_DriverInfo8      *driver;
    1971           0 :         bool in_use = false;
    1972           0 :         uint32_t i, num_drivers;
    1973           0 :         const char **drivers;
    1974           0 :         WERROR result;
    1975             : 
    1976           0 :         if ( !info )
    1977           0 :                 return False;
    1978             : 
    1979           0 :         version = info->version;
    1980             : 
    1981             :         /* loop over all driver versions */
    1982             : 
    1983           0 :         DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
    1984             : 
    1985             :         /* get the list of drivers */
    1986             : 
    1987           0 :         result = winreg_get_driver_list(mem_ctx, b,
    1988             :                                         info->architecture, version,
    1989             :                                         &num_drivers, &drivers);
    1990           0 :         if (!W_ERROR_IS_OK(result)) {
    1991           0 :                 return true;
    1992             :         }
    1993             : 
    1994           0 :         DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
    1995             :                      num_drivers, info->architecture, version));
    1996             : 
    1997             :         /* check each driver for overlap in files */
    1998             : 
    1999           0 :         for (i = 0; i < num_drivers; i++) {
    2000           0 :                 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
    2001             : 
    2002           0 :                 driver = NULL;
    2003             : 
    2004           0 :                 result = winreg_get_driver(mem_ctx, b,
    2005           0 :                                            info->architecture, drivers[i],
    2006             :                                            version, &driver);
    2007           0 :                 if (!W_ERROR_IS_OK(result)) {
    2008           0 :                         talloc_free(drivers);
    2009           0 :                         return True;
    2010             :                 }
    2011             : 
    2012             :                 /* check if d2 uses any files from d1 */
    2013             :                 /* only if this is a different driver than the one being deleted */
    2014             : 
    2015           0 :                 if (!strequal(info->driver_name, driver->driver_name)) {
    2016           0 :                         if (trim_overlap_drv_files(mem_ctx, info, driver)) {
    2017             :                                 /* mz: Do not instantly return -
    2018             :                                  * we need to ensure this file isn't
    2019             :                                  * also in use by other drivers. */
    2020           0 :                                 in_use = true;
    2021             :                         }
    2022             :                 }
    2023             : 
    2024           0 :                 talloc_free(driver);
    2025             :         }
    2026             : 
    2027           0 :         talloc_free(drivers);
    2028             : 
    2029           0 :         DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
    2030             : 
    2031           0 :         return in_use;
    2032             : }
    2033             : 
    2034           0 : static NTSTATUS driver_unlink_internals(connection_struct *conn,
    2035             :                                         const char *short_arch,
    2036             :                                         int vers,
    2037             :                                         const char *fname)
    2038             : {
    2039           0 :         TALLOC_CTX *tmp_ctx = talloc_new(conn);
    2040           0 :         struct smb_filename *smb_fname = NULL;
    2041           0 :         char *print_dlr_path;
    2042           0 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    2043             : 
    2044           0 :         print_dlr_path = talloc_asprintf(tmp_ctx, "%s/%d/%s",
    2045             :                                          short_arch, vers, fname);
    2046           0 :         if (print_dlr_path == NULL) {
    2047           0 :                 goto err_out;
    2048             :         }
    2049             : 
    2050           0 :         status = synthetic_pathref(tmp_ctx,
    2051             :                                    conn->cwd_fsp,
    2052             :                                    print_dlr_path,
    2053             :                                    NULL,
    2054             :                                    NULL,
    2055             :                                    0,
    2056             :                                    0,
    2057             :                                    &smb_fname);
    2058           0 :         if (!NT_STATUS_IS_OK(status)) {
    2059           0 :                 goto err_out;
    2060             :         }
    2061             : 
    2062           0 :         status = unlink_internals(conn, NULL, 0, NULL, smb_fname);
    2063           0 : err_out:
    2064           0 :         talloc_free(tmp_ctx);
    2065           0 :         return status;
    2066             : }
    2067             : 
    2068             : /****************************************************************************
    2069             :   Actually delete the driver files.  Make sure that
    2070             :   printer_driver_files_in_use() return False before calling
    2071             :   this.
    2072             : ****************************************************************************/
    2073             : 
    2074           0 : bool delete_driver_files(const struct auth_session_info *session_info,
    2075             :                          const struct spoolss_DriverInfo8 *r)
    2076             : {
    2077           0 :         TALLOC_CTX *frame = talloc_stackframe();
    2078           0 :         const struct loadparm_substitution *lp_sub =
    2079           0 :                 loadparm_s3_global_substitution();
    2080           0 :         const char *short_arch;
    2081           0 :         struct conn_struct_tos *c = NULL;
    2082           0 :         connection_struct *conn = NULL;
    2083           0 :         NTSTATUS nt_status;
    2084           0 :         char *printdollar = NULL;
    2085           0 :         int printdollar_snum;
    2086           0 :         bool ret = false;
    2087             : 
    2088           0 :         if (!r) {
    2089           0 :                 TALLOC_FREE(frame);
    2090           0 :                 return false;
    2091             :         }
    2092             : 
    2093           0 :         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
    2094             :                 r->driver_name, r->version));
    2095             : 
    2096           0 :         printdollar_snum = find_service(frame, "print$", &printdollar);
    2097           0 :         if (!printdollar) {
    2098           0 :                 TALLOC_FREE(frame);
    2099           0 :                 return false;
    2100             :         }
    2101           0 :         if (printdollar_snum == -1) {
    2102           0 :                 TALLOC_FREE(frame);
    2103           0 :                 return false;
    2104             :         }
    2105             : 
    2106           0 :         nt_status = create_conn_struct_tos_cwd(global_messaging_context(),
    2107             :                                                printdollar_snum,
    2108           0 :                                                lp_path(frame, lp_sub, printdollar_snum),
    2109             :                                                session_info,
    2110             :                                                &c);
    2111           0 :         if (!NT_STATUS_IS_OK(nt_status)) {
    2112           0 :                 DEBUG(0,("delete_driver_files: create_conn_struct "
    2113             :                          "returned %s\n", nt_errstr(nt_status)));
    2114           0 :                 TALLOC_FREE(frame);
    2115           0 :                 return false;
    2116             :         }
    2117           0 :         conn = c->conn;
    2118             : 
    2119           0 :         nt_status = set_conn_force_user_group(conn, printdollar_snum);
    2120           0 :         if (!NT_STATUS_IS_OK(nt_status)) {
    2121           0 :                 DEBUG(0, ("failed set force user / group\n"));
    2122           0 :                 ret = false;
    2123           0 :                 goto err_free_conn;
    2124             :         }
    2125             : 
    2126           0 :         if (!become_user_without_service_by_session(conn, session_info)) {
    2127           0 :                 DEBUG(0, ("failed to become user\n"));
    2128           0 :                 ret = false;
    2129           0 :                 goto err_free_conn;
    2130             :         }
    2131             : 
    2132           0 :         if ( !CAN_WRITE(conn) ) {
    2133           0 :                 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
    2134           0 :                 ret = false;
    2135           0 :                 goto err_out;
    2136             :         }
    2137             : 
    2138           0 :         short_arch = get_short_archi(r->architecture);
    2139           0 :         if (short_arch == NULL) {
    2140           0 :                 DEBUG(0, ("bad architecture %s\n", r->architecture));
    2141           0 :                 ret = false;
    2142           0 :                 goto err_out;
    2143             :         }
    2144             : 
    2145             :         /* now delete the files */
    2146             : 
    2147           0 :         if (r->driver_path && r->driver_path[0]) {
    2148           0 :                 DEBUG(10,("deleting driverfile [%s]\n", r->driver_path));
    2149           0 :                 driver_unlink_internals(conn, short_arch, r->version, r->driver_path);
    2150             :         }
    2151             : 
    2152           0 :         if (r->config_file && r->config_file[0]) {
    2153           0 :                 DEBUG(10,("deleting configfile [%s]\n", r->config_file));
    2154           0 :                 driver_unlink_internals(conn, short_arch, r->version, r->config_file);
    2155             :         }
    2156             : 
    2157           0 :         if (r->data_file && r->data_file[0]) {
    2158           0 :                 DEBUG(10,("deleting datafile [%s]\n", r->data_file));
    2159           0 :                 driver_unlink_internals(conn, short_arch, r->version, r->data_file);
    2160             :         }
    2161             : 
    2162           0 :         if (r->help_file && r->help_file[0]) {
    2163           0 :                 DEBUG(10,("deleting helpfile [%s]\n", r->help_file));
    2164           0 :                 driver_unlink_internals(conn, short_arch, r->version, r->help_file);
    2165             :         }
    2166             : 
    2167           0 :         if (r->dependent_files) {
    2168           0 :                 int i = 0;
    2169           0 :                 while (r->dependent_files[i] && r->dependent_files[i][0]) {
    2170           0 :                         DEBUG(10,("deleting dependent file [%s]\n", r->dependent_files[i]));
    2171           0 :                         driver_unlink_internals(conn, short_arch, r->version, r->dependent_files[i]);
    2172           0 :                         i++;
    2173             :                 }
    2174             :         }
    2175             : 
    2176           0 :         ret = true;
    2177           0 :  err_out:
    2178           0 :         unbecome_user_without_service();
    2179           0 :  err_free_conn:
    2180           0 :         TALLOC_FREE(frame);
    2181           0 :         return ret;
    2182             : }
    2183             : 
    2184             : /* error code:
    2185             :         0: everything OK
    2186             :         1: level not implemented
    2187             :         2: file doesn't exist
    2188             :         3: can't allocate memory
    2189             :         4: can't free memory
    2190             :         5: non existent struct
    2191             : */
    2192             : 
    2193             : /*
    2194             :         A printer and a printer driver are 2 different things.
    2195             :         NT manages them separately, Samba does the same.
    2196             :         Why ? Simply because it's easier and it makes sense !
    2197             : 
    2198             :         Now explanation: You have 3 printers behind your samba server,
    2199             :         2 of them are the same make and model (laser A and B). But laser B
    2200             :         has an 3000 sheet feeder and laser A doesn't such an option.
    2201             :         Your third printer is an old dot-matrix model for the accounting :-).
    2202             : 
    2203             :         If the /usr/local/samba/lib directory (default dir), you will have
    2204             :         5 files to describe all of this.
    2205             : 
    2206             :         3 files for the printers (1 by printer):
    2207             :                 NTprinter_laser A
    2208             :                 NTprinter_laser B
    2209             :                 NTprinter_accounting
    2210             :         2 files for the drivers (1 for the laser and 1 for the dot matrix)
    2211             :                 NTdriver_printer model X
    2212             :                 NTdriver_printer model Y
    2213             : 
    2214             : jfm: I should use this comment for the text file to explain
    2215             :         same thing for the forms BTW.
    2216             :         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
    2217             : 
    2218             : */
    2219             : 
    2220             : /* Convert generic access rights to printer object specific access rights.
    2221             :    It turns out that NT4 security descriptors use generic access rights and
    2222             :    NT5 the object specific ones. */
    2223             : 
    2224           4 : void map_printer_permissions(struct security_descriptor *sd)
    2225             : {
    2226           0 :         uint32_t i;
    2227             : 
    2228          32 :         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
    2229          28 :                 se_map_generic(&sd->dacl->aces[i].access_mask,
    2230             :                                &printer_generic_mapping);
    2231             :         }
    2232           4 : }
    2233             : 
    2234           0 : void map_job_permissions(struct security_descriptor *sd)
    2235             : {
    2236           0 :         uint32_t i;
    2237             : 
    2238           0 :         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
    2239           0 :                 se_map_generic(&sd->dacl->aces[i].access_mask,
    2240             :                                &job_generic_mapping);
    2241             :         }
    2242           0 : }
    2243             : 
    2244             : 
    2245             : /****************************************************************************
    2246             :  Check a user has permissions to perform the given operation.  We use the
    2247             :  permission constants defined in include/rpc_spoolss.h to check the various
    2248             :  actions we perform when checking printer access.
    2249             : 
    2250             :    PRINTER_ACCESS_ADMINISTER:
    2251             :        print_queue_pause, print_queue_resume, update_printer_sec,
    2252             :        update_printer, spoolss_addprinterex_level_2,
    2253             :        _spoolss_setprinterdata
    2254             : 
    2255             :    PRINTER_ACCESS_USE:
    2256             :        print_job_start
    2257             : 
    2258             :    JOB_ACCESS_ADMINISTER:
    2259             :        print_job_delete, print_job_pause, print_job_resume,
    2260             :        print_queue_purge
    2261             : 
    2262             :   Try access control in the following order (for performance reasons):
    2263             :     1)  root and SE_PRINT_OPERATOR can do anything (easy check)
    2264             :     2)  check security descriptor (bit comparisons in memory)
    2265             :     3)  "printer admins" (may result in numerous calls to winbind)
    2266             : 
    2267             :  ****************************************************************************/
    2268        1294 : WERROR print_access_check(const struct auth_session_info *session_info,
    2269             :                           struct messaging_context *msg_ctx, int snum,
    2270             :                           int access_type)
    2271             : {
    2272        1294 :         struct spoolss_security_descriptor *secdesc = NULL;
    2273           0 :         const struct loadparm_substitution *lp_sub =
    2274        1294 :                 loadparm_s3_global_substitution();
    2275           0 :         uint32_t access_granted;
    2276           0 :         size_t sd_size;
    2277           0 :         NTSTATUS status;
    2278           0 :         WERROR result;
    2279           0 :         const char *pname;
    2280        1294 :         TALLOC_CTX *mem_ctx = NULL;
    2281             : 
    2282             :         /* If user is NULL then use the current_user structure */
    2283             : 
    2284             :         /* Always allow root or SE_PRINT_OPERATROR to do anything */
    2285             : 
    2286        1294 :         if ((session_info->unix_token->uid == sec_initial_uid())
    2287           4 :             || security_token_has_privilege(session_info->security_token,
    2288             :                                             SEC_PRIV_PRINT_OPERATOR)) {
    2289        1290 :                 return WERR_OK;
    2290             :         }
    2291             : 
    2292             :         /* Get printer name */
    2293             : 
    2294           4 :         pname = lp_printername(talloc_tos(), lp_sub, snum);
    2295             : 
    2296           4 :         if (!pname || !*pname) {
    2297           0 :                 return WERR_ACCESS_DENIED;
    2298             :         }
    2299             : 
    2300             :         /* Get printer security descriptor */
    2301             : 
    2302           4 :         if(!(mem_ctx = talloc_init("print_access_check"))) {
    2303           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    2304             :         }
    2305             : 
    2306           4 :         result = winreg_get_printer_secdesc_internal(mem_ctx,
    2307             :                                             get_session_info_system(),
    2308             :                                             msg_ctx,
    2309             :                                             pname,
    2310             :                                             &secdesc);
    2311           4 :         if (!W_ERROR_IS_OK(result)) {
    2312           0 :                 talloc_destroy(mem_ctx);
    2313           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    2314             :         }
    2315             : 
    2316           4 :         if (access_type == JOB_ACCESS_ADMINISTER) {
    2317           0 :                 struct spoolss_security_descriptor *parent_secdesc = secdesc;
    2318             : 
    2319             :                 /* Create a child security descriptor to check permissions
    2320             :                    against.  This is because print jobs are child objects
    2321             :                    objects of a printer. */
    2322           0 :                 status = se_create_child_secdesc(mem_ctx,
    2323             :                                                  &secdesc,
    2324             :                                                  &sd_size,
    2325             :                                                  parent_secdesc,
    2326           0 :                                                  parent_secdesc->owner_sid,
    2327           0 :                                                  parent_secdesc->group_sid,
    2328             :                                                  false);
    2329           0 :                 if (!NT_STATUS_IS_OK(status)) {
    2330           0 :                         talloc_destroy(mem_ctx);
    2331           0 :                         return ntstatus_to_werror(status);
    2332             :                 }
    2333             : 
    2334           0 :                 map_job_permissions(secdesc);
    2335             :         } else {
    2336           4 :                 map_printer_permissions(secdesc);
    2337             :         }
    2338             : 
    2339             :         /* Check access */
    2340           4 :         status = se_access_check(secdesc, session_info->security_token, access_type,
    2341             :                                  &access_granted);
    2342             : 
    2343           4 :         DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
    2344             : 
    2345           4 :         talloc_destroy(mem_ctx);
    2346             : 
    2347           4 :         return ntstatus_to_werror(status);
    2348             : }
    2349             : 
    2350             : /****************************************************************************
    2351             :  Check the time parameters allow a print operation.
    2352             : *****************************************************************************/
    2353             : 
    2354         668 : bool print_time_access_check(const struct auth_session_info *session_info,
    2355             :                              struct messaging_context *msg_ctx,
    2356             :                              const char *servicename)
    2357             : {
    2358         668 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    2359           0 :         WERROR result;
    2360         668 :         bool ok = False;
    2361         668 :         time_t now = time(NULL);
    2362           0 :         struct tm *t;
    2363           0 :         uint32_t mins;
    2364             : 
    2365         668 :         result = winreg_get_printer_internal(NULL, session_info, msg_ctx,
    2366             :                                     servicename, &pinfo2);
    2367         668 :         if (!W_ERROR_IS_OK(result)) {
    2368           0 :                 return False;
    2369             :         }
    2370             : 
    2371         668 :         if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
    2372         668 :                 ok = True;
    2373             :         }
    2374             : 
    2375         668 :         t = gmtime(&now);
    2376         668 :         mins = (uint32_t)t->tm_hour*60 + (uint32_t)t->tm_min;
    2377             : 
    2378         668 :         if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
    2379           0 :                 ok = True;
    2380             :         }
    2381             : 
    2382         668 :         TALLOC_FREE(pinfo2);
    2383             : 
    2384         668 :         if (!ok) {
    2385           0 :                 errno = EACCES;
    2386             :         }
    2387             : 
    2388         668 :         return ok;
    2389             : }
    2390             : 
    2391           0 : void nt_printer_remove(TALLOC_CTX *mem_ctx,
    2392             :                         const struct auth_session_info *session_info,
    2393             :                         struct messaging_context *msg_ctx,
    2394             :                         const char *printer)
    2395             : {
    2396           0 :         WERROR result;
    2397             : 
    2398           0 :         result = winreg_delete_printer_key_internal(mem_ctx, session_info, msg_ctx,
    2399             :                                            printer, "");
    2400           0 :         if (!W_ERROR_IS_OK(result)) {
    2401           0 :                 DEBUG(0, ("nt_printer_remove: failed to remove printer %s: "
    2402             :                 "%s\n", printer, win_errstr(result)));
    2403             :         }
    2404           0 : }
    2405             : 
    2406           0 : void nt_printer_add(TALLOC_CTX *mem_ctx,
    2407             :                     const struct auth_session_info *session_info,
    2408             :                     struct messaging_context *msg_ctx,
    2409             :                     const char *printer)
    2410             : {
    2411           0 :         WERROR result;
    2412             : 
    2413           0 :         result = winreg_create_printer_internal(mem_ctx, session_info, msg_ctx,
    2414             :                                                 printer);
    2415           0 :         if (!W_ERROR_IS_OK(result)) {
    2416           0 :                 DEBUG(0, ("nt_printer_add: failed to add printer %s: %s\n",
    2417             :                           printer, win_errstr(result)));
    2418             :         }
    2419           0 : }

Generated by: LCOV version 1.14