s3-printing: eliminate another non sec_initial_uid using security check.
[ira/wip.git] / source3 / printing / nt_printing.c
index a99485d3814b4d4de7f6faad801877bafdfde4f1..3e206becf4a930e16799a9398b7c4d4861aa525a 100644 (file)
@@ -204,21 +204,7 @@ static const nt_forms_struct default_forms[] = {
        {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
 };
 
-struct table_node {
-       const char      *long_archi;
-       const char      *short_archi;
-       int     version;
-};
-
-#define SPL_ARCH_WIN40         "WIN40"
-#define SPL_ARCH_W32X86                "W32X86"
-#define SPL_ARCH_W32MIPS       "W32MIPS"
-#define SPL_ARCH_W32ALPHA      "W32ALPHA"
-#define SPL_ARCH_W32PPC                "W32PPC"
-#define SPL_ARCH_IA64          "IA64"
-#define SPL_ARCH_X64           "x64"
-
-static const struct table_node archi_table[]= {
+static const struct print_architecture_table_node archi_table[]= {
 
        {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
        {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
@@ -648,25 +634,30 @@ bool nt_printing_init(struct messaging_context *msg_ctx)
  Function to allow filename parsing "the old way".
 ********************************************************************/
 
-static char *driver_unix_convert(connection_struct *conn,
-               const char *old_name,
-               SMB_STRUCT_STAT *pst)
+static NTSTATUS driver_unix_convert(connection_struct *conn,
+                                   const char *old_name,
+                                   struct smb_filename **smb_fname)
 {
+       NTSTATUS status;
        TALLOC_CTX *ctx = talloc_tos();
        char *name = talloc_strdup(ctx, old_name);
-       char *new_name = NULL;
 
        if (!name) {
-               return NULL;
+               return NT_STATUS_NO_MEMORY;
        }
        unix_format(name);
        name = unix_clean_name(ctx, name);
        if (!name) {
-               return NULL;
+               return NT_STATUS_NO_MEMORY;
        }
        trim_string(name,"/","/");
-       unix_convert(ctx,conn, name, false, &new_name, NULL, pst);
-       return new_name;
+
+       status = unix_convert(ctx, conn, name, smb_fname, 0);
+       if (!NT_STATUS_IS_OK(status)) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       return NT_STATUS_OK;
 }
 
 /*******************************************************************
@@ -745,7 +736,7 @@ int get_builtin_ntforms(nt_forms_struct **list)
        if (!*list) {
                return 0;
        }
-       return sizeof(default_forms) / sizeof(default_forms[0]);
+       return ARRAY_SIZE(default_forms);
 }
 
 /****************************************************************************
@@ -754,18 +745,17 @@ int get_builtin_ntforms(nt_forms_struct **list)
 
 bool get_a_builtin_ntform_by_string(const char *form_name, nt_forms_struct *form)
 {
-       int i,count;
+       int i;
        DEBUGADD(6,("Looking for builtin form %s \n", form_name));
-       count = sizeof(default_forms) / sizeof(default_forms[0]);
-       for (i=0;i<count;i++) {
+       for (i=0; i<ARRAY_SIZE(default_forms); i++) {
                if (strequal(form_name,default_forms[i].name)) {
                        DEBUGADD(6,("Found builtin form %s \n", form_name));
                        memcpy(form,&default_forms[i],sizeof(*form));
-                       break;
+                       return true;
                }
        }
 
-       return (i !=count);
+       return false;
 }
 
 /****************************************************************************
@@ -1287,7 +1277,6 @@ the modification date). Otherwise chose the numerically larger version number.
 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
 {
        bool use_version = true;
-       char *filepath = NULL;
 
        uint32 new_major;
        uint32 new_minor;
@@ -1297,20 +1286,20 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
        uint32 old_minor;
        time_t old_create_time;
 
+       struct smb_filename *smb_fname = NULL;
        files_struct    *fsp = NULL;
        SMB_STRUCT_STAT st;
-       SMB_STRUCT_STAT stat_buf;
 
        NTSTATUS status;
+       int ret;
 
        SET_STAT_INVALID(st);
-       SET_STAT_INVALID(stat_buf);
        new_create_time = (time_t)0;
        old_create_time = (time_t)0;
 
        /* Get file version info (if available) for previous file (if it exists) */
-       filepath = driver_unix_convert(conn,old_file,&stat_buf);
-       if (!filepath) {
+       status = driver_unix_convert(conn, old_file, &smb_fname);
+       if (!NT_STATUS_IS_OK(status)) {
                goto error_exit;
        }
 
@@ -1318,8 +1307,7 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
                conn,                                   /* conn */
                NULL,                                   /* req */
                0,                                      /* root_dir_fid */
-               filepath,                               /* fname */
-               0,                                      /* create_file_flags */
+               smb_fname,                              /* fname */
                FILE_GENERIC_READ,                      /* access_mask */
                FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
                FILE_OPEN,                              /* create_disposition*/
@@ -1330,17 +1318,18 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
                NULL,                                   /* sd */
                NULL,                                   /* ea_list */
                &fsp,                                   /* result */
-               NULL,                                   /* pinfo */
-               &stat_buf);                             /* psbuf */
+               NULL);                                  /* pinfo */
 
        if (!NT_STATUS_IS_OK(status)) {
                /* Old file not found, so by definition new file is in fact newer */
-               DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
-                               filepath, errno));
-               return 1;
+               DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
+                         "errno = %d\n", smb_fname_str_dbg(smb_fname),
+                         errno));
+               ret = 1;
+               goto done;
 
        } else {
-               int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
+               ret = get_file_version(fsp, old_file, &old_major, &old_minor);
                if (ret == -1) {
                        goto error_exit;
                }
@@ -1352,7 +1341,7 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
                        if (SMB_VFS_FSTAT(fsp, &st) == -1) {
                                 goto error_exit;
                        }
-                       old_create_time = st.st_mtime;
+                       old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
                        DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
                                (long)old_create_time));
                }
