#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
(*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;
}
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) {
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 ));
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;
}
- 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;
*/
len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
devmode.driverextra=(uint16)extra_len;
+
+ /* check to catch an invalid TDB entry so we don't segfault */
+ if (devmode.driverextra == 0) {
+ devmode.private = NULL;
+ }
}
*nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
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;
static SEC_DESC_BUF *construct_default_printer_sdb(void)
{
- SEC_ACE ace[2];
+ SEC_ACE ace[3];
SEC_ACCESS sa;
SEC_ACL *psa = NULL;
SEC_DESC_BUF *sdb = NULL;
init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
-
/* Make the security descriptor owned by the Administrators group
on the PDC of the domain. */
}
}
- init_sec_access(&sa, PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT);
+ init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
+ sa, SEC_ACE_FLAG_OBJECT_INHERIT |
+ SEC_ACE_FLAG_INHERIT_ONLY);
+
+ init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
+ init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
/* The ACL revision number in rpc_secdesc.h differs from the one
#define NT4_ACL_REVISION 0x2
- if ((psa = make_sec_acl(NT4_ACL_REVISION, 2, ace)) != NULL) {
+ if ((psa = make_sec_acl(NT4_ACL_REVISION, 3, ace)) != NULL) {
psd = make_sec_desc(SEC_DESC_REVISION,
&owner_sid, NULL,
NULL, psa, &sd_size);
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);
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));
}
}
*/
+/* 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
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
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;
- int i;
extern struct current_user current_user;
/* If user is NULL then use the current_user structure */
/* Get printer security descriptor */
nt_printing_getsec(pname, &secdesc);
+
+ map_printer_permissions(secdesc->sec);
- /* 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:
- required_access = PRINTER_ACE_MANAGE_DOCUMENTS |
- PRINTER_ACE_PRINT;
- 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;
- }
-
- /* The ACE for Full Control in a printer security descriptor
- doesn't seem to map properly to the access checking model. For
- it to work properly it should be the logical OR of all the other
- values, i.e PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT.
- This would cause the access check to simply fall out when we
- check against any subset of these bits. To get things to work,
- change every ACE mask of PRINTER_ACE_FULL_CONTROL to
- PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT before
- performing the access check. I'm sure there is a better way to
- do this! */
-
- if (secdesc && secdesc->sec && secdesc->sec->dacl &&
- secdesc->sec->dacl->ace) {
- for(i = 0; i < secdesc->sec->dacl->num_aces; i++) {
- if (secdesc->sec->dacl->ace[i].info.mask ==
- PRINTER_ACE_FULL_CONTROL) {
- secdesc->sec->dacl->ace[i].info.mask =
- PRINTER_ACE_MANAGE_DOCUMENTS |
- PRINTER_ACE_PRINT;
- }
- }
- }
-
- 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,
+ 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 */