Fix from Martin Zielinski <mz@seh.de>. Don't delete files when
[samba.git] / source / printing / nt_printing.c
index f83f898cc03118e027d602375d9c900456e15c22..c31a48c58595664db87eb6cbf01d2fbe670a6676 100644 (file)
@@ -344,7 +344,6 @@ static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
        int result, i;
        uint32 sd_size;
        size_t size_new_sec;
-       DOM_SID sid;
 
        if (!data.dptr || data.dsize == 0) {
                return 0;
@@ -358,7 +357,7 @@ static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
 
        ZERO_STRUCT( ps );
 
-       prs_init( &ps, 0, ctx, UNMARSHALL );
+       prs_init_empty( &ps, ctx, UNMARSHALL );
        prs_give_memory( &ps, (char *)data.dptr, data.dsize, False );
 
        if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_orig, &ps, 1 ) ) {
@@ -405,10 +404,10 @@ static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
 
        /* create a new SEC_DESC with the appropriate owner and group SIDs */
 
-       string_to_sid(&sid, "S-1-5-32-544" );
        new_sec = make_sec_desc( ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
-               &sid, &sid,
-               NULL, NULL, &size_new_sec );
+                                &global_sid_Builtin_Administrators,
+                                &global_sid_Builtin_Administrators,
+                                NULL, NULL, &size_new_sec );
        if (!new_sec) {
                prs_mem_free( &ps );
                return 0;
@@ -429,8 +428,12 @@ static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
 
        /* store it back */
        
-       sd_size = sec_desc_size(sd_store->sd) + sizeof(SEC_DESC_BUF);
-       prs_init(&ps, sd_size, ctx, MARSHALL);
+       sd_size = ndr_size_security_descriptor(sd_store->sd, 0)
+               + sizeof(SEC_DESC_BUF);
+       if ( !prs_init(&ps, sd_size, ctx, MARSHALL) ) {
+               DEBUG(0,("sec_desc_upg_fn: Failed to allocate prs memory for %s\n", key.dptr ));
+               return 0;
+       }
 
        if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_store, &ps, 1 ) ) {
                DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
@@ -1096,7 +1099,7 @@ static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32
        }
 
        /* Skip OEM header (if any) and the DOS stub to start of Windows header */
-       if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
+       if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
                DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
                                fname, errno));
                /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
@@ -1117,7 +1120,7 @@ static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32
                unsigned int section_table_bytes;
 
                /* Just skip over optional header to get to section table */
-               if (SMB_VFS_LSEEK(fsp, fsp->fh->fd,
+               if (SMB_VFS_LSEEK(fsp,
                                SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
                                SEEK_CUR) == (SMB_OFF_T)-1) {
                        DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
@@ -1163,7 +1166,7 @@ static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32
                                }
 
                                /* Seek to the start of the .rsrc section info */
-                               if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
+                               if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
                                        DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
                                                        fname, errno));
                                        goto error_exit;
@@ -1259,7 +1262,7 @@ static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32
                                 * twice, as it is simpler to read the code. */
                                if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
                                        /* Compute skip alignment to next long address */
-                                       int skip = -(SMB_VFS_LSEEK(fsp, fsp->fh->fd, 0, SEEK_CUR) - (byte_count - i) +
+                                       int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
                                                                 sizeof(VS_SIGNATURE)) & 3;
                                        if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
 
@@ -1359,7 +1362,7 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
                        DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
                                         old_file));
                        use_version = false;
-                       if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) {
+                       if (SMB_VFS_FSTAT(fsp, &st) == -1) {
                                 goto error_exit;
                        }
                        old_create_time = st.st_mtime;
@@ -1399,7 +1402,7 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
                        DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
                                         new_file));
                        use_version = false;
-                       if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) {
+                       if (SMB_VFS_FSTAT(fsp, &st) == -1) {
                                goto error_exit;
                        }
                        new_create_time = st.st_mtime;
@@ -1866,7 +1869,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                goto err_exit;
        }
 
-       create_directory(conn, new_dir);
+       create_directory(conn, NULL, new_dir);
 
        /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
         * listed for this driver which has already been moved, skip it (note:
@@ -3314,8 +3317,13 @@ static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
 
        /* publish it */
        ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
-       if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT)
+       if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
+               int i;
+               for (i=0; mods[i] != 0; i++)
+                       ;
+               mods[i] = (LDAPMod *)-1;
                ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
+       }
 
        if (!ADS_ERR_OK(ads_rc))
                DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
@@ -3965,7 +3973,11 @@ static void map_to_os2_driver(fstring drivername)
 /****************************************************************************
  Get a default printer info 2 struct.
 ****************************************************************************/