@@ -1361,8 +1350,8 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
        fsp = NULL;
 
        /* Get file version info (if available) for new file */
-       filepath = driver_unix_convert(conn,new_file,&stat_buf);
-       if (!filepath) {
+       status = driver_unix_convert(conn, new_file, &smb_fname);
+       if (!NT_STATUS_IS_OK(status)) {
                goto error_exit;
        }
 
@@ -1370,8 +1359,7 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
                conn,                                   /* conn */
                NULL,                                   /* req */
                0,                                      /* root_dir_fid */
-               filepath,                               /* fname */
-               0,                                      /* create_file_flags */
+               smb_fname,                              /* fname */
                FILE_GENERIC_READ,                      /* access_mask */
                FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
                FILE_OPEN,                              /* create_disposition*/
@@ -1382,17 +1370,16 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
                NULL,                                   /* sd */
                NULL,                                   /* ea_list */
                &fsp,                                   /* result */
-               NULL,                                   /* pinfo */
-               &stat_buf);                             /* psbuf */
+               NULL);                                  /* pinfo */
 
        if (!NT_STATUS_IS_OK(status)) {
                /* New file not found, this shouldn't occur if the caller did its job */
-               DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
-                               filepath, errno));
+               DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
+                        "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
                goto error_exit;
 
        } else {
-               int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
+               ret = get_file_version(fsp, new_file, &new_major, &new_minor);
                if (ret == -1) {
                        goto error_exit;
                }
@@ -1404,7 +1391,7 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
                        if (SMB_VFS_FSTAT(fsp, &st) == -1) {
                                goto error_exit;
                        }
-                       new_create_time = st.st_mtime;
+                       new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
                        DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
                                (long)new_create_time));
                }
@@ -1418,29 +1405,36 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
                        (new_major == old_major && new_minor > old_minor)) {
 
                        DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
-                       return 1;
+                       ret = 1;
+                       goto done;
                }
                else {
                        DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
-                       return 0;
+                       ret = 0;
+                       goto done;
                }
 
        } else {
                /* Compare modification time/dates and choose the newest time/date */
                if (new_create_time > old_create_time) {
                        DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
-                       return 1;
+                       ret = 1;
+                       goto done;
                }
                else {
                        DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
-                       return 0;
+                       ret = 0;
+                       goto done;
                }
        }
 
-       error_exit:
-               if(fsp)
-                       close_file(NULL, fsp, NORMAL_CLOSE);
-               return -1;
+ error_exit:
+       if(fsp)
+               close_file(NULL, fsp, NORMAL_CLOSE);
+       ret = -1;
+ done:
+       TALLOC_FREE(smb_fname);
+       return ret;
 }
 
 /****************************************************************************
@@ -1453,17 +1447,15 @@ static uint32 get_correct_cversion(struct pipes_struct *p,
 {
        int               cversion;
        NTSTATUS          nt_status;
-       char *driverpath = NULL;
+       struct smb_filename *smb_fname = NULL;
+       char *driverpath = NULL;
        files_struct      *fsp = NULL;
-       SMB_STRUCT_STAT   st;
        connection_struct *conn = NULL;
        NTSTATUS status;
        char *oldcwd;
        fstring printdollar;
        int printdollar_snum;
 
-       SET_STAT_INVALID(st);
-
        *perr = WERR_INVALID_PARAM;
 
        /* If architecture is Windows 95/98/ME, the version is always 0. */
