summaryrefslogtreecommitdiff
path: root/source3/printing
diff options
context:
space:
mode:
authorDavid O'Neill <dmo@samba.org>2000-09-01 18:49:26 +0000
committerDavid O'Neill <dmo@samba.org>2000-09-01 18:49:26 +0000
commita3a28675fafbbc5a5a378b3a7235253d772ef63e (patch)
tree65eb150c18125c199b8e289b9027de8d69344413 /source3/printing
parentbfa751734a1229a25bb3f33edc7710a1efee376d (diff)
downloadsamba-a3a28675fafbbc5a5a378b3a7235253d772ef63e.tar.gz
samba-a3a28675fafbbc5a5a378b3a7235253d772ef63e.tar.bz2
samba-a3a28675fafbbc5a5a378b3a7235253d772ef63e.zip
Changes from APPLIANCE_HEAD (per Tim Potter):
- make proto - addition of function to convert from errno values to NT status codes (source/lib/error.c) - purge queue done without full access permission will purge only the jobs owned by that user, rather than failing. - unlock job database tdb before sending job to printer - in print_job_start(), ensure that we don't pick a jobid with an existing temporary file that may be owned by another user, as it causes silent failures. - fixes for printer permission checking for NT5 clients (source/include/rpc_spoolss.h, source/printing/nt_printing.c, source/printing/printing.c, source/rpc_server/srv_spoolss_nt.c) - change from uint8 to 'enum SID_NAME_USE' (source/rpc_server/srv_lsa.c) - fixed memory leaks for win95 driver download process (source/smbd/lanman.c) - properly free prs_structs and dacl in testsuite/printing/psec.c (This used to be commit 74af3e2caec7197e5d1ca389e2f78054a4197502)
Diffstat (limited to 'source3/printing')
-rw-r--r--source3/printing/nt_printing.c103
-rw-r--r--source3/printing/printing.c30
2 files changed, 99 insertions, 34 deletions
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c
index 05ab71d178..0ad50a2277 100644
--- a/source3/printing/nt_printing.c
+++ b/source3/printing/nt_printing.c
@@ -2203,30 +2203,47 @@ jfm: I should use this comment for the text file to explain
*/
/****************************************************************************
- Check a user has permissions to perform the given operation
+ 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
+ the various actions we perform when checking printer access.
+
+ PRINTER_ACCESS_ADMINISTER:
+ print_queue_pause, print_queue_resume, update_printer_sec,
+ update_printer, spoolss_addprinterex_level_2,
+ _spoolss_setprinterdata
+
+ PRINTER_ACCESS_USE:
+ print_job_start
+
+ JOB_ACCESS_ADMINISTER:
+ print_job_delete, print_job_pause, print_job_resume,
+ print_queue_purge
- if user is NULL then use the current_user structure
****************************************************************************/
-BOOL print_access_check(struct current_user *user, int snum,
- uint32 required_access)
+BOOL print_access_check(struct current_user *user, int snum, int access_type)
{
SEC_DESC_BUF *secdesc = NULL;
- uint32 access_granted, status;
+ uint32 access_granted, status, required_access = 0;
BOOL result;
char *pname;
int i;
extern struct current_user current_user;
+ /* If user is NULL then use the current_user structure */
+
if (!user) user = &current_user;
- /* always allow root or printer admins to do anything */
- if (user->uid==0 ||
+ /* Always allow root or printer admins to do anything */
+
+ if (user->uid == 0 ||
user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
return True;
}
/* Get printer name */
+
pname = PRINTERNAME(snum);
+
if (!pname || !*pname)
pname = SERVICE(snum);
@@ -2236,8 +2253,34 @@ BOOL print_access_check(struct current_user *user, int snum,
}
/* 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:
+ required_access = PRINTER_ACE_MANAGE_DOCUMENTS |
+ PRINTER_ACE_PRINT;
+ break;
+ case JOB_ACCESS_ADMINISTER:
+ required_access = PRINTER_ACE_MANAGE_DOCUMENTS;
+ default:
+ DEBUG(0, ("invalid value passed to print_access_check()\n"));
+ return False;
+ }
+
/* 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
@@ -2249,16 +2292,6 @@ BOOL print_access_check(struct current_user *user, int snum,
performing the access check. I'm sure there is a better way to
do this! */
- /* You forgot to also change the *required access* from PRINTER_ACE_FULL_CONTROL
- to PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT before doing the check.
- This took me 3 hours to find !!!!! JRA.
- */
-
- if (required_access & PRINTER_ACE_FULL_CONTROL) {
- required_access |= (PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT);
- required_access &= ~PRINTER_ACE_FULL_CONTROL;
- }
-
if (secdesc && secdesc->sec && secdesc->sec->dacl &&
secdesc->sec->dacl->ace) {
for(i = 0; i < secdesc->sec->dacl->num_aces; i++) {
@@ -2271,14 +2304,46 @@ BOOL print_access_check(struct current_user *user, int snum,
}
}
- /* Check access */
+ 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,
&access_granted, &status);
+ /* Check access */
+
+ done:
DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
-
+
/* Free mallocated memory */
+
free_sec_desc_buf(&secdesc);
if (!result)
diff --git a/source3/printing/printing.c b/source3/printing/printing.c
index cf3748ed16..406cbf2c80 100644
--- a/source3/printing/printing.c
+++ b/source3/printing/printing.c
@@ -507,7 +507,7 @@ BOOL print_job_delete(struct current_user *user, int jobid)
owns their job. */
if (!owner &&
- !print_access_check(user, snum, PRINTER_ACE_MANAGE_DOCUMENTS)) {
+ !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
DEBUG(3, ("delete denied by security descriptor\n"));
return False;
}
@@ -542,7 +542,7 @@ BOOL print_job_pause(struct current_user *user, int jobid)
owner = is_owner(user->uid, jobid);
if (!owner &&
- !print_access_check(user, snum, PRINTER_ACE_MANAGE_DOCUMENTS)) {
+ !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
DEBUG(3, ("pause denied by security descriptor\n"));
return False;
}
@@ -579,7 +579,7 @@ BOOL print_job_resume(struct current_user *user, int jobid)
owner = is_owner(user->uid, jobid);
if (!is_owner(user->uid, jobid) &&
- !print_access_check(user, snum, PRINTER_ACE_MANAGE_DOCUMENTS)) {
+ !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
DEBUG(3, ("resume denied by security descriptor\n"));
return False;
}
@@ -624,9 +624,9 @@ int print_job_start(struct current_user *user, int snum, char *jobname)
errno = 0;
- if (!print_access_check(user, snum, PRINTER_ACE_PRINT)) {
+ if (!print_access_check(user, snum, PRINTER_ACCESS_USE)) {
DEBUG(3, ("job start denied by security descriptor\n"));
- return False;
+ return -1;
}
path = lp_pathname(snum);
@@ -665,6 +665,7 @@ int print_job_start(struct current_user *user, int snum, char *jobname)
/* lock the database */
tdb_writelock(tdb);
+ next_jobnum:
next_jobid = tdb_fetch_int(tdb, "INFO/nextjob");
if (next_jobid == -1) next_jobid = 1;
@@ -684,17 +685,20 @@ int print_job_start(struct current_user *user, int snum, char *jobname)
we unlink first to cope with old spool files and also to beat
a symlink security hole - it allows us to use O_EXCL
+ There may be old spool files owned by other users lying around.
*/
slprintf(pjob.filename, sizeof(pjob.filename), "%s/%s%d",
path, PRINT_SPOOL_PREFIX, jobid);
if (unlink(pjob.filename) == -1 && errno != ENOENT) {
- goto fail;
+ goto next_jobnum;
}
pjob.fd = sys_open(pjob.filename,O_WRONLY|O_CREAT|O_EXCL,0600);
if (pjob.fd == -1) goto fail;
print_job_store(jobid, &pjob);
+ tdb_writeunlock(tdb);
+
/*
* If the printer is marked as postscript output a leading
* file identifier to ensure the file is treated as a raw
@@ -706,7 +710,6 @@ int print_job_start(struct current_user *user, int snum, char *jobname)
print_job_write(jobid, "%!\n",3);
}
- tdb_writeunlock(tdb);
return jobid;
fail:
@@ -896,7 +899,7 @@ BOOL print_queue_pause(struct current_user *user, int snum, int *errcode)
if (!user) return False;
- if (!print_access_check(user, snum, PRINTER_ACE_MANAGE_DOCUMENTS)) {
+ if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
*errcode = ERROR_ACCESS_DENIED;
return False;
}
@@ -917,7 +920,7 @@ BOOL print_queue_resume(struct current_user *user, int snum, int *errcode)
{
int ret;
- if (!print_access_check(user, snum, PRINTER_ACE_MANAGE_DOCUMENTS)) {
+ if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
*errcode = ERROR_ACCESS_DENIED;
return False;
}
@@ -940,14 +943,11 @@ BOOL print_queue_purge(struct current_user *user, int snum, int *errcode)
print_status_struct status;
int njobs, i;
- if (!print_access_check(user, snum, PRINTER_ACE_MANAGE_DOCUMENTS)) {
- *errcode = ERROR_ACCESS_DENIED;
- return False;
- }
-
njobs = print_queue_status(snum, &queue, &status);
for (i=0;i<njobs;i++) {
- print_job_delete1(queue[i].job);
+ if (print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
+ print_job_delete1(queue[i].job);
+ }
}
print_cache_flush(snum);