Make "struct policy" private to srv_lsa_hnd.c
[ira/wip.git] / source3 / rpc_server / srv_spoolss_nt.c
index 098e59216b8317c5c07918c1d7515d762108691b..629e41c0033444c1b3da3df170fd8a415b67e9aa 100644 (file)
@@ -591,7 +591,8 @@ static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
 
        new_printer->access_granted = access_granted;
 
-       DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
+       DEBUG(5, ("%d printer handles active\n",
+                 (int)num_pipe_handles(p->pipe_handles)));
 
        return true;
 }
@@ -4084,6 +4085,39 @@ static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
        return WERR_OK;
 }
 
+/********************************************************************
+ * construct_printer_info8
+ * fill a spoolss_PrinterInfo8 struct
+ ********************************************************************/
+
+static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
+                                     const NT_PRINTER_INFO_LEVEL *ntprinter,
+                                     struct spoolss_DeviceModeInfo *r,
+                                     int snum)
+{
+       struct spoolss_DeviceMode *devmode;
+       WERROR result;
+
+       if (!ntprinter->info_2->devmode) {
+               r->devmode = NULL;
+               return WERR_OK;
+       }
+
+       devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
+       W_ERROR_HAVE_NO_MEMORY(devmode);
+
+       result = convert_nt_devicemode(mem_ctx, devmode, ntprinter->info_2->devmode);
+       if (!W_ERROR_IS_OK(result)) {
+               TALLOC_FREE(devmode);
+               return result;
+       }
+
+       r->devmode      = devmode;
+
+       return WERR_OK;
+}
+
+
 /********************************************************************
  * construct_printer_info1
  * fill a spoolss_PrinterInfo1 struct
@@ -4095,25 +4129,21 @@ static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
                                      struct spoolss_PrinterInfo1 *r,
                                      int snum)
 {
-       char *chaine = NULL;
        r->flags                = flags;
 
+       r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
+                                                 ntprinter->info_2->printername,
+                                                 ntprinter->info_2->drivername,
+                                                 ntprinter->info_2->location);
+       W_ERROR_HAVE_NO_MEMORY(r->description);
+
        if (*ntprinter->info_2->comment == '\0') {
                r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
-               chaine = talloc_asprintf(mem_ctx,
-                               "%s,%s,%s", ntprinter->info_2->printername,
-                               ntprinter->info_2->drivername, lp_comment(snum));
        } else {
                r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
-               chaine = talloc_asprintf(mem_ctx,
-                               "%s,%s,%s", ntprinter->info_2->printername,
-                               ntprinter->info_2->drivername, ntprinter->info_2->comment);
        }
-       W_ERROR_HAVE_NO_MEMORY(chaine);
        W_ERROR_HAVE_NO_MEMORY(r->comment);
 
-       r->description          = talloc_strdup(mem_ctx, chaine);
-       W_ERROR_HAVE_NO_MEMORY(r->description);
        r->name                 = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
        W_ERROR_HAVE_NO_MEMORY(r->name);
 
@@ -4636,6 +4666,10 @@ WERROR _spoolss_GetPrinter(pipes_struct *p,
                result = construct_printer_info7(p->mem_ctx, Printer,
                                                 &r->out.info->info7, snum);
                break;
+       case 8:
+               result = construct_printer_info8(p->mem_ctx, ntprinter,
+                                                &r->out.info->info8, snum);
+               break;
        default:
                result = WERR_UNKNOWN_LEVEL;
                break;
@@ -4799,7 +4833,7 @@ static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
        } else {
                r->help_file    = talloc_strdup(mem_ctx, "");
        }
-       W_ERROR_HAVE_NO_MEMORY(r->config_file);
+       W_ERROR_HAVE_NO_MEMORY(r->help_file);
 
        r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
        W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
@@ -4812,6 +4846,121 @@ static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
        return WERR_OK;
 }
 
+/********************************************************************
+ * fill a spoolss_DriverInfo4 struct
+ ********************************************************************/
+
+static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
+                                       struct spoolss_DriverInfo4 *r,
+                                       const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
+                                       const char *servername)
+{
+       const char *cservername = canon_servername(servername);
+
+       r->version              = driver->info_3->cversion;
+
+       r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
+       W_ERROR_HAVE_NO_MEMORY(r->driver_name);
+       r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
+       W_ERROR_HAVE_NO_MEMORY(r->architecture);
+
+       if (strlen(driver->info_3->driverpath)) {
+               r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
+                               cservername, driver->info_3->driverpath);
+       } else {
+               r->driver_path  = talloc_strdup(mem_ctx, "");
+       }
+       W_ERROR_HAVE_NO_MEMORY(r->driver_path);
+
+       if (strlen(driver->info_3->datafile)) {
+               r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
+                               cservername, driver->info_3->datafile);
+       } else {
+               r->data_file    = talloc_strdup(mem_ctx, "");
+       }
+       W_ERROR_HAVE_NO_MEMORY(r->data_file);
+
+       if (strlen(driver->info_3->configfile)) {
+               r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
+                               cservername, driver->info_3->configfile);
+       } else {
+               r->config_file  = talloc_strdup(mem_ctx, "");
+       }
+       W_ERROR_HAVE_NO_MEMORY(r->config_file);
+
+       if (strlen(driver->info_3->helpfile)) {
+               r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
+                               cservername, driver->info_3->helpfile);
+       } else {
+               r->help_file    = talloc_strdup(mem_ctx, "");
+       }
+       W_ERROR_HAVE_NO_MEMORY(r->help_file);
+
+       r->dependent_files = string_array_from_driver_info(mem_ctx,
+                                                          driver->info_3->dependentfiles,
+                                                          cservername);
+
+
+       r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
+       W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
+       r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
+       W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
+
+       r->previous_names = string_array_from_driver_info(mem_ctx,
+                                                         NULL,
+                                                         cservername);
+
+       return WERR_OK;
+}
+
+/********************************************************************
+ * fill a spoolss_DriverInfo5 struct
+ ********************************************************************/
+
+static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
+                                       struct spoolss_DriverInfo5 *r,
+                                       const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
+                                       const char *servername)
+{
+       const char *cservername = canon_servername(servername);
+
+       r->version              = driver->info_3->cversion;
+
+       r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
+       W_ERROR_HAVE_NO_MEMORY(r->driver_name);
+       r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
+       W_ERROR_HAVE_NO_MEMORY(r->architecture);
+
+       if (strlen(driver->info_3->driverpath)) {
+               r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
+                               cservername, driver->info_3->driverpath);
+       } else {
+               r->driver_path  = talloc_strdup(mem_ctx, "");
+       }
+       W_ERROR_HAVE_NO_MEMORY(r->driver_path);
+
+       if (strlen(driver->info_3->datafile)) {
+               r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
+                               cservername, driver->info_3->datafile);
+       } else {
+               r->data_file    = talloc_strdup(mem_ctx, "");
+       }
+       W_ERROR_HAVE_NO_MEMORY(r->data_file);
+
+       if (strlen(driver->info_3->configfile)) {
+               r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
+                               cservername, driver->info_3->configfile);
+       } else {
+               r->config_file  = talloc_strdup(mem_ctx, "");
+       }
+       W_ERROR_HAVE_NO_MEMORY(r->config_file);
+
+       r->driver_attributes    = 0;
+       r->config_version       = 0;
+       r->driver_version       = 0;
+
+       return WERR_OK;
+}
 /********************************************************************
  * fill a spoolss_DriverInfo6 struct
  ********************************************************************/
@@ -4860,7 +5009,7 @@ static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
        } else {
                r->help_file    = talloc_strdup(mem_ctx, "");
        }
-       W_ERROR_HAVE_NO_MEMORY(r->config_file);
+       W_ERROR_HAVE_NO_MEMORY(r->help_file);
 
        r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
        W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
@@ -6572,14 +6721,15 @@ WERROR _spoolss_SetJob(pipes_struct *p,
 }
 
 /****************************************************************************
- Enumerates all printer drivers at level 1.
+ Enumerates all printer drivers by level.
 ****************************************************************************/
 
-static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
-                                       const char *servername,
-                                       const char *architecture,
-                                       union spoolss_DriverInfo **info_p,
-                                       uint32_t *count)
+static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
+                                      const char *servername,
+                                      const char *architecture,
+                                      uint32_t level,
+                                      union spoolss_DriverInfo **info_p,
+                                      uint32_t *count_p)
 {
        int i;
        int ndrivers;
@@ -6587,9 +6737,11 @@ static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
        fstring *list = NULL;
        NT_PRINTER_DRIVER_INFO_LEVEL driver;
        union spoolss_DriverInfo *info = NULL;
+       uint32_t count = 0;
        WERROR result = WERR_OK;
 
-       *count = 0;
+       *count_p = 0;
+       *info_p = NULL;
 
        for (version=0; version<DRIVER_MAX_VERSION; version++) {
                list = NULL;
@@ -6605,7 +6757,7 @@ static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
                if (ndrivers != 0) {
                        info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
                                                    union spoolss_DriverInfo,
-                                                   *count + ndrivers);
+                                                   count + ndrivers);
                        if (!info) {
                                DEBUG(0,("enumprinterdrivers_level1: "
                                        "failed to enlarge driver info buffer!\n"));
@@ -6622,9 +6774,38 @@ static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
                        if (!W_ERROR_IS_OK(result)) {
                                goto out;
                        }
-                       result = fill_printer_driver_info1(info, &info[*count+i].info1,
-                                                          &driver, servername,
-                                                          architecture);
+
+                       switch (level) {
+                       case 1:
+                               result = fill_printer_driver_info1(info, &info[count+i].info1,
+                                                                  &driver, servername,
+                                                                  architecture);
+                               break;
+                       case 2:
+                               result = fill_printer_driver_info2(info, &info[count+i].info2,
+                                                                  &driver, servername);
+                               break;
+                       case 3:
+                               result = fill_printer_driver_info3(info, &info[count+i].info3,
+                                                                  &driver, servername);
+                               break;
+                       case 4:
+                               result = fill_printer_driver_info4(info, &info[count+i].info4,
+                                                                  &driver, servername);
+                               break;
+                       case 5:
+                               result = fill_printer_driver_info5(info, &info[count+i].info5,
+                                                                  &driver, servername);
+                               break;
+                       case 6:
+                               result = fill_printer_driver_info6(info, &info[count+i].info6,
+                                                                  &driver, servername);
+                               break;
+                       default:
+                               result = WERR_UNKNOWN_LEVEL;
+                               break;
+                       }
+
                        if (!W_ERROR_IS_OK(result)) {
                                free_a_printer_driver(driver, 3);
                                goto out;
@@ -6632,7 +6813,7 @@ static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
                        free_a_printer_driver(driver, 3);
                }
 
-               *count += ndrivers;
+               count += ndrivers;
                SAFE_FREE(list);
        }
 
@@ -6641,91 +6822,41 @@ static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
 
        if (!W_ERROR_IS_OK(result)) {
                TALLOC_FREE(info);
-               *count = 0;
                return result;
        }
 
        *info_p = info;
+       *count_p = count;
 
        return WERR_OK;
 }
 
 /****************************************************************************
- Enumerates all printer drivers at level 2.
+ Enumerates all printer drivers at level 1.
 ****************************************************************************/
 
-static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
+static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
                                        const char *servername,
                                        const char *architecture,
                                        union spoolss_DriverInfo **info_p,
                                        uint32_t *count)
 {
-       int i;
-       int ndrivers;
-       uint32_t version;
-       fstring *list = NULL;
-       NT_PRINTER_DRIVER_INFO_LEVEL driver;
-       union spoolss_DriverInfo *info = NULL;
-       WERROR result = WERR_OK;
-
-       *count = 0;
-
-       for (version=0; version<DRIVER_MAX_VERSION; version++) {
-               list = NULL;
-               ndrivers = get_ntdrivers(&list, architecture, version);
-               DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
-                       ndrivers, architecture, version));
-
-               if (ndrivers == -1) {
-                       result = WERR_NOMEM;
-                       goto out;
-               }
-
-               if (ndrivers != 0) {
-                       info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
-                                                   union spoolss_DriverInfo,
-                                                   *count + ndrivers);
-                       if (!info) {
-                               DEBUG(0,("enumprinterdrivers_level2: "
-                                       "failed to enlarge driver info buffer!\n"));
-                               result = WERR_NOMEM;
-                               goto out;
-                       }
-               }
-
-               for (i=0; i<ndrivers; i++) {
-                       DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
-                       ZERO_STRUCT(driver);
-                       result = get_a_printer_driver(&driver, 3, list[i],
-                                                     architecture, version);
-                       if (!W_ERROR_IS_OK(result)) {
-                               goto out;
-                       }
-                       result = fill_printer_driver_info2(info, &info[*count+i].info2,
-                                                          &driver, servername);
-                       if (!W_ERROR_IS_OK(result)) {
-                               free_a_printer_driver(driver, 3);
-                               goto out;
-                       }
-                       free_a_printer_driver(driver, 3);
-               }
-
-               *count += ndrivers;
-               SAFE_FREE(list);
-       }
-
- out:
-       SAFE_FREE(list);
-
-       if (!W_ERROR_IS_OK(result)) {
-               TALLOC_FREE(info);
-               *count = 0;
-               return result;
-       }
+       return enumprinterdrivers_level(mem_ctx, servername, architecture, 1,
+                                       info_p, count);
+}
 
-       *info_p = info;
+/****************************************************************************
+ Enumerates all printer drivers at level 2.
+****************************************************************************/
 
-       return WERR_OK;
+static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
+                                       const char *servername,
+                                       const char *architecture,
+                                       union spoolss_DriverInfo **info_p,
+                                       uint32_t *count)
+{
+       return enumprinterdrivers_level(mem_ctx, servername, architecture, 2,
+                                       info_p, count);
 }
 
 /****************************************************************************
@@ -6738,75 +6869,53 @@ static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
                                        union spoolss_DriverInfo **info_p,
                                        uint32_t *count)
 {
-       int i;
-       int ndrivers;
-       uint32_t version;
-       fstring *list = NULL;
-       union spoolss_DriverInfo *info = NULL;
-       NT_PRINTER_DRIVER_INFO_LEVEL driver;
-       WERROR result = WERR_OK;
-
-       *count = 0;
-
-       for (version=0; version<DRIVER_MAX_VERSION; version++) {
-               list = NULL;
-               ndrivers = get_ntdrivers(&list, architecture, version);
-               DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
-                       ndrivers, architecture, version));
-
-               if (ndrivers == -1) {
-                       result = WERR_NOMEM;
-                       goto out;
-               }
-
-               if (ndrivers != 0) {
-                       info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
-                                                   union spoolss_DriverInfo,
-                                                   *count + ndrivers);
-                       if (!info) {
-                               DEBUG(0,("enumprinterdrivers_level3: "
-                                       "failed to enlarge driver info buffer!\n"));
-                               result = WERR_NOMEM;
-                               goto out;
-                       }
-               }
-
-               for (i=0; i<ndrivers; i++) {
-                       DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
-                       ZERO_STRUCT(driver);
-                       result = get_a_printer_driver(&driver, 3, list[i],
-                                                     architecture, version);
-                       if (!W_ERROR_IS_OK(result)) {
-                               goto out;
-                       }
-                       result = fill_printer_driver_info3(info, &info[*count+i].info3,
-                                                          &driver, servername);
-                       if (!W_ERROR_IS_OK(result)) {
-                               free_a_printer_driver(driver, 3);
-                               goto out;
-                       }
+       return enumprinterdrivers_level(mem_ctx, servername, architecture, 3,
+                                       info_p, count);
+}
 
-                       free_a_printer_driver(driver, 3);
-               }
+/****************************************************************************
+ Enumerates all printer drivers at level 4.
+****************************************************************************/
 
-               *count += ndrivers;
-               SAFE_FREE(list);
-       }
+static WERROR enumprinterdrivers_level4(TALLOC_CTX *mem_ctx,
+                                       const char *servername,
+                                       const char *architecture,
+                                       union spoolss_DriverInfo **info_p,
+                                       uint32_t *count)
+{
+       return enumprinterdrivers_level(mem_ctx, servername, architecture, 4,
+                                       info_p, count);
+}
 
- out:
-       SAFE_FREE(list);
+/****************************************************************************
+ Enumerates all printer drivers at level 5.
+****************************************************************************/
 
-       if (!W_ERROR_IS_OK(result)) {
-               TALLOC_FREE(info);
-               *count = 0;
-               return result;
-       }
+static WERROR enumprinterdrivers_level5(TALLOC_CTX *mem_ctx,
+                                       const char *servername,
+                                       const char *architecture,
+                                       union spoolss_DriverInfo **info_p,
+                                       uint32_t *count)
+{
+       return enumprinterdrivers_level(mem_ctx, servername, architecture, 5,
+                                       info_p, count);
+}
 
-       *info_p = info;
+/****************************************************************************
+ Enumerates all printer drivers at level 6.
+****************************************************************************/
 
-       return WERR_OK;
+static WERROR enumprinterdrivers_level6(TALLOC_CTX *mem_ctx,
+                                       const char *servername,
+                                       const char *architecture,
+                                       union spoolss_DriverInfo **info_p,
+                                       uint32_t *count)
+{
+       return enumprinterdrivers_level(mem_ctx, servername, architecture, 6,
+                                       info_p, count);
 }
 
+
 /****************************************************************
  _spoolss_EnumPrinterDrivers
 ****************************************************************/
@@ -6851,6 +6960,21 @@ WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
                                                   r->in.environment,
                                                   r->out.info, r->out.count);
                break;
+       case 4:
+               result = enumprinterdrivers_level4(p->mem_ctx, cservername,
+                                                  r->in.environment,
+                                                  r->out.info, r->out.count);
+               break;
+       case 5:
+               result = enumprinterdrivers_level5(p->mem_ctx, cservername,
+                                                  r->in.environment,
+                                                  r->out.info, r->out.count);
+               break;
+       case 6:
+               result = enumprinterdrivers_level6(p->mem_ctx, cservername,
+                                                  r->in.environment,
+                                                  r->out.info, r->out.count);
+               break;
        default:
                return WERR_UNKNOWN_LEVEL;
        }
@@ -8143,6 +8267,7 @@ WERROR _spoolss_AddForm(pipes_struct *p,
        int snum;
        WERROR status = WERR_OK;
        NT_PRINTER_INFO_LEVEL *printer = NULL;
+       SE_PRIV se_printop = SE_PRINT_OPERATOR;
 
        int count=0;
        nt_forms_struct *list=NULL;
@@ -8169,10 +8294,17 @@ WERROR _spoolss_AddForm(pipes_struct *p,
                        goto done;
        }
 
-       if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
-               DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
-               status = WERR_ACCESS_DENIED;
-               goto done;
+       /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
+          and not a printer admin, then fail */
+
+       if ((p->server_info->utok.uid != sec_initial_uid()) &&
+            !user_has_privileges(p->server_info->ptok, &se_printop) &&
+            !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
+                                         NULL, NULL,
+                                         p->server_info->ptok,
+                                         lp_printer_admin(snum))) {
+               DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
+               return WERR_ACCESS_DENIED;
        }
 
        /* can't add if builtin */
@@ -8189,7 +8321,9 @@ WERROR _spoolss_AddForm(pipes_struct *p,
                goto done;
        }
 
+       become_root();
        write_ntforms(&list, count);
+       unbecome_root();
 
        /*
         * ChangeID must always be set if this is a printer
@@ -8221,6 +8355,8 @@ WERROR _spoolss_DeleteForm(pipes_struct *p,
        int snum;
        WERROR status = WERR_OK;
        NT_PRINTER_INFO_LEVEL *printer = NULL;
+       SE_PRIV se_printop = SE_PRINT_OPERATOR;
+       bool ret = false;
 
        DEBUG(5,("_spoolss_DeleteForm\n"));
 
@@ -8242,12 +8378,17 @@ WERROR _spoolss_DeleteForm(pipes_struct *p,
                        goto done;
        }
 
-       if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
-               DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
-               status = WERR_ACCESS_DENIED;
-               goto done;
+       if ((p->server_info->utok.uid != sec_initial_uid()) &&
+            !user_has_privileges(p->server_info->ptok, &se_printop) &&
+            !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
+                                         NULL, NULL,
+                                         p->server_info->ptok,
+                                         lp_printer_admin(snum))) {
+               DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
+               return WERR_ACCESS_DENIED;
        }
 
+
        /* can't delete if builtin */
 
        if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
@@ -8257,8 +8398,12 @@ WERROR _spoolss_DeleteForm(pipes_struct *p,
 
        count = get_ntforms(&list);
 
-       if ( !delete_a_form(&list, form_name, &count, &status ))
+       become_root();
+       ret = delete_a_form(&list, form_name, &count, &status);
+       unbecome_root();
+       if (ret == false) {
                goto done;
+       }
 
        /*
         * ChangeID must always be set if this is a printer
@@ -8287,6 +8432,7 @@ WERROR _spoolss_SetForm(pipes_struct *p,
        int snum;
        WERROR status = WERR_OK;
        NT_PRINTER_INFO_LEVEL *printer = NULL;
+       SE_PRIV se_printop = SE_PRINT_OPERATOR;
 
        int count=0;
        nt_forms_struct *list=NULL;
@@ -8312,10 +8458,17 @@ WERROR _spoolss_SetForm(pipes_struct *p,
                        goto done;
        }
 
-       if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
-               DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
-               status = WERR_ACCESS_DENIED;
-               goto done;
+       /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
+          and not a printer admin, then fail */
+
+       if ((p->server_info->utok.uid != sec_initial_uid()) &&
+            !user_has_privileges(p->server_info->ptok, &se_printop) &&
+            !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
+                                         NULL, NULL,
+                                         p->server_info->ptok,
+                                         lp_printer_admin(snum))) {
+               DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
+               return WERR_ACCESS_DENIED;
        }
 
        /* can't set if builtin */
@@ -8326,7 +8479,9 @@ WERROR _spoolss_SetForm(pipes_struct *p,
 
        count = get_ntforms(&list);
        update_a_form(&list, form, count);
+       become_root();
        write_ntforms(&list, count);
+       unbecome_root();
 
        /*
         * ChangeID must always be set if this is a printer
@@ -9798,6 +9953,18 @@ WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
        return WERR_OK;
 }
 
+/****************************************************************
+ _spoolss_AddPort
+****************************************************************/
+
+WERROR _spoolss_AddPort(pipes_struct *p,
+                       struct spoolss_AddPort *r)
+{
+       /* do what w2k3 does */
+
+       return WERR_NOT_SUPPORTED;
+}
+
 /****************************************************************
  _spoolss_AddPrinter
 ****************************************************************/
@@ -9842,17 +10009,6 @@ WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
        return WERR_NOT_SUPPORTED;
 }
 
-/****************************************************************
- _spoolss_AddPort
-****************************************************************/
-
-WERROR _spoolss_AddPort(pipes_struct *p,
-                       struct spoolss_AddPort *r)
-{
-       p->rng_fault_state = true;
-       return WERR_NOT_SUPPORTED;
-}
-
 /****************************************************************
  _spoolss_ConfigurePort
 ****************************************************************/