@@ -1509,13 +1501,14 @@ static uint32 get_correct_cversion(struct pipes_struct *p,
                goto error_exit;
        }
 
-       driverpath = driver_unix_convert(conn,driverpath,&st);
-       if (!driverpath) {
-               *perr = WERR_NOMEM;
+       nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               *perr = ntstatus_to_werror(nt_status);
                goto error_exit;
        }
 
-       if (!vfs_file_exist(conn, driverpath, &st)) {
+       nt_status = vfs_file_exist(conn, smb_fname);
+       if (!NT_STATUS_IS_OK(nt_status)) {
                *perr = WERR_BADFILE;
                goto error_exit;
        }
@@ -1524,8 +1517,7 @@ static uint32 get_correct_cversion(struct pipes_struct *p,
                conn,                                   /* conn */
                NULL,                                   /* req */
                0,                                      /* root_dir_fid */
-               driverpath,                             /* fname */
-               0,                                      /* create_file_flags */
+               smb_fname,                              /* fname */
                FILE_GENERIC_READ,                      /* access_mask */
                FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
                FILE_OPEN,                              /* create_disposition*/
@@ -1536,22 +1528,25 @@ static uint32 get_correct_cversion(struct pipes_struct *p,
                NULL,                                   /* sd */
                NULL,                                   /* ea_list */
                &fsp,                                   /* result */
-               NULL,                                   /* pinfo */
-               &st);                                   /* psbuf */
+               NULL);                                  /* pinfo */
 
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
-                               driverpath, errno));
+               DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
+                        "%d\n", smb_fname_str_dbg(smb_fname), errno));
                *perr = WERR_ACCESS_DENIED;
                goto error_exit;
        } else {
                uint32 major;
                uint32 minor;
-               int    ret = get_file_version(fsp, driverpath, &major, &minor);
+               int    ret;
+
+               ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
                if (ret == -1) goto error_exit;
 
                if (!ret) {
-                       DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
+                       DEBUG(6,("get_correct_cversion: Version info not "
+                                "found [%s]\n",
+                                smb_fname_str_dbg(smb_fname)));
                        goto error_exit;
                }
 
@@ -1569,23 +1564,27 @@ static uint32 get_correct_cversion(struct pipes_struct *p,
                                break;
 
                        default:
-                               DEBUG(6,("get_correct_cversion: cversion invalid [%s]  cversion = %d\n",
-                                       driverpath, cversion));
+                               DEBUG(6,("get_correct_cversion: cversion "
+                                        "invalid [%s]  cversion = %d\n",
+                                        smb_fname_str_dbg(smb_fname),
+                                        cversion));
                                goto error_exit;
                }
 
-               DEBUG(10,("get_correct_cversion: Version info found [%s]  major = 0x%x  minor = 0x%x\n",
-                                 driverpath, major, minor));
+               DEBUG(10,("get_correct_cversion: Version info found [%s] major"
+                         " = 0x%x  minor = 0x%x\n",
+                         smb_fname_str_dbg(smb_fname), major, minor));
        }
 
        DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
-               driverpath, cversion));
+                 smb_fname_str_dbg(smb_fname), cversion));
 
        goto done;
 
  error_exit:
        cversion = -1;
  done:
+       TALLOC_FREE(smb_fname);
        if (fsp != NULL) {
                close_file(NULL, fsp, NORMAL_CLOSE);
        }