-static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char* sharename)
+
+static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
+                               const char *servername,
+                               const char* sharename,
+                               bool get_loc_com)
 {
        int snum = lp_servicenumber(sharename);
 
@@ -3992,7 +4004,7 @@ static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info, const char
        fstrcpy(info->datatype, "RAW");
 
 #ifdef HAVE_CUPS
-       if ( (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {           
+       if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {             
                /* Pull the location and comment strings from cups if we don't
                   already have one */
                if ( !strlen(info->location) || !strlen(info->comment) )
@@ -4041,7 +4053,11 @@ fail:
 
 /****************************************************************************
 ****************************************************************************/
-static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char *sharename)
+
+static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
+                               const char *servername,
+                               const char *sharename,
+                               bool get_loc_com)
 {
        int len = 0;
        int snum = lp_servicenumber(sharename);
@@ -4054,7 +4070,8 @@ static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info, const char *servern
 
        dbuf = tdb_fetch(tdb_printers, kbuf);
        if (!dbuf.dptr) {
-               return get_a_printer_2_default(info, servername, sharename);
+               return get_a_printer_2_default(info, servername,
+                                       sharename, get_loc_com);
        }
 
        len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
@@ -4102,7 +4119,7 @@ static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info, const char *servern
        fstrcpy(info->printername, printername);
 
 #ifdef HAVE_CUPS
-       if ( (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {           
+       if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
                /* Pull the location and comment strings from cups if we don't
                   already have one */
                if ( !strlen(info->location) || !strlen(info->comment) )
@@ -4545,7 +4562,7 @@ static bool convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uin
 
        ZERO_STRUCT(devmode);
 
-       prs_init(&ps, 0, ctx, UNMARSHALL);
+       prs_init_empty(&ps, ctx, UNMARSHALL);
        ps.data_p      = (char *)data;
        ps.buffer_size = data_len;
 
@@ -4686,8 +4703,8 @@ WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *dat
 
 ****************************************************************************/
 
-WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, 
-                       const char *sharename)
+static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, 
+                       const char *sharename, bool get_loc_com)
 {
        WERROR result;
        fstring servername;
@@ -4715,11 +4732,11 @@ WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_print
                                                    sizeof(servername)-1 );
                        }
 
-                       result = get_a_printer_2( (*pp_printer)->info_2, servername, sharename );
-       
-                       
+                       result = get_a_printer_2( (*pp_printer)->info_2,
+                                       servername, sharename, get_loc_com);
+
                        /* we have a new printer now.  Save it with this handle */
-                       
+
                        if ( !W_ERROR_IS_OK(result) ) {
                                TALLOC_FREE( *pp_printer );
                                DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", 
@@ -4739,6 +4756,24 @@ WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_print
        return WERR_OK;
 }
 
+WERROR get_a_printer( Printer_entry *print_hnd,
+                       NT_PRINTER_INFO_LEVEL **pp_printer,
+                       uint32 level,
+                       const char *sharename)
+{
+       return get_a_printer_internal(print_hnd, pp_printer, level,
+                                       sharename, true);
+}
+
+WERROR get_a_printer_search( Printer_entry *print_hnd,
+                       NT_PRINTER_INFO_LEVEL **pp_printer,
+                       uint32 level,
+                       const char *sharename)
+{
+       return get_a_printer_internal(print_hnd, pp_printer, level,
+                                       sharename, false);
+}
+
 /****************************************************************************
  Deletes a NT_PRINTER_INFO_LEVEL struct.
 ****************************************************************************/
@@ -4957,10 +4992,15 @@ bool printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
 static bool drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
 {
        int i = 0;
-       
+
        if ( !info )
                return False;
-               
+
+       /* mz: skip files that are in the list but already deleted */
+       if (!file || !file[0]) {
+               return false;
+       }
+
        if ( strequal(file, info->driverpath) )
                return True;
 
@@ -5073,6 +5113,12 @@ static bool trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
   
   Upon return, *info has been modified to only contain the driver files
   which are not in use
+
+  Fix from mz:
+
+  This needs to check all drivers to ensure that all files in use
+  have been removed from *info, not just the ones in the first
+  match.
 ****************************************************************************/
 
 bool printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
@@ -5082,7 +5128,8 @@ bool printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
        uint32                          version;
        fstring                         *list = NULL;
        NT_PRINTER_DRIVER_INFO_LEVEL    driver;
-       
+       bool in_use = false;
+
        if ( !info )
                return False;
        
@@ -5117,9 +5164,10 @@ bool printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
                        
                if ( !strequal(info->name, driver.info_3->name) ) {
                        if ( trim_overlap_drv_files(info, driver.info_3) ) {
-                               free_a_printer_driver(driver, 3);
-                               SAFE_FREE( list );
-                               return True;
+                               /* mz: Do not instantly return -
+                                * we need to ensure this file isn't
+                                * also in use by other drivers. */
+                               in_use = true;
                        }
                }
 
@@ -5135,7 +5183,7 @@ bool printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
        if ( DEBUGLEVEL >= 20 )
                dump_a_printer_driver( driver, 3 );
 
-       return False;
+       return in_use;
 }
 
 /****************************************************************************
@@ -5325,6 +5373,7 @@ WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
        SEC_DESC_BUF *new_secdesc_ctr = NULL;
        SEC_DESC_BUF *old_secdesc_ctr = NULL;
        prs_struct ps;
+       bool prs_init_done = false;
        TALLOC_CTX *mem_ctx = NULL;
        TDB_DATA kbuf;
        WERROR status;
@@ -5389,8 +5438,15 @@ WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
 
        /* Store the security descriptor in a tdb */
 
-       prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sd) +
-                sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
+       if (!prs_init(&ps,
+               (uint32)ndr_size_security_descriptor(new_secdesc_ctr->sd, 0)
+               + sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL) ) {
+               status = WERR_NOMEM;
+               goto out;
+       }
+
+
+       prs_init_done = true;
 
        if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
                             &ps, 1)) {
@@ -5411,7 +5467,9 @@ WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
 
  out:
 
-       prs_mem_free(&ps);
+       if (prs_init_done) {
+               prs_mem_free(&ps);
+       }
        if (mem_ctx)
                talloc_destroy(mem_ctx);
        return status;
@@ -5534,8 +5592,9 @@ bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **s
 
                /* Save default security descriptor for later */
 
-               prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sd) +
-                               sizeof(SEC_DESC_BUF), ctx, MARSHALL);
+               if (!prs_init(&ps, (uint32)ndr_size_security_descriptor((*secdesc_ctr)->sd, 0) +
+                       sizeof(SEC_DESC_BUF), ctx, MARSHALL))
+                       return False;
 
                if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
                        tdb_prs_store(tdb_printers, kbuf, &ps);