s3-printing: eliminate another non sec_initial_uid using security check.
[ira/wip.git] / source3 / printing / nt_printing.c
index 39e9661bd68e2b55f72da42ab27b43ca1d3189dd..3e206becf4a930e16799a9398b7c4d4861aa525a 100644 (file)
@@ -634,40 +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();
-       struct smb_filename *smb_fname = NULL;
        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,"/","/");
 
-       status = unix_convert(ctx, conn, name, &smb_fname, 0);
-       if (!NT_STATUS_IS_OK(status)) {
-               return NULL;
-       }
-
-       *pst = smb_fname->st;
-       status = get_full_smb_filename(ctx, smb_fname, &new_name);
+       status = unix_convert(ctx, conn, name, smb_fname, 0);
        if (!NT_STATUS_IS_OK(status)) {
-               TALLOC_FREE(smb_fname);
-               return NULL;
+               return NT_STATUS_NO_MEMORY;
        }
 
-       TALLOC_FREE(smb_fname);
-       return new_name;
+       return NT_STATUS_OK;
 }
 
 /*******************************************************************
@@ -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);
        }
@@ -1811,10 +1810,12 @@ static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
                                                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;
-       SMB_STRUCT_STAT st;
        NTSTATUS status;
+       WERROR ret;
 
        old_name = talloc_asprintf(mem_ctx, "%s/%s",
                                   short_architecture, driver_file);
@@ -1822,29 +1823,52 @@ static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
 
        new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
                                   short_architecture, driver_version, driver_file);
-       W_ERROR_HAVE_NO_MEMORY(new_name);
+       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) {
 
-               old_name = driver_unix_convert(conn, old_name, &st);
-               W_ERROR_HAVE_NO_MEMORY(old_name);
+               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",
-                       old_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, old_name, new_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",
-                               old_name, new_name, nt_errstr(status)));
-                       return WERR_ACCESS_DENIED;
+                       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;
                }
        }
 
-       return WERR_OK;
+       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,
@@ -1854,10 +1878,10 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
        NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
        NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
        const char *short_architecture;
+       struct smb_filename *smb_dname = NULL;
        char *new_dir = NULL;
        connection_struct *conn = NULL;
        NTSTATUS nt_status;
-       SMB_STRUCT_STAT st;
        int i;
        TALLOC_CTX *ctx = talloc_tos();
        int ver = 0;
@@ -1911,15 +1935,15 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
                *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;
        }
 
-       DEBUG(5,("Creating first directory: %s\n", new_dir));
+       DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
 
-       create_directory(conn, NULL, new_dir);
+       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:
@@ -2044,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);
@@ -2507,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) {
@@ -5134,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;
@@ -5172,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);
                }
@@ -5181,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);
                }
@@ -5190,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);
                }
@@ -5199,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);
                }
@@ -5215,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);
                        }