@@ -1803,19 +1802,86 @@ static char* ffmt(unsigned char *c){
 
 /****************************************************************************
 ****************************************************************************/
+
+static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
+                                               connection_struct *conn,
+                                               const char *driver_file,
+                                               const char *short_architecture,
+                                               uint32_t driver_version,
+                                               uint32_t version)
+{
+       struct smb_filename *smb_fname_old = NULL;
+       struct smb_filename *smb_fname_new = NULL;
+       char *old_name = NULL;
+       char *new_name = NULL;
+       NTSTATUS status;
+       WERROR ret;
+
+       old_name = talloc_asprintf(mem_ctx, "%s/%s",
+                                  short_architecture, driver_file);
+       W_ERROR_HAVE_NO_MEMORY(old_name);
+
+       new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
+                                  short_architecture, driver_version, driver_file);
+       if (new_name == NULL) {
+               TALLOC_FREE(old_name);
+               return WERR_NOMEM;
+       }
+
+       if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
+
+               status = driver_unix_convert(conn, old_name, &smb_fname_old);
+               if (!NT_STATUS_IS_OK(status)) {
+                       ret = WERR_NOMEM;
+                       goto out;
+               }
+
+               /* Setup a synthetic smb_filename struct */
+               smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
+               if (!smb_fname_new) {
+                       ret = WERR_NOMEM;
+                       goto out;
+               }
+
+               smb_fname_new->base_name = new_name;
+
+               DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
+                         "'%s'\n", smb_fname_old->base_name,
+                         smb_fname_new->base_name));
+
+               status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
+                                  OPENX_FILE_EXISTS_TRUNCATE |
+                                  OPENX_FILE_CREATE_IF_NOT_EXIST,
+                                  0, false);
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(0,("move_driver_file_to_download_area: Unable "
+                                "to rename [%s] to [%s]: %s\n",
+                                smb_fname_old->base_name, new_name,
+                                nt_errstr(status)));
+                       ret = WERR_ACCESS_DENIED;
+                       goto out;
+               }
+       }
+
+       ret = WERR_OK;
+ out:
+       TALLOC_FREE(smb_fname_old);
+       TALLOC_FREE(smb_fname_new);
+       return ret;
+}
+
 WERROR move_driver_to_download_area(struct pipes_struct *p,
                                    NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
                                    uint32 level, WERROR *perr)
 {
        NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
        NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
-       const char *architecture;
+       const char *short_architecture;
+       struct smb_filename *smb_dname = NULL;
        char *new_dir = NULL;
-       char *old_name = NULL;
-       char *new_name = NULL;
        connection_struct *conn = NULL;
        NTSTATUS nt_status;
-       SMB_STRUCT_STAT st;
        int i;
        TALLOC_CTX *ctx = talloc_tos();
        int ver = 0;
@@ -1825,18 +1891,21 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
 
        *perr = WERR_OK;
 
-       if (level==3)
-               driver=driver_abstract.info_3;
-       else if (level==6) {
+       switch (level) {
+       case 3:
+               driver = driver_abstract.info_3;
+               break;
+       case 6:
                convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
                driver = &converted_driver;
-       } else {
+               break;
+       default:
                DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
                return WERR_UNKNOWN_LEVEL;
        }
 
-       architecture = get_short_archi(driver->environment);
-       if (!architecture) {
+       short_architecture = get_short_archi(driver->environment);
+       if (!short_architecture) {
                return WERR_UNKNOWN_PRINTER_DRIVER;
        }
 
@@ -1858,22 +1927,23 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
                return *perr;
        }
 
-       DEBUG(5,("Creating first directory\n"));
        new_dir = talloc_asprintf(ctx,
                                "%s/%d",
-                               architecture,
+                               short_architecture,
                                driver->cversion);
        if (!new_dir) {
                *perr = WERR_NOMEM;
                goto err_exit;
        }
-       new_dir = driver_unix_convert(conn,new_dir,&st);
-       if (!new_dir) {
+       nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
+       if (!NT_STATUS_IS_OK(nt_status)) {
                *perr = WERR_NOMEM;
                goto err_exit;
        }
 
-       create_directory(conn, NULL, new_dir);
+       DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
+
+       create_directory(conn, NULL, smb_dname);
 
        /* 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:
@@ -1895,143 +1965,74 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
        DEBUG(5,("Moving files now !\n"));
 
        if (driver->driverpath && strlen(driver->driverpath)) {
-               new_name = talloc_asprintf(ctx,
-                                       "%s/%s",
-                                       architecture,
-                                       driver->driverpath);
-               if (!new_name) {
-                       *perr = WERR_NOMEM;
-                       goto err_exit;
-               }
-               old_name = talloc_asprintf(ctx,
-                                       "%s/%s",
-                                       new_dir,
-                                       driver->driverpath);
-               if (!old_name) {
-                       *perr = WERR_NOMEM;
-                       goto err_exit;
-               }
 
-               if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
-                       new_name = driver_unix_convert(conn,new_name,&st);
-                       if (!new_name) {
-                               *perr = WERR_NOMEM;
-                               goto err_exit;
-                       }
-                       if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
-                                               OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
-                               DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
-                                               new_name, old_name));
-                               *perr = WERR_ACCESS_DENIED;
+               *perr = move_driver_file_to_download_area(ctx,
+                                                         conn,
+                                                         driver->driverpath,
+                                                         short_architecture,
+                                                         driver->cversion,
+                                                         ver);
+               if (!W_ERROR_IS_OK(*perr)) {
+                       if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
                                ver = -1;
                        }
+                       goto err_exit;
                }
        }
 
        if (driver->datafile && strlen(driver->datafile)) {
                if (!strequal(driver->datafile, driver->driverpath)) {
-                       new_name = talloc_asprintf(ctx,
-                                       "%s/%s",
-                                       architecture,
-                                       driver->datafile);
-                       if (!new_name) {
-                               *perr = WERR_NOMEM;
-                               goto err_exit;
-                       }
-                       old_name = talloc_asprintf(ctx,
-                                       "%s/%s",
-                                       new_dir,
-                                       driver->datafile);
-                       if (!old_name) {
-                               *perr = WERR_NOMEM;
-                               goto err_exit;
-                       }
-                       if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
-                               new_name = driver_unix_convert(conn,new_name,&st);
-                               if (!new_name) {
-                                       *perr = WERR_NOMEM;
-                                       goto err_exit;
-                               }
-                               if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
-                                               OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
-                                       DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
-                                                       new_name, old_name));
-                                       *perr = WERR_ACCESS_DENIED;
+
+                       *perr = move_driver_file_to_download_area(ctx,
+                                                                 conn,
+                                                                 driver->datafile,
+                                                                 short_architecture,
+                                                                 driver->cversion,
+                                                                 ver);
+                       if (!W_ERROR_IS_OK(*perr)) {
+                               if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
                                        ver = -1;
                                }
+                               goto err_exit;
                        }
                }
        }
 
        if (driver->configfile && strlen(driver->configfile)) {
                if (!strequal(driver->configfile, driver->driverpath) &&
-                       !strequal(driver->configfile, driver->datafile)) {
-                       new_name = talloc_asprintf(ctx,
-                                               "%s/%s",
-                                               architecture,
-                                               driver->configfile);
-                       if (!new_name) {
-                               *perr = WERR_NOMEM;
-                               goto err_exit;
-                       }
-                       old_name = talloc_asprintf(ctx,
-                                               "%s/%s",
-                                               new_dir,
-                                               driver->configfile);
-                       if (!old_name) {
-                               *perr = WERR_NOMEM;
-                               goto err_exit;
-                       }
-                       if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
-                               new_name = driver_unix_convert(conn,new_name,&st);
-                               if (!new_name) {
-                                       *perr = WERR_NOMEM;
-                                       goto err_exit;
-                               }
-                               if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
-                                               OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
-                                       DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
-                                                       new_name, old_name));
-                                       *perr = WERR_ACCESS_DENIED;
+                   !strequal(driver->configfile, driver->datafile)) {
+
+                       *perr = move_driver_file_to_download_area(ctx,
+                                                                 conn,
+                                                                 driver->configfile,
+                                                                 short_architecture,
+                                                                 driver->cversion,
+                                                                 ver);
+                       if (!W_ERROR_IS_OK(*perr)) {
+                               if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
                                        ver = -1;
                                }
+                               goto err_exit;
                        }
                }
        }
 
        if (driver->helpfile && strlen(driver->helpfile)) {
                if (!strequal(driver->helpfile, driver->driverpath) &&
-                       !strequal(driver->helpfile, driver->datafile) &&
-                       !strequal(driver->helpfile, driver->configfile)) {
-                       new_name = talloc_asprintf(ctx,
-                                       "%s/%s",
-                                       architecture,
-                                       driver->helpfile);
-                       if (!new_name) {
-                               *perr = WERR_NOMEM;
-                               goto err_exit;
-                       }
-                       old_name = talloc_asprintf(ctx,
-                                       "%s/%s",
-                                       new_dir,
-                                       driver->helpfile);
-                       if (!old_name) {
-                               *perr = WERR_NOMEM;
-                               goto err_exit;
-                       }
-                       if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
-                               new_name = driver_unix_convert(conn,new_name,&st);
-                               if (!new_name) {
-                                       *perr = WERR_NOMEM;
-                                       goto err_exit;
-                               }
-                               if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
-                                               OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
-                                       DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
-                                                       new_name, old_name));
-                                       *perr = WERR_ACCESS_DENIED;
+                   !strequal(driver->helpfile, driver->datafile) &&
+                   !strequal(driver->helpfile, driver->configfile)) {
+
+                       *perr = move_driver_file_to_download_area(ctx,
+                                                                 conn,
+                                                                 driver->helpfile,
+                                                                 short_architecture,
+                                                                 driver->cversion,
+                                                                 ver);
+                       if (!W_ERROR_IS_OK(*perr)) {
+                               if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
                                        ver = -1;
                                }
+                               goto err_exit;
                        }
                }
        }
@@ -2039,9 +2040,9 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
        if (driver->dependentfiles) {
                for (i=0; *driver->dependentfiles[i]; i++) {
                        if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
-                               !strequal(driver->dependentfiles[i], driver->datafile) &&
-                               !strequal(driver->dependentfiles[i], driver->configfile) &&
-                               !strequal(driver->dependentfiles[i], driver->helpfile)) {
+                           !strequal(driver->dependentfiles[i], driver->datafile) &&
+                           !strequal(driver->dependentfiles[i], driver->configfile) &&
+                           !strequal(driver->dependentfiles[i], driver->helpfile)) {
                                int j;
                                for (j=0; j < i; j++) {
                                        if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
@@ -2049,36 +2050,17 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
                                        }
                                }
 
-                               new_name = talloc_asprintf(ctx,
-                                               "%s/%s",
-                                               architecture,
-                                               driver->dependentfiles[i]);
-                               if (!new_name) {
-                                       *perr = WERR_NOMEM;
-                                       goto err_exit;
-                               }
-                               old_name = talloc_asprintf(ctx,
-                                               "%s/%s",
-                                               new_dir,
-                                               driver->dependentfiles[i]);
-                               if (!old_name) {
-                                       *perr = WERR_NOMEM;
-                                       goto err_exit;
-                               }
-                               if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
-                                       new_name = driver_unix_convert(conn,new_name,&st);
-                                       if (!new_name) {
-                                               *perr = WERR_NOMEM;
-                                               goto err_exit;
-                                       }
-                                       if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name,
-                                                       OPENX_FILE_EXISTS_TRUNCATE|
-                                                       OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
-                                               DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
-                                                               new_name, old_name));
-                                               *perr = WERR_ACCESS_DENIED;
+                               *perr = move_driver_file_to_download_area(ctx,
+                                                                         conn,
+                                                                         driver->dependentfiles[i],
+                                                                         short_architecture,
+                                                                         driver->cversion,
+                                                                         ver);
+                               if (!W_ERROR_IS_OK(*perr)) {
+                                       if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
                                                ver = -1;
                                        }
+                                       goto err_exit;
                                }
                        }
                NextDriver: ;
@@ -2086,6 +2068,7 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
        }
 
   err_exit:
+       TALLOC_FREE(smb_dname);
 
        if (conn != NULL) {
                vfs_ChDir(conn, oldcwd);
@@ -2474,8 +2457,8 @@ static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
 {
        int             len = 0;
        int             i, j;
-       REGISTRY_VALUE  *val;
-       REGVAL_CTR      *val_ctr;
+       struct regval_blob      *val;
+       struct regval_ctr       *val_ctr;
        char *path = NULL;
        int             num_values;
 
@@ -2549,7 +2532,7 @@ uint32 del_a_printer(const char *sharename)
 
        close_all_print_db();
 
-       if (geteuid() == 0) {
+       if (geteuid() == sec_initial_uid()) {
                if (asprintf(&printdb_path, "%s%s.tdb",
                                cache_path("printing/"),
                                sharename) < 0) {
@@ -2731,34 +2714,6 @@ NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
        return nt_devmode;
 }
 
-/****************************************************************************
- Deepcopy an NT devicemode.
-****************************************************************************/
-
-NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
-{
-       NT_DEVICEMODE *new_nt_devicemode = NULL;
-
-       if ( !nt_devicemode )
-               return NULL;
-
-       if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
-               DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
-               return NULL;
-       }
-
-       new_nt_devicemode->nt_dev_private = NULL;
-       if (nt_devicemode->nt_dev_private != NULL) {
-               if ((new_nt_devicemode->nt_dev_private = (uint8 *)memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
-                       SAFE_FREE(new_nt_devicemode);
-                       DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
-                       return NULL;
-        }
-       }
-
-       return new_nt_devicemode;
-}
-
 /****************************************************************************
  Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
 ****************************************************************************/
@@ -2899,7 +2854,7 @@ int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
 
        data->keys[key_index].name = talloc_strdup( data, name );
 
-       if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, REGVAL_CTR )) )
+       if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, struct regval_ctr )) )
                return -1;
 
        data->num_keys++;
@@ -3070,7 +3025,7 @@ done:
 }
 
 #ifdef HAVE_ADS
-static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
+static void map_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
                            const char *sz)
 {
        smb_ucs2_t conv_str[1024];
@@ -3083,7 +3038,7 @@ static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
                            (char *) conv_str, str_size);
 }
 
-static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
+static void map_dword_into_ctr(struct regval_ctr *ctr, const char *val_name,
                               uint32 dword)
 {
        regval_ctr_delvalue(ctr, val_name);
@@ -3091,7 +3046,7 @@ static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
                            (char *) &dword, sizeof(dword));
 }
 
-static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
+static void map_bool_into_ctr(struct regval_ctr *ctr, const char *val_name,
                              bool b)
 {
        uint8 bin_bool = (b ? 1 : 0);
@@ -3100,7 +3055,7 @@ static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
                            (char *) &bin_bool, sizeof(bin_bool));
 }
 
-static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
+static void map_single_multi_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
                                         const char *multi_sz)
 {
        smb_ucs2_t *conv_strs = NULL;
@@ -3134,7 +3089,7 @@ static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
 
 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
 {
-       REGVAL_CTR *ctr = NULL;
+       struct regval_ctr *ctr = NULL;
        fstring longname;
        const char *dnssuffix;
        char *allocated_string = NULL;
@@ -3206,7 +3161,7 @@ static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
                               struct GUID guid)
 {
        int i;
-       REGVAL_CTR *ctr=NULL;
+       struct regval_ctr *ctr=NULL;
        UNISTR2 unistr_guid;
 
        /* find the DsSpooler key */
@@ -3243,7 +3198,12 @@ static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
        struct GUID guid;
        WERROR win_rc = WERR_OK;
        size_t converted_size;
-       int ret;
+
+       /* build the ads mods */
+       ctx = talloc_init("nt_printer_publish_ads");
+       if (ctx == NULL) {
+               return WERR_NOMEM;
+       }
 
        DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
 
@@ -3255,24 +3215,28 @@ static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
 
        srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
        if (!srv_dn_utf8) {
+               TALLOC_FREE(ctx);
                return WERR_SERVER_UNAVAILABLE;
        }
        ads_msgfree(ads, res);
        srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
        if (!srv_cn_utf8) {
+               TALLOC_FREE(ctx);
                ldap_memfree(srv_dn_utf8);
                return WERR_SERVER_UNAVAILABLE;
        }
        /* Now convert to CH_UNIX. */
-       if (!pull_utf8_allocate(&srv_dn, srv_dn_utf8, &converted_size)) {
+       if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
+               TALLOC_FREE(ctx);
                ldap_memfree(srv_dn_utf8);
                ldap_memfree(srv_cn_utf8);
                return WERR_SERVER_UNAVAILABLE;
        }
-       if (!pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0], &converted_size)) {
+       if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
+               TALLOC_FREE(ctx);
                ldap_memfree(srv_dn_utf8);
                ldap_memfree(srv_cn_utf8);
-               SAFE_FREE(srv_dn);
+               TALLOC_FREE(srv_dn);
                return WERR_SERVER_UNAVAILABLE;
        }
 
@@ -3281,41 +3245,26 @@ static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
 
        srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
        if (!srv_cn_escaped) {
-               SAFE_FREE(srv_cn_0);
-               SAFE_FREE(srv_dn);
+               TALLOC_FREE(ctx);
                return WERR_SERVER_UNAVAILABLE;
        }
        sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
        if (!sharename_escaped) {
                SAFE_FREE(srv_cn_escaped);
-               SAFE_FREE(srv_cn_0);
-               SAFE_FREE(srv_dn);
+               TALLOC_FREE(ctx);
                return WERR_SERVER_UNAVAILABLE;
        }
 
-       ret = asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
+       prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
 
-       SAFE_FREE(srv_dn);
-       SAFE_FREE(srv_cn_0);
        SAFE_FREE(srv_cn_escaped);
        SAFE_FREE(sharename_escaped);
 
-       if (ret == -1) {
-               return WERR_NOMEM;
-       }
-
-       /* build the ads mods */
-       ctx = talloc_init("nt_printer_publish_ads");
-       if (ctx == NULL) {
-               SAFE_FREE(prt_dn);
-               return WERR_NOMEM;
-       }
-
        mods = ads_init_mods(ctx);
 
        if (mods == NULL) {
                SAFE_FREE(prt_dn);
-               talloc_destroy(ctx);
+               TALLOC_FREE(ctx);
                return WERR_NOMEM;
        }
 
@@ -3336,8 +3285,6 @@ static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
        if (!ADS_ERR_OK(ads_rc))
                DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
 
-       talloc_destroy(ctx);
-
        /* retreive the guid and store it locally */
        if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
                ZERO_STRUCT(guid);
@@ -3346,8 +3293,8 @@ static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
                store_printer_guid(printer->info_2, guid);
                win_rc = mod_a_printer(printer, 2);
        }
+       TALLOC_FREE(ctx);
 
-       SAFE_FREE(prt_dn);
        return win_rc;
 }
 
@@ -3365,13 +3312,13 @@ static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
                            printer->info_2->sharename, global_myname());
 
        if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
-               prt_dn = ads_get_dn(ads, res);
+               prt_dn = ads_get_dn(ads, talloc_tos(), res);
                if (!prt_dn) {
                        ads_msgfree(ads, res);
                        return WERR_NOMEM;
                }
                ads_rc = ads_del_dn(ads, prt_dn);
-               ads_memfree(ads, prt_dn);
+               TALLOC_FREE(prt_dn);
        }
 
        if (res) {
@@ -3506,8 +3453,8 @@ bool is_printer_published(Printer_entry *print_hnd, int snum,
                          struct GUID *guid)
 {
        NT_PRINTER_INFO_LEVEL *printer = NULL;
-       REGVAL_CTR *ctr;
-       REGISTRY_VALUE *guid_val;
+       struct regval_ctr *ctr;
+       struct regval_blob *guid_val;
        WERROR win_rc;
        int i;
        bool ret = False;
@@ -3727,7 +3674,7 @@ WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const cha
 /****************************************************************************
  ***************************************************************************/
 
-REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
+struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
 {
        int             key_index;
 
@@ -3754,7 +3701,7 @@ static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int bu
        char            *str;
        int             size;
        uint8           *data_p;
-       REGISTRY_VALUE  *regval_p;
+       struct regval_blob      *regval_p;
        int             key_index;
 
        /* add the "PrinterDriverData" key first for performance reasons */
@@ -5212,7 +5159,6 @@ static bool delete_driver_files(struct pipes_struct *rpc_pipe,
        const char *file;
        connection_struct *conn;
        NTSTATUS nt_status;
-       SMB_STRUCT_STAT  st;
        char *oldcwd;
        fstring printdollar;
        int printdollar_snum;
@@ -5250,7 +5196,6 @@ static bool delete_driver_files(struct pipes_struct *rpc_pipe,
        if ( *info_3->driverpath ) {
                if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
                        file = s;
-                       driver_unix_convert(conn,file,&st);
                        DEBUG(10,("deleting driverfile [%s]\n", s));
                        unlink_internals(conn, NULL, 0, file, False);
                }
@@ -5259,7 +5204,6 @@ static bool delete_driver_files(struct pipes_struct *rpc_pipe,
        if ( *info_3->configfile ) {
                if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
                        file = s;
-                       driver_unix_convert(conn,file,&st);
                        DEBUG(10,("deleting configfile [%s]\n", s));
                        unlink_internals(conn, NULL, 0, file, False);
                }
@@ -5268,7 +5212,6 @@ static bool delete_driver_files(struct pipes_struct *rpc_pipe,
        if ( *info_3->datafile ) {
                if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
                        file = s;
-                       driver_unix_convert(conn,file,&st);
                        DEBUG(10,("deleting datafile [%s]\n", s));
                        unlink_internals(conn, NULL, 0, file, False);
                }
@@ -5277,7 +5220,6 @@ static bool delete_driver_files(struct pipes_struct *rpc_pipe,
        if ( *info_3->helpfile ) {
                if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
                        file = s;
-                       driver_unix_convert(conn,file,&st);
                        DEBUG(10,("deleting helpfile [%s]\n", s));
                        unlink_internals(conn, NULL, 0, file, False);
                }
@@ -5293,7 +5235,6 @@ static bool delete_driver_files(struct pipes_struct *rpc_pipe,
 
                        if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
                                file = p;
-                               driver_unix_convert(conn,file,&st);
                                DEBUG(10,("deleting dependent file [%s]\n", file));
                                unlink_internals(conn, NULL, 0, file, False);
                        }
@@ -5753,7 +5694,7 @@ void map_job_permissions(SEC_DESC *sd)
        print_queue_purge
 
   Try access control in the following order (for performance reasons):
-    1)  root ans SE_PRINT_OPERATOR can do anything (easy check)
+    1)  root and SE_PRINT_OPERATOR can do anything (easy check)
     2)  check security descriptor (bit comparisons in memory)
     3)  "printer admins" (may result in numerous calls to winbind)
 
@@ -5772,7 +5713,7 @@ bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
 
        /* Always allow root or SE_PRINT_OPERATROR to do anything */
 
-       if (server_info->utok.uid == 0
+       if (server_info->utok.uid == sec_initial_uid()
            || user_has_privileges(server_info->ptok, &se_printop ) ) {
                return True;
        }