Changes from APPLIANCE_HEAD:
[samba.git] / source3 / printing / nt_printing.c
index 91679235cd70f6a09e5372f090d635a1bf6cdd73..2572a98bdea495315df7d9fa91ddaece0b6511a5 100644 (file)
@@ -35,6 +35,15 @@ static TDB_CONTEXT *tdb; /* used for driver files */
 
 #define DATABASE_VERSION 1
 
+/* Map generic permissions to printer object specific permissions */
+
+struct generic_mapping printer_generic_mapping = {
+       PRINTER_READ,
+       PRINTER_WRITE,
+       PRINTER_EXECUTE,
+       PRINTER_ALL_ACCESS
+};
+
 /* We need one default form to support our default printer. Msoft adds the
 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
 array index). Letter is always first, so (for the current code) additions
@@ -135,6 +144,7 @@ int write_ntforms(nt_forms_struct **list, int number)
                               (*list)[i].bottom);
                if (len > sizeof(buf)) break;
                slprintf(key, sizeof(key), "%s%s", FORMS_PREFIX, (*list)[i].name);
+        dos_to_unix(key, True);            /* Convert key to unix-codepage */
                kbuf.dsize = strlen(key)+1;
                kbuf.dptr = key;
                dbuf.dsize = len;
@@ -226,6 +236,7 @@ BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, uint32
        }
 
        slprintf(key, sizeof(key), "%s%s", FORMS_PREFIX, (*list)[n].name);
+       dos_to_unix(key, True);                /* Convert key to unix-codepage */
        kbuf.dsize = strlen(key)+1;
        kbuf.dptr = key;
        if (tdb_delete(tdb, kbuf) != 0) {
@@ -1292,27 +1303,41 @@ static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
 
        slprintf(directory, sizeof(directory), "\\print$\\%s\\%d\\", architecture, driver->cversion);
 
-       
-       fstrcpy(temp_name, driver->driverpath);
-       slprintf(driver->driverpath, sizeof(driver->driverpath), "%s%s", directory, temp_name);
+    /* .inf files do not always list a file for each of the four standard files. 
+     * Don't prepend a path to a null filename, or client claims:
+     *   "The server on which the printer resides does not have a suitable 
+     *   <printer driver name> printer driver installed. Click OK if you 
+     *   wish to install the driver on your local machine."
+     */
+       if (strlen(driver->driverpath)) {
+       fstrcpy(temp_name, driver->driverpath);
+       slprintf(driver->driverpath, sizeof(driver->driverpath), "%s%s", directory, temp_name);
+    }
 
-       fstrcpy(temp_name, driver->datafile);
-       slprintf(driver->datafile, sizeof(driver->datafile), "%s%s", directory, temp_name);
+       if (strlen(driver->datafile)) {
+       fstrcpy(temp_name, driver->datafile);
+       slprintf(driver->datafile, sizeof(driver->datafile), "%s%s", directory, temp_name);
+    }
 
-       fstrcpy(temp_name, driver->configfile);
-       slprintf(driver->configfile, sizeof(driver->configfile), "%s%s", directory, temp_name);
+       if (strlen(driver->configfile)) {
+       fstrcpy(temp_name, driver->configfile);
+       slprintf(driver->configfile, sizeof(driver->configfile), "%s%s", directory, temp_name);
+    }
 
-       fstrcpy(temp_name, driver->helpfile);
-       slprintf(driver->helpfile, sizeof(driver->helpfile), "%s%s", directory, temp_name);
+       if (strlen(driver->helpfile)) {
+       fstrcpy(temp_name, driver->helpfile);
+       slprintf(driver->helpfile, sizeof(driver->helpfile), "%s%s", directory, temp_name);
+    }
 
        if (driver->dependentfiles) {
                for (i=0; *driver->dependentfiles[i]; i++) {
-                       fstrcpy(temp_name, driver->dependentfiles[i]);
-                       slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i]), "%s%s", directory, temp_name);
+            fstrcpy(temp_name, driver->dependentfiles[i]);
+            slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i]), "%s%s", directory, temp_name);
                }
        }
 
        slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
+       dos_to_unix(key, True);                /* Convert key to unix-codepage */
 
        DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
 
@@ -1676,8 +1701,8 @@ uint32 del_a_printer(char *sharename)
        pstring key;
        TDB_DATA kbuf;
 
-       slprintf(key, sizeof(key), "%s%s",
-                PRINTERS_PREFIX, sharename);
+       slprintf(key, sizeof(key), "%s%s", PRINTERS_PREFIX, sharename);
+       dos_to_unix(key, True);                /* Convert key to unix-codepage */
 
        kbuf.dptr=key;
        kbuf.dsize=strlen(key)+1;
@@ -1759,8 +1784,8 @@ static uint32 update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
        }
        
 
-       slprintf(key, sizeof(key), "%s%s",
-                PRINTERS_PREFIX, info->sharename);
+       slprintf(key, sizeof(key), "%s%s", PRINTERS_PREFIX, info->sharename);
+       dos_to_unix(key, True);                /* Convert key to unix-codepage */
 
        kbuf.dptr = key;
        kbuf.dsize = strlen(key)+1;
@@ -2187,6 +2212,7 @@ static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharen
        ZERO_STRUCT(info);
 
        slprintf(key, sizeof(key), "%s%s", PRINTERS_PREFIX, sharename);
+       dos_to_unix(key, True);                /* Convert key to unix-codepage */
 
        kbuf.dptr = key;
        kbuf.dsize = strlen(key)+1;
@@ -2833,11 +2859,16 @@ BOOL nt_printing_getsec(char *printername, SEC_DESC_BUF **secdesc_ctr)
        prs_struct ps;
        TALLOC_CTX *mem_ctx = NULL;
        fstring key;
+       char *temp;
 
        mem_ctx = talloc_init();
        if (mem_ctx == NULL)
                return False;
 
+       if ((temp = strchr(printername + 2, '\\'))) {
+               printername = temp + 1;
+       }
+
        /* Fetch security descriptor from tdb */
 
        slprintf(key, sizeof(key), "SECDESC/%s", printername);
@@ -2910,8 +2941,9 @@ BOOL nt_printing_getsec(char *printername, SEC_DESC_BUF **secdesc_ctr)
 
                        sid_to_string(sid_str, &acl->ace[i].sid);
 
-                       DEBUG(10, ("%s 0x%08x\n", sid_str, 
-                                 acl->ace[i].info.mask));
+                       DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
+                                  acl->ace[i].type, acl->ace[i].flags, 
+                                  acl->ace[i].info.mask)); 
                }
        }
 
@@ -2956,6 +2988,20 @@ jfm: I should use this comment for the text file to explain
 
 */
 
+/* Convert generic access rights to printer object specific access rights.
+   It turns out that NT4 security descriptors use generic access rights and
+   NT5 the object specific ones. */
+
+void map_printer_permissions(SEC_DESC *sd)
+{
+       int i;
+
+       for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
+               se_map_generic(&sd->dacl->ace[i].info.mask,
+                              &printer_generic_mapping);
+       }
+}
+
 /****************************************************************************
  Check a user has permissions to perform the given operation.  We use some
  constants defined in include/rpc_spoolss.h that look relevant to check
@@ -2969,7 +3015,7 @@ jfm: I should use this comment for the text file to explain
    PRINTER_ACCESS_USE:
        print_job_start
 
-   JOB_ACCESS_ADMINISTER:
+   PRINTER_ACCESS_ADMINISTER (should really be JOB_ACCESS_ADMINISTER):
        print_job_delete, print_job_pause, print_job_resume,
        print_queue_purge
 
@@ -2977,7 +3023,7 @@ jfm: I should use this comment for the text file to explain
 BOOL print_access_check(struct current_user *user, int snum, int access_type)
 {
        SEC_DESC_BUF *secdesc = NULL;
-       uint32 access_granted, status, required_access = 0;
+       uint32 access_granted, status;
        BOOL result;
        char *pname;
        extern struct current_user current_user;
@@ -3008,77 +3054,14 @@ BOOL print_access_check(struct current_user *user, int snum, int access_type)
        /* Get printer security descriptor */
 
        nt_printing_getsec(pname, &secdesc);
-
-       /* Check against NT4 ACE mask values.  From observation these
-          values are:
-
-              Access Type       ACE Mask    Constant
-              -------------------------------------
-              Full Control      0x10000000  PRINTER_ACE_FULL_CONTROL
-              Print             0xe0000000  PRINTER_ACE_PRINT
-              Manage Documents  0x00020000  PRINTER_ACE_MANAGE_DOCUMENTS
-       */
-
-    switch (access_type) {
-    case PRINTER_ACCESS_USE:
-           required_access = PRINTER_ACE_PRINT;
-           break;
-    case PRINTER_ACCESS_ADMINISTER:
-               /* 
-                * This should be set to PRINTER_ACE_FULL_CONTROL, not to
-                * (PRINTER_ACE_PRINT | PRINTER_ACE_MANAGE_DOCUMENTS).
-                * Doing the latter gives anyone with both PRINTER_ACE_PRINT
-                * and PRINTER_ACE_MANAGE_DOCUMENTS (in any combination of ACLs)
-                * full control over all printer functions.  This isn't what 
-                * we want.
-                */
-               required_access = PRINTER_ACE_FULL_CONTROL; 
-               break;
-       case JOB_ACCESS_ADMINISTER:
-               required_access = PRINTER_ACE_MANAGE_DOCUMENTS;
-               break;
-       default:
-               DEBUG(0, ("invalid value passed to print_access_check()\n"));
-               result = False;
-               goto done;
-       }       
        
-       if ((result = se_access_check(secdesc->sec, user, required_access,
-                                     &access_granted, &status))) {
-               goto done;
-       }
-
-       /* Check against NT5 ACE mask values.  From observation these
-          values are:
-
-              Access Type       ACE Mask    Constant
-              -------------------------------------
-              Full Control      0x000f000c  PRINTER_ACE_NT5_FULL_CONTROL
-              Print             0x00020008  PRINTER_ACE_NT5_PRINT
-              Manage Documents  0x00020000  PRINTER_ACE_NT5_MANAGE_DOCUMENTS
-
-          NT5 likes to rewrite the security descriptor and change the ACE
-          masks from NT4 format to NT5 format making them unreadable by
-          NT4 clients. */
-
-       switch (access_type) {
-       case PRINTER_ACCESS_USE:
-               required_access = PRINTER_ACE_NT5_PRINT;
-               break;
-       case PRINTER_ACCESS_ADMINISTER:
-               required_access = PRINTER_ACE_NT5_FULL_CONTROL;
-               break;
-       case JOB_ACCESS_ADMINISTER:
-               required_access = PRINTER_ACE_NT5_MANAGE_DOCUMENTS;
-               break;
-       }       
-
-       result = se_access_check(secdesc->sec, user, required_access,
+       map_printer_permissions(secdesc->sec);
+
+       result = se_access_check(secdesc->sec, user, access_type,
                                 &access_granted, &status);
 
        /* Check access */
        
- done:
        DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
        
        /* Free mallocated memory */