I've posted the latest cups src.rpms and patches up on
http://free.linux.hp.com/~mra/rpms/
http://free.linux.hp.com/~mra/patches/cups-lspp.patch
the cups-lspp.patch file is also attached to this mail.
This version introduces a new file which by default lives in
/usr/lib/cups/daemon/access which accepts a filename as its argument and
then calls access() to see if it has read and write access to the file.
CUPS exec's this with the path to a printer after using setexeccon() to
assume the context which the user had when the job was sent to the
server. The check is performed twice, once during the enqueue, so the
user can get a permission denied on the command line. Again just before
actually printing the job so that if the printer's level has changed it
will be caught.
The architecture of CUPS is such that this last check will occur prior
to running the filters and sending it to the backend, so there is still
a window of opportunity here for the level to change. In this case
SELinux comes to the rescue and prevents the data from leaving the
system. The downside is that CUPS doesn't know whats going on, and the
job stays active and holds up the queue. Nothing an lprm can't fix.
This has been tested with a parallel port printer, and works well there.
I haven't yet gotten a USB printer with which to test this with. It
should work fine there, but CUPS has some interesting device URIs and I
may not have caught all cases.
CUPS also doesn't have an easy way to determine if a device is local or
not. It has a concept of local vs remote printers, but that has more to
do with who is the scheduler vs if the printer is directly attached
(please correct me if I'm wrong here.) As a result the access check is
only performed if the printer is found to start with "/dev/" For
evaluation purposes this should be fine since we can require that in the
configuration guide.
One question I have for the perspective users is what would be preferred
actions? Right now if you try to print, but cannot currently access the
device you get denied. If your job is getting ready to be sent but
can't access the device the job is canceled. Is this what you'd want to
happen? I could just as easily accept all jobs, and leave the in the
queue if they aren't able to access the printer. After some internal
discussion it was decided that rather than leaving it in the queue an
immediate error would be more transparent for the user.
As I mentioned on the call Monday I'll be on vacation this coming week.
Knowing me I'll still check my mail, but I won't be able to access a
system to run any tests. Please feel free to comment, but don't be
offended if I don't respond right away.
thanks
-matt
ps. In my final testing I've noticed that with Classification set to mls
this version hangs the queue after printing the banner page. With
Classification unset the access check appears to function correctly. I
may have an update for this over the weekend, but I really must leave
now so consider this a known bug.
Index: cups-1.1.23/scheduler/ipp.c
===================================================================
--- cups-1.1.23/scheduler/ipp.c (revision 3)
+++ cups-1.1.23/scheduler/ipp.c (working copy)
@@ -74,6 +74,9 @@
* validate_user() - Validate the user for the request.
*/
+/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */
+/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */
+
/*
* Include necessary headers...
*/
@@ -86,6 +89,11 @@
# include <paper.h>
#endif /* HAVE_LIBPAPER */
+#ifdef WITH_LSPP
+#include <selinux/selinux.h>
+#include <selinux/context.h>
+#include <libaudit.h>
+#endif /* WITH_LSPP */
/*
* PPD default choice structure...
@@ -2254,6 +2262,10 @@
char attrname[255], /* Name of attribute */
*s; /* Pointer into name */
ipp_attribute_t *attr; /* Attribute */
+#ifdef WITH_LSPP
+ const char *mls_label; /* SL of print job */
+ context_t job_context; /* SELinux context of the job */
+#endif /* WITH_LSPP */
LogMessage(L_DEBUG2, "copy_banner(%p[%d], %p[%d], %s)",
@@ -2380,6 +2392,22 @@
else
s = attrname;
+#ifdef WITH_LSPP
+ if (strcmp(s, "mls-label") == 0)
+ {
+ if (strcmp(job->scon, "UNKNOWN SL") == 0)
+ cupsFilePuts(out, "UNKNOWN SL");
+ else
+ {
+ job_context = context_new(job->scon);
+ mls_label = context_range_get(job_context);
+ cupsFilePuts(out, mls_label);
+ context_free(job_context);
+ }
+
+ continue;
+ }
+#endif /* WITH_LSPP */
if (strcmp(s, "printer-name") == 0)
{
cupsFilePuts(out, job->dest);
@@ -2926,6 +2954,33 @@
return;
}
+#ifdef WITH_LSPP
+ if (!con->scon || strlen(con->scon) == 0)
+ {
+ LogMessage(L_ERROR, "create_job: missing classification for connection \'%s\'!", dest);
+ if (is_lspp_config())
+ {
+ send_ipp_error(con, IPP_INTERNAL_ERROR);
+ return;
+ }
+ }
+ else
+ {
+ /*
+ * duplicate the security context and auid of the connection into the job structure
+ */
+ job->scon = strdup(con->scon);
+ job->auid = con->auid;
+
+ /*
+ * add the security context to the request so that on a restart the security
+ * attributes will be able to be restored
+ */
+ ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_NAME, "security-context",
+ NULL, job->scon);
+ }
+#endif /* WITH_LSPP */
+
job->dtype = dtype;
job->attrs = con->request;
con->request = NULL;
@@ -3203,6 +3258,7 @@
else if ((attr = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_ZERO)) != NULL)
job->sheets = attr;
+
/*
* Save and log the job...
*/
@@ -4491,8 +4547,16 @@
int i; /* Looping var */
int lowerpagerange; /* Page range bound */
int compression; /* Document compression */
+#ifdef WITH_LSPP
+ char *audit_message; /* Audit message string */
+ int status; /* return value of the access check */
+ pid_t acpid; /* pid for the access check */
+ char *printerfile; /* The device file pointed to by a local printer */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* POSIX signal handler */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+#endif /* WITH_LSPP */
-
LogMessage(L_DEBUG2, "print_job(%p[%d], %s)\n", con, con->http.fd,
uri->values[0].string.text);
@@ -4764,6 +4828,139 @@
return;
}
+#ifdef WITH_LSPP
+ if (!con->scon || strlen(con->scon) == 0)
+ {
+ if (is_lspp_config())
+ {
+ LogMessage(L_ERROR, "print_job: missing classification for connection \'%s\'!", dest);
+ send_ipp_error(con, IPP_INTERNAL_ERROR);
+ return;
+ }
+ }
+ else
+ {
+ /*
+ * duplicate the security context and auid of the connection into the job structure
+ */
+ job->scon = strdup(con->scon);
+ job->auid = con->auid;
+
+ /*
+ * add the security context to the request so that on a restart the security
+ * attributes will be able to be restored
+ */
+ ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_NAME, "security-context",
+ NULL, job->scon);
+ }
+
+ /*
+ * Perform an access check so that if the user gets feedback at enqueue time
+ */
+ HoldSignals();
+
+ if (setexeccon(job->scon) != 0)
+ {
+ LogMessage(L_ERROR, "print_job: Unable to setexeccon to %s", job->scon);
+ send_ipp_error(con, IPP_INTERNAL_ERROR);
+ return;
+ }
+
+ printerfile = strdup(printer->device_uri);
+ if ((printerfile = strrchr(printer->device_uri, '=')) == NULL)
+ {
+ if ((printerfile = strrchr(printer->device_uri, ':')) == NULL)
+ {
+ LogMessage(L_ERROR, "print_job: Unable to determine printer device file");
+ send_ipp_error(con, IPP_INTERNAL_ERROR);
+ return;
+ }
+ }
+
+ printerfile++;
+
+ /*
+ * Only perform the access check if the device_uri decodes to start with /dev/
+ */
+
+ if (strncmp(printerfile, "/dev/", 5) == 0)
+ {
+ LogMessage(L_DEBUG, "print_job: Attempting an access check on printer device %s",
+ printerfile);
+
+ if ((acpid = fork()) == 0)
+ {
+ /*
+ * Child..
+ * Unblock signals before doing the exec...
+ */
+
+#ifdef HAVE_SIGSET
+ sigset(SIGTERM, SIG_DFL);
+ sigset(SIGCHLD, SIG_DFL);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = SIG_DFL;
+
+ sigaction(SIGTERM, &action, NULL);
+ sigaction(SIGCHLD, &action, NULL);
+#else
+ signal(SIGTERM, SIG_DFL);
+ signal(SIGCHLD, SIG_DFL);
+#endif /* HAVE_SIGSET */
+
+ ReleaseSignals();
+
+ /*
+ * setexeccon has been issued with the job's context so exec the access check
+ */
+ execl(CUPS_SERVERBIN "/daemon/access", "access", printerfile, NULL);
+ }
+ if (acpid < 0)
+ {
+ /*
+ * The fork() failed, something terrible is wrong, fail the enqueue
+ */
+ LogMessage(L_ERROR, "StartJob: Unable to fork access check - %s",
+ strerror(errno));
+
+ send_ipp_error(con, IPP_INTERNAL_ERROR);
+ return;
+ }
+ else
+ {
+ waitpid(acpid, &status, 0);
+ if (WIFEXITED(status))
+ {
+ if (WEXITSTATUS(status) != 0)
+ {
+ /*
+ * The access check failed, so cancel the job and send an audit message
+ */
+ audit_message = NULL;
+ SetStringf(&audit_message, "job=%d refused, auid=%u acct=%s unable to access printer=%s",
+ job->id, con->auid, con->username, printer->name);
+ audit_log_user_message(AuditLog, AUDIT_USER_LABELED_EXPORT, audit_message,
+ ServerName, NULL, NULL, 0);
+ free(audit_message);
+
+ send_ipp_error(con, IPP_NOT_AUTHORIZED);
+ return;
+ }
+ else
+ {
+ LogMessage(L_DEBUG, "print_job: access check succeeded (returned %d)",
+ WEXITSTATUS(status));
+ }
+ }
+ }
+
+ ReleaseSignals();
+ }
+#endif /* WITH_LSPP */
+
job->dtype = dtype;
job->attrs = con->request;
con->request = NULL;
@@ -4919,6 +5116,57 @@
SetJobHoldUntil(job->id, attr->values[0].string.text);
}
+#ifdef WITH_LSPP
+ if (is_lspp_config())
+ {
+ if (ClassifyOverride)
+ {
+ /*
+ * The configuration allows for user's to Override the banner, so let them
+ */
+ audit_message = NULL;
+ SetStringf(&audit_message, "job=%d user supplied classification \"%s\" \"%s\"", job->id,
+ (attr->values[0].string.text)?attr->values[0].string.text:"none",
+ (attr->values[1].string.text)?attr->values[1].string.text:"none");
+ audit_log_user_message(AuditLog, AUDIT_LABEL_OVERRIDE, audit_message,
+ ServerName, NULL, NULL, 1);
+ free(audit_message);
+ }
+ else
+ {
+ if ((attr = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_ZERO)) == NULL)
+ {
+ /*
+ * If its not set the user was accepting the defaults, so apply the banners
+ */
+ LogMessage(L_DEBUG, "Adding default job-sheets values \"%s,%s\"",
+ MLS_TEMPLATE, MLS_TEMPLATE);
+ }
+ else
+ {
+ /*
+ * The user supplied some cruft so log it, delete it and move on
+ */
+ LogMessage(L_DEBUG, "Deleting unknown job-sheets values \"%s,%s\"",
+ (attr->values[0].string.text)?attr->values[0].string.text:"none",
+ (attr->values[1].string.text)?attr->values[1].string.text:"none");
+ ippDeleteAttribute(job->attrs, attr);
+ }
+
+ attr = ippAddStrings(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, "job-sheets",
+ 2, NULL, NULL);
+ attr->values[0].string.text = strdup(MLS_TEMPLATE);
+ attr->values[1].string.text = strdup(MLS_TEMPLATE);
+
+ job->job_sheets = attr;
+
+ kbytes = copy_banner(con, job, attr->values[0].string.text);
+
+ UpdateQuota(printer, job->username, 0, kbytes);
+ }
+ }
+#else /* !WITH_LSPP */
+
if (!(printer->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)) ||
Classification)
{
@@ -5046,6 +5294,8 @@
else if ((attr = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_ZERO)) != NULL)
job->sheets = attr;
+#endif /* WITH_LSPP */
+
/*
* Add the job file...
*/
@@ -5976,6 +6226,23 @@
if ((attr = ippFindAttribute(con->request, "last-document", IPP_TAG_BOOLEAN)) != NULL &&
attr->values[0].boolean)
{
+#ifdef WITH_LSPP
+ if (printer != NULL &&
+ (attr = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_ZERO)) != NULL &&
+ attr->num_values > 1)
+ {
+ /*
+ * Yes...
+ */
+
+ LogMessage(L_INFO, "Adding MLS end banner page \"%s\" to job %d.",
+ attr->values[1].string.text, job->id);
+
+ kbytes = copy_banner(con, job, attr->values[1].string.text);
+
+ UpdateQuota(printer, job->username, 0, kbytes);
+ }
+#else /* WITH_LSPP */
/*
* See if we need to add the ending sheet...
*/
@@ -5996,6 +6263,7 @@
UpdateQuota(printer, job->username, 0, kbytes);
}
+#endif /* WITH_LSPP */
if (job->state->values[0].integer == IPP_JOB_STOPPED)
job->state->values[0].integer = IPP_JOB_PENDING;
Index: cups-1.1.23/scheduler/Makefile
===================================================================
--- cups-1.1.23/scheduler/Makefile (revision 3)
+++ cups-1.1.23/scheduler/Makefile (working copy)
@@ -35,8 +35,8 @@
ppds.o printers.o quotas.o server.o
MIMEOBJS = file.o filter.o mime.o type.o
OBJS = $(CUPSDOBJS) $(MIMEOBJS) cups-lpd.o cups-polld.o testmime.o \
- testspeed.o
-TARGETS = cupsd cups-lpd cups-polld libmime.a testmime testspeed
+ testspeed.o access.o
+TARGETS = cupsd cups-lpd cups-polld libmime.a testmime testspeed access
#
# Make everything...
@@ -72,6 +72,7 @@
$(INSTALL_DIR) $(SERVERBIN)/daemon
$(INSTALL_BIN) cups-lpd $(SERVERBIN)/daemon
$(INSTALL_BIN) cups-polld $(SERVERBIN)/daemon
+ $(INSTALL_BIN) access $(SERVERBIN)/daemon
$(INSTALL_DIR) -m 711 $(SERVERROOT)/certs
$(INSTALL_DIR) $(SERVERROOT)/interfaces
$(INSTALL_DIR) $(SERVERROOT)/ppd
Index: cups-1.1.23/scheduler/access.c
===================================================================
--- cups-1.1.23/scheduler/access.c (revision 0)
+++ cups-1.1.23/scheduler/access.c (revision 13)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) Hewlett-Packard Development Company, L.P., 2006
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Contents:
+ *
+ * main() - Main entry for the access checker.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+int main(int argc, char *argv[]) {
+ int status = -1;
+ char filename[256] = {0};
+
+ if (argc < 2)
+ {
+ printf("Check for access to which file? ");
+ scanf("%s", (char *)&filename);
+ }
+ else
+ {
+ strncpy(filename, argv[1], 255);
+ }
+
+ status = access(filename, R_OK|W_OK);
+
+ if (argc < 2)
+ {
+ /*
+ * Assume the user would like to hear the answer on the terminal
+ * since the filename was received interactively.
+ */
+ if (status != 0)
+ printf("Unable to access that file.\n");
+ else
+ printf("Access Granted\n");
+ }
+
+ return (status == 0)?0:1;
+}
Index: cups-1.1.23/scheduler/job.c
===================================================================
--- cups-1.1.23/scheduler/job.c (revision 3)
+++ cups-1.1.23/scheduler/job.c (working copy)
@@ -56,6 +56,9 @@
* set_hold_until() - Set the hold time and update job-hold-until attribute.
*/
+/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */
+/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */
+
/*
* Include necessary headers...
*/
@@ -63,6 +66,11 @@
#include "cupsd.h"
#include <grp.h>
+#ifdef WITH_LSPP
+#include <selinux/selinux.h>
+#include <selinux/context.h>
+#include <libaudit.h>
+#endif /* WITH_LSPP */
/*
* Local globals...
@@ -693,6 +701,19 @@
SetString(&job->dest, dest);
+#ifdef WITH_LSPP
+ if ((attr = ippFindAttribute(job->attrs, "security-context", IPP_TAG_NAME)) == NULL)
+ {
+ LogMessage(L_ERROR, "LoadAllJobs: Missing or bad security-context attribute in control file \"%s\"!",
+ filename);
+ ippDelete(job->attrs);
+ free(job);
+ unlink(filename);
+ continue;
+ }
+ SetString(&job->scon, attr->values[0].string.text);
+#endif /* WITH_LSPP */
+
job->sheets = ippFindAttribute(job->attrs, "job-media-sheets-completed",
IPP_TAG_INTEGER);
job->job_sheets = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_NAME);
@@ -1225,6 +1246,17 @@
ld_assume_kernel[1024]; /* LD_ASSUME_KERNEL environment variable */
static char *options = NULL; /* Full list of options */
static int optlength = 0; /* Length of option buffer */
+#ifdef WITH_LSPP
+ int status = 0; /* return value of the access check */
+ pid_t acpid = -1; /* pid for the access check */
+ const char *mls_label = NULL; /* SL to put in classification env var */
+ char *audit_message = NULL; /* Audit message string */
+ char *printerfile = NULL; /* The device file pointed to by a local printer */
+ context_t job_context; /* SELinux context of the job */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* POSIX signal handler */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+#endif /* WITH_LSPP */
LogMessage(L_DEBUG, "StartJob(%d, %p)", id, printer);
@@ -1435,7 +1467,110 @@
LogMessage(L_DEBUG, "banner_page = %d", banner_page);
+#ifdef WITH_LSPP
/*
+ * Perform an access check before printing, but only if the printer starts with /dev/
+ */
+ printerfile = strdup(printer->device_uri);
+ if ((printerfile = strrchr(printer->device_uri, '=')) == NULL)
+ {
+ if ((printerfile = strrchr(printer->device_uri, ':')) == NULL)
+ {
+ LogMessage(L_ERROR, "StartJob: Unable to determine printer device file");
+ CancelJob(current->id, 0);
+ return;
+ }
+ }
+
+ printerfile++;
+ if (strncmp(printerfile, "/dev/", 5) == 0)
+ {
+ HoldSignals();
+
+ if (setexeccon(current->scon) != 0)
+ {
+ LogMessage(L_ERROR, "StartJob: Unable to setexeccon to %s", current->scon);
+ CancelJob(current->id, 0);
+ return;
+ }
+
+ LogMessage(L_DEBUG, "StartJob: Attempting to check access on printer device %s",
+ printerfile);
+
+ if ((acpid = fork()) == 0)
+ {
+ /*
+ * Child..
+ * Unblock signals before doing the exec...
+ */
+
+#ifdef HAVE_SIGSET
+ sigset(SIGTERM, SIG_DFL);
+ sigset(SIGCHLD, SIG_DFL);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = SIG_DFL;
+
+ sigaction(SIGTERM, &action, NULL);
+ sigaction(SIGCHLD, &action, NULL);
+#else
+ signal(SIGTERM, SIG_DFL);
+ signal(SIGCHLD, SIG_DFL);
+#endif /* HAVE_SIGSET */
+
+ ReleaseSignals();
+
+ /*
+ * setexeccon has been issued with the job's context so exec the access check
+ */
+ execl(CUPS_SERVERBIN "/daemon/access", "access", printerfile, NULL);
+ }
+ if (acpid < 0)
+ {
+ /*
+ * The fork() failed, something is probably wrong, so log it to cups and
+ * leave this job in the queue for now
+ */
+ LogMessage(L_ERROR, "StartJob: Unable to fork access check - %s",
+ strerror(errno));
+
+ return;
+ }
+ else
+ {
+ waitpid(acpid, &status, 0);
+ if (WIFEXITED(status))
+ {
+ if (WEXITSTATUS(status) != 0)
+ {
+ /*
+ * The access check failed, so cancel the job and send an audit message
+ */
+ audit_message = NULL;
+ SetStringf(&audit_message, "job=%d cancelled, auid=%u acct=%s unable to access printer=%s",
+ id, current->auid, current->username, printer->name);
+ audit_log_user_message(AuditLog, AUDIT_USER_LABELED_EXPORT, audit_message,
+ ServerName, NULL, NULL, 0);
+ free(audit_message);
+
+ CancelJob(current->id, 0);
+
+ return;
+ }
+ else
+ {
+ LogMessage(L_DEBUG, "StartJob: access check succeeded (returned %d)",
+ WEXITSTATUS(status));
+ }
+ }
+ }
+ ReleaseSignals();
+ }
+#endif /* WITH_LSPP */
+
+ /*
* Building the options string is harder than it needs to be, but
* for the moment we need to pass strings for command-line args and
* not IPP attribute pointers... :)
@@ -1786,6 +1921,36 @@
envp[envc ++] = dbus_address;
}
+#ifdef WITH_LSPP
+ if (!banner_page)
+ {
+ if (strcmp(current->scon, "UNKNOWN SL") == 0)
+ {
+ audit_message = NULL;
+ SetStringf(&audit_message, "job=%d auid=%u acct=%s printer=%s",
+ id, current->auid, current->username, printer->name);
+ audit_log_user_message(AuditLog, AUDIT_USER_UNLABELED_EXPORT, audit_message,
+ ServerName, NULL, NULL, 1);
+ free(audit_message);
+ }
+ else
+ {
+ job_context = context_new(current->scon);
+ mls_label = context_range_get(job_context);
+
+ snprintf(classification, sizeof(classification), "CLASSIFICATION=%s",
+ mls_label);
+ envp[envc ++] = classification;
+ audit_message = NULL;
+ SetStringf(&audit_message, "job=%d auid=%u acct=%s printer=%s obj=%s",
+ id, current->auid, current->username, printer->name, mls_label);
+ audit_log_user_message(AuditLog, AUDIT_USER_LABELED_EXPORT, audit_message,
+ ServerName, NULL, NULL, 1);
+ context_free(job_context);
+ free(audit_message);
+ }
+ }
+#else
if (Classification && !banner_page)
{
if ((attr = ippFindAttribute(current->attrs, "job-sheets",
@@ -1802,6 +1967,7 @@
envp[envc ++] = classification;
}
+#endif /* WITH_LSPP */
if (current->dtype & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
{
Index: cups-1.1.23/scheduler/main.c
===================================================================
--- cups-1.1.23/scheduler/main.c (revision 3)
+++ cups-1.1.23/scheduler/main.c (working copy)
@@ -41,6 +41,8 @@
* usage() - Show scheduler usage.
*/
+/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */
+
/*
* Include necessary headers...
*/
@@ -57,6 +59,9 @@
# include <malloc.h>
#endif /* HAVE_MALLOC_H && HAVE_MALLINFO */
+#ifdef WITH_LSPP
+# include <libaudit.h>
+#endif /* WITH_LSPP */
/*
* Local functions...
@@ -340,6 +345,17 @@
if (!ConfigurationFile)
SetString(&ConfigurationFile, CUPS_SERVERROOT "/cupsd.conf");
+#ifdef WITH_LSPP
+ if ((AuditLog = audit_open()) < 0 )
+ {
+ if (is_lspp_config())
+ {
+ fprintf(stderr, "cupsd: unable to start auditing");
+ return -1;
+ }
+ }
+#endif /* WITH_LSPP */
+
/*
* If the user hasn't specified "-f", run in the background...
*/
@@ -972,6 +988,10 @@
free(input);
free(output);
+#ifdef WITH_LSPP
+ audit_close(AuditLog);
+#endif /* WITH_LSPP */
+
return (!stop_scheduler);
}
Index: cups-1.1.23/scheduler/client.c
===================================================================
--- cups-1.1.23/scheduler/client.c (revision 3)
+++ cups-1.1.23/scheduler/client.c (working copy)
@@ -43,15 +43,24 @@
* pipe_command() - Pipe the output of a command to the remote client.
* CDSAReadFunc() - Read function for CDSA decryption code.
* CDSAWriteFunc() - Write function for CDSA encryption code.
+ * get_client_auid() - Get the audit login uid of the client.
*/
+/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */
+/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */
+
/*
* Include necessary headers...
*/
+#define _GNU_SOURCE
#include <cups/http-private.h>
#include "cupsd.h"
#include <grp.h>
+#ifdef WITH_LSPP
+#include <selinux/selinux.h>
+#include <fcntl.h>
+#endif /* WITH_LSPP */
/*
@@ -74,6 +83,9 @@
static OSStatus CDSAWriteFunc(SSLConnectionRef connection,
const void *data, size_t *dataLength);
#endif /* HAVE_CDSASSL */
+#ifdef WITH_LSPP
+uid_t get_client_auid(pid_t clipid);
+#endif /* WITH_LSPP */
/*
@@ -275,6 +287,40 @@
LogMessage(L_DEBUG, "AcceptClient: %d from %s:%d.", con->http.fd,
con->http.hostname, ntohs(con->http.hostaddr.sin_port));
+#ifdef WITH_LSPP
+ {
+ struct ucred cr;
+ unsigned int cl=sizeof(cr);
+
+ if (getsockopt(con->http.fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl)==0) {
+ /*
+ * get_client_auid() can be racey
+ * In this case the pid is based on a socket connected to the client
+ */
+ con->auid = get_client_auid(cr.pid);
+ LogMessage(L_INFO, "AcceptClient: peer's pid=%d, uid=%d, gid=%d, auid=%d",
+ cr.pid, cr.uid, cr.gid, con->auid);
+ } else {
+ close(con->http.fd);
+ LogMessage(L_ERROR, "AcceptClient: getsockopt() failed");
+ return;
+ }
+
+ /*
+ * get the context of the peer connection
+ */
+ if (getpeercon(con->http.fd, &con->scon))
+ {
+ LogMessage(L_ERROR, "AcceptClient: getpeercon() failed");
+ SetString(&con->scon, "UNKNOWN SL");
+ }
+
+ LogMessage(L_INFO, "AcceptClient: client context=%s", con->scon);
+
+ }
+#endif /* WITH_LSPP */
+
+
/*
* Using TCP_NODELAY improves responsiveness, especially on systems
* with a slow loopback interface... Since we write large buffers
@@ -3494,7 +3540,49 @@
}
#endif /* HAVE_CDSASSL */
+#ifdef WITH_LSPP
+/*
+ * 'get_client_auid()' - Using the client's pid, read /proc and determine the loginuid.
+ */
+uid_t get_client_auid(pid_t clipid)
+{
+ uid_t uid;
+ int len, in;
+ char buf[16] = {0};
+ char fname[32] = {0};
+
+
+ /*
+ * There is a race here wrt the client's pid
+ */
+ snprintf(fname, 32, "/proc/%d/loginuid", clipid);
+ in = open(fname, O_NOFOLLOW|O_RDONLY);
+
+ if (in < 0)
+ return -1;
+
+ errno = 0;
+
+ do {
+ len = read(in, buf, sizeof(buf));
+ } while (len < 0 && errno == EINTR);
+
+ close(in);
+
+ if (len < 0 || len >= sizeof(buf))
+ return -1;
+
+ buf[len] = 0;
+ uid = strtol(buf, 0, 10);
+
+ if (errno != 0)
+ return -1;
+ else
+ return uid;
+}
+#endif /* WITH_LSPP */
+
/*
* End of "$Id: client.c,v 1.197 2005/01/03 19:29:59 mike Exp $".
*/
Index: cups-1.1.23/scheduler/client.h
===================================================================
--- cups-1.1.23/scheduler/client.h (revision 3)
+++ cups-1.1.23/scheduler/client.h (working copy)
@@ -22,6 +22,13 @@
* WWW: http://www.cups.org
*/
+/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */
+/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */
+
+#ifdef WITH_LSPP
+#include <selinux/selinux.h>
+#endif /* WITH_LSPP */
+
/*
* HTTP client structure...
*/
@@ -46,6 +53,10 @@
int got_fields, /* Non-zero if all fields seen */
field_col; /* Column within line */
cups_lang_t *language; /* Language to use */
+#ifdef WITH_LSPP
+ security_context_t scon; /* Security context of connection */
+ uid_t auid; /* Audit loginuid of the client */
+#endif /* WITH_LSPP */
} client_t;
#define HTTP(con) &((con)->http)
Index: cups-1.1.23/scheduler/conf.c
===================================================================
--- cups-1.1.23/scheduler/conf.c (revision 3)
+++ cups-1.1.23/scheduler/conf.c (working copy)
@@ -29,6 +29,7 @@
* get_address() - Get an address + port number from a line.
* CDSAGetServerCerts() - Convert a keychain name into the CFArrayRef
* required by SSLSetCertificate.
+ * is_lspp_config() - Is the system configured for LSPP
*/
/*
@@ -59,6 +60,9 @@
# define INADDR_NONE 0xffffffff
#endif /* !INADDR_NONE */
+#ifdef WITH_LSPP
+# include <libaudit.h>
+#endif /* WITH_LSPP */
/*
* Configuration variable structure...
@@ -139,6 +143,9 @@
{ "ServerKey", &ServerKey, VAR_STRING },
# endif /* HAVE_LIBSSL || HAVE_GNUTLS */
#endif /* HAVE_SSL */
+#ifdef WITH_LSPP
+ { "AuditLog", &AuditLog, VAR_INTEGER },
+#endif /* WITH_LSPP */
{ "ServerName", &ServerName, VAR_STRING },
{ "ServerRoot", &ServerRoot, VAR_STRING },
{ "TempDir", &TempDir, VAR_STRING },
@@ -183,6 +190,9 @@
sigset_t oldset, newset;
sigset_t *oldset_p = &oldset, *newset_p = &newset;
int sigerr, errmask = 0;
+#ifdef WITH_LSPP
+ char *audit_message; /* Audit message string */
+#endif /* WITH_LSPP */
sigerr = sigemptyset(newset_p);
if (!sigerr)
@@ -403,6 +413,16 @@
else
RunUser = getuid();
+#ifdef WITH_LSPP
+ /*
+ * ClassifyOverride is set during read_configuration, if its on, report it now
+ */
+ if (ClassifyOverride)
+ audit_log_user_message(AuditLog, AUDIT_USYS_CONFIG,
+ "[Config] ClassifyOverride=enabled Users can override print banners",
+ ServerName, NULL, NULL, 1);
+#endif /* WITH_LSPP */
+
/*
* Use the default system group if none was supplied in cupsd.conf...
*/
@@ -577,7 +597,16 @@
ClearString(&Classification);
if (Classification)
+ {
LogMessage(L_INFO, "Security set to \"%s\"", Classification);
+#ifdef WITH_LSPP
+ audit_message = NULL;
+ SetStringf(&audit_message, "[Config] Security level=%s", Classification);
+ audit_log_user_message(AuditLog, AUDIT_LABEL_LEVEL_CHANGE, audit_message,
+ ServerName, NULL, NULL, 1);
+ free(audit_message);
+#endif /* WITH_LSPP */
+ }
/*
* Update the MaxClientsPerHost value, as needed...
@@ -2259,6 +2288,17 @@
}
#endif /* HAVE_CDSASSL */
+#if WITH_LSPP
+int is_lspp_config()
+{
+ if (Classification != NULL)
+ return ((strcmp(Classification, MLS_CONFIG) == 0)
+ || (strcmp(Classification, TE_CONFIG) == 0)
+ || (strcmp(Classification, SELINUX_CONFIG) == 0));
+ else
+ return 0;
+}
+#endif /* WITH_LSPP */
/*
* End of "$Id: conf.c,v 1.152 2005/01/03 19:29:59 mike Exp $".
Index: cups-1.1.23/scheduler/conf.h
===================================================================
--- cups-1.1.23/scheduler/conf.h (revision 3)
+++ cups-1.1.23/scheduler/conf.h (working copy)
@@ -179,6 +179,10 @@
/* Array containing certificates */
# endif /* HAVE_LIBSSL || HAVE_GNUTLS */
#endif /* HAVE_SSL */
+#ifdef WITH_LSPP
+VAR int AuditLog VALUE(-1);
+ /* File descriptor for audit */
+#endif /* WITH_LSPP */
/*
@@ -194,6 +198,9 @@
#endif /* __GNUC__ */
;
extern int LogPage(job_t *job, const char *page);
+#ifdef WITH_LSPP
+extern int is_lspp_config(void);
+#endif /* WITH_LSPP */
/*
Index: cups-1.1.23/scheduler/printers.c
===================================================================
--- cups-1.1.23/scheduler/printers.c (revision 3)
+++ cups-1.1.23/scheduler/printers.c (working copy)
@@ -50,6 +50,8 @@
* desktop tools.
*/
+/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */
+
/*
* Include necessary headers...
*/
@@ -66,6 +68,9 @@
static void write_irix_state(printer_t *p);
#endif /* __sgi */
+#ifdef WITH_LSPP
+# include <libaudit.h>
+#endif /* WITH_LSPP */
/*
* 'AddPrinter()' - Add a printer to the system.
@@ -1190,6 +1195,9 @@
"two-long-edge",
"two-short-edge"
};
+#ifdef WITH_LSPP
+ char *audit_message; /* Audit message string */
+#endif /* WITH_LSPP */
DEBUG_printf(("SetPrinterAttrs: entering name = %s, type = %x\n", p->name,
@@ -1229,6 +1237,14 @@
else if (auth->type == AUTH_DIGEST)
auth_supported = "digest";
}
+#ifdef WITH_LSPP
+ audit_message = NULL;
+ SetStringf(&audit_message, "[Config] printer=%s uri=%s banners set to %s %s",
+ p->name, p->device_uri, p->job_sheets[0], p->job_sheets[1]);
+ audit_log_user_message(AuditLog, AUDIT_LABEL_LEVEL_CHANGE, audit_message,
+ ServerName, NULL, NULL, 1);
+ free(audit_message);
+#endif /* WITH_LSPP */
}
/*
Index: cups-1.1.23/scheduler/job.h
===================================================================
--- cups-1.1.23/scheduler/job.h (revision 3)
+++ cups-1.1.23/scheduler/job.h (working copy)
@@ -22,6 +22,13 @@
* WWW: http://www.cups.org
*/
+/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */
+/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */
+
+#ifdef WITH_LSPP
+#include <selinux/selinux.h>
+#endif /* WITH_LSPP */
+
/*
* Constants...
*/
@@ -58,6 +65,10 @@
char *buffer; /* Status buffer */
int bufused; /* Amount of buffer in use */
int tries; /* Number of tries for this job */
+#ifdef WITH_LSPP
+ security_context_t scon; /* Security context of job */
+ uid_t auid; /* Audit loginuid for this job */
+#endif /* WITH_LSPP */
} job_t;
Index: cups-1.1.23/Makedefs.in
===================================================================
--- cups-1.1.23/Makedefs.in (revision 3)
+++ cups-1.1.23/Makedefs.in (working copy)
@@ -95,7 +95,7 @@
LDFLAGS = -L../cups -L../filter $(RC_CFLAGS) @LDFLAGS@ $(OPTIM)
LINKCUPS = @LINKCUPS@
LINKCUPSIMAGE = @LINKCUPSIMAGE@
-LIBS = $(LINKCUPS) $(NETLIBS) @LIBS@ $(COMMONLIBS)
+LIBS = $(LINKCUPS) $(NETLIBS) @LIBS@ $(COMMONLIBS) @LIBAUDIT@ @LIBSELINUX@
NETLIBS = @NETLIBS@
OPTIM = @OPTIM@
OPTIONS =
Index: cups-1.1.23/cups.list.in
===================================================================
--- cups-1.1.23/cups.list.in (revision 3)
+++ cups-1.1.23/cups.list.in (working copy)
@@ -242,6 +242,7 @@
f 0444 root sys $DATADIR/banners/standard data/standard
f 0444 root sys $DATADIR/banners/topsecret data/topsecret
f 0444 root sys $DATADIR/banners/unclassified data/unclassified
+f 0444 root sys $DATADIR/banners/mls_template data/mls_template
d 0555 root sys $DATADIR/charsets -
f 0444 root sys $DATADIR/charsets/windows-874 data/windows-874
Index: cups-1.1.23/config-scripts/cups-lspp.m4
===================================================================
--- cups-1.1.23/config-scripts/cups-lspp.m4 (revision 0)
+++ cups-1.1.23/config-scripts/cups-lspp.m4 (revision 4)
@@ -0,0 +1,36 @@
+dnl
+dnl LSPP code for the Common UNIX Printing System (CUPS).
+dnl
+dnl Copyright 2005-2006 by Hewlett-Packard Development Company, L.P.
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; version 2.
+dnl
+dnl This program is distributed in the hope that it will be useful, but
+dnl WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+dnl General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software Foundation,
+dnl Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301 USA
+dnl
+
+dnl Are we trying to meet LSPP requirements
+AC_ARG_ENABLE(audit, [ --enable-lspp turn on auditing and label support, default=no])
+
+if test x"$enable_lspp" != xno; then
+ case "$uname" in
+ Linux)
+ AC_CHECK_LIB(audit,audit_log_user_message, [LIBAUDIT="-laudit" AC_SUBST(LIBAUDIT)])
+ AC_CHECK_HEADER(libaudit.h)
+ AC_CHECK_LIB(selinux,getpeercon, [LIBSELINUX="-lselinux" AC_SUBST(LIBSELINUX)])
+ AC_CHECK_HEADER(selinux/selinux.h)
+ AC_DEFINE(WITH_LSPP)
+ ;;
+ *)
+ # All others
+ ;;
+ esac
+fi
Index: cups-1.1.23/data/mls_template
===================================================================
--- cups-1.1.23/data/mls_template (revision 0)
+++ cups-1.1.23/data/mls_template (revision 4)
@@ -0,0 +1,277 @@
+%!PS-Adobe-3.0
+%%BoundingBox: 0 0 612 792
+%%Pages: 1
+%%LanguageLevel: 1
+%%DocumentData: Clean7Bit
+%%DocumentSuppliedResources: procset bannerprint/1.0
+%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman
+%%Creator: Michael Sweet, Easy Software Products
+%%CreationDate: May 10, 2000
+%%Title: Test Page
+%%EndComments
+%%BeginProlog
+%%BeginResource procset bannerprint 1.1 0
+%
+% PostScript banner page for the Common UNIX Printing System ("CUPS").
+%
+% Copyright 1993-2005 by Easy Software Products
+%
+% These coded instructions, statements, and computer programs are the
+% property of Easy Software Products and are protected by Federal
+% copyright law. Distribution and use rights are outlined in the file
+% "LICENSE.txt" which should have been included with this file. If this
+% file is missing or damaged please contact Easy Software Products
+% at:
+%
+% Attn: CUPS Licensing Information
+% Easy Software Products
+% 44141 Airport View Drive, Suite 204
+% Hollywood, Maryland 20636 USA
+%
+% Voice: (301) 373-9600
+% EMail: [EMAIL PROTECTED]
+% WWW: http://www.cups.org
+%
+/CENTER { % Draw centered text
+ % (name) CENTER -
+ dup stringwidth pop % Get the width of the string
+ 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance
+ show % Show the string
+} bind def
+/RIGHT { % Draw right-justified text
+ % (name) RIGHT -
+ dup stringwidth pop % Get the width of the string
+ neg 0 rmoveto % Shift left the entire distance
+ show % Show the string
+} bind def
+/NUMBER { % Draw a number
+ % power n NUMBER -
+ 1 index 1 eq { % power == 1?
+ round cvi exch pop % Convert "n" to integer
+ } {
+ 1 index mul round exch div % Truncate extra decimal places
+ } ifelse
+ 100 string cvs show % Convert to a string and show it...
+} bind def
+/CUPSLOGO { % Draw the CUPS logo
+ % height CUPSLOGO
+ % Start with a big C...
+ /Helvetica findfont 1 index scalefont setfont
+ 0 setgray
+ 0 0 moveto
+ (C) show
+
+ % Then "UNIX Printing System" much smaller...
+ /Helvetica-Bold findfont 1 index 9 div scalefont setfont
+ 0.25 mul
+ dup dup 2.0 mul moveto
+ (UNIX) show
+ dup dup 1.6 mul moveto
+ (Printing) show
+ dup 1.2 mul moveto
+ (System) show
+} bind def
+/ESPLOGO { % Draw the ESP logo
+ % height ESPLOGO
+ % Compute the size of the logo...
+ 0 0
+ 2 index 1.5 mul 3 index
+
+ % Do the "metallic" fill from 10% black to 40% black...
+ 1 -0.001 0 {
+ dup % loopval
+ -0.15 mul % loopval * -0.15
+ 0.9 add % 0.9 - loopval * 0.15
+ setgray % set gray shade
+
+ 0 % x
+ 1 index neg % loopval
+ 1 add % 1 - loopval
+ 3 index % height
+ mul % height * (1 - loopval)
+ moveto % starting point
+
+ dup % loopval
+ 3 index % width
+ mul % loopval * width
+ 2 index % height
+ lineto % Next point
+
+ 0 % x
+ 2 index % height
+ lineto % Next point
+
+ closepath
+ fill
+
+ dup % loopval
+ 0.15 mul % loopval * 0.15
+ 0.6 add % 0.6 + loopval * 0.15
+ setgray
+
+ dup % loopval
+ neg 1 add % 1 - loopval
+ 3 index % width
+ mul % (1 - loopval) * width
+ 0 % y
+ moveto % Starting point
+
+ 2 index % width
+ exch % loopval
+ 2 index % height
+ mul % loopval * height
+ lineto % Next point
+
+ 1 index % width
+ 0 % y
+ lineto % Next point
+
+ closepath
+ fill
+ } for
+
+ 0 setgray rectstroke
+
+ /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont
+ dup 40 div
+
+ dup 4 mul 1 index 25 mul moveto (E) show
+ dup 10 mul 1 index 15 mul moveto (S) show
+ dup 16 mul 1 index 5 mul moveto (P) show
+
+ /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont
+ dup 14 mul 1 index 29 mul moveto (asy) show
+ dup 20 mul 1 index 19 mul moveto (oftware) show
+ dup 26 mul 1 index 9 mul moveto (roducts) show
+
+ pop
+} bind def
+%%EndResource
+%%EndProlog
+%%Page: 1 1
+gsave
+
+ % Determine the imageable area and device resolution...
+ initclip newpath clippath pathbbox % Get bounding rectangle
+ 72 div /pageTop exch def % Get top margin in inches
+ 72 div /pageRight exch def % Get right margin in inches
+ 72 div /pageBottom exch def % Get bottom margin in inches
+ 72 div /pageLeft exch def % Get left margin in inches
+
+ /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft
+ /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom
+
+ /boxWidth % width of text box
+ pageWidth pageHeight lt
+ { pageWidth 54 mul }
+ { pageHeight 42 mul }
+ ifelse def
+
+ newpath % Clear bounding path
+
+ % Create fonts...
+ /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold
+ pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33)
+
+ /mediumFont /Helvetica findfont % mediumFont = Helvetica
+ pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5)
+
+ % Offset page to account for lower-left margin...
+ pageLeft 72 mul
+ pageBottom 72 mul
+ translate
+
+ % Draw the label at the top and bottom...
+ 0 setgray % Color
+
+ pageWidth 36 mul % Center of page
+ pageHeight 72 mul % Top of page
+ pageWidth -7 mul add % - 2 lines
+ moveto % Position text
+ bigFont setfont % Font
+ ({mls-label}) CENTER % Show text centered
+
+ pageWidth 36 mul % Center of page
+ pageHeight 6 mul % Bottom of page
+ moveto % Position text
+ bigFont setfont % Font
+ ({mls-label}) CENTER % Show text centered
+
+ % Job information box...
+ pageWidth 36 mul 9 add % x = pageWidth * 1/2 * 72 + 9
+ boxWidth 0.5 mul sub % x-= 1/2 box width
+ pageHeight 30 mul 9 sub % y = pageHeight * 1/2 * 72 - 9
+ boxWidth % w = box width
+ pageHeight 14 mul % h = pageHeight * 1/2 * 72
+ 0.5 setgray rectfill % Draw a shadow
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ boxWidth 0.5 mul sub % x-= 1/2 box width
+ pageHeight 30 mul % y = pageHeight * 1/4 * 72
+ boxWidth % w = box width
+ pageHeight 14 mul % h = pageHeight * 1/2 * 72
+
+ 4 copy 1 setgray rectfill % Clear the box to white
+ 0 setgray rectstroke % Draw a black box around it...
+
+ % Job information text...
+ mediumFont setfont % Medium sized font
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight 5 mul add % y += 2 lines
+ 2 copy % Copy X & Y
+ moveto
+ (Job ID: ) RIGHT
+ moveto
+ ({printer-name}-{job-id}) show
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight 2 mul add % y += 1 line
+ 2 copy % Copy X & Y
+ moveto
+ (Title: ) RIGHT
+ moveto
+ ({job-name}) show
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight -1 mul add % y -= 1 line
+ 2 copy % Copy X & Y
+ moveto
+ (Requesting User: ) RIGHT
+ moveto
+ ({job-originating-user-name}) show
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight -4 mul add % y -= 2 lines
+ 2 copy % Copy X & Y
+ moveto
+ (Billing Info: ) RIGHT
+ moveto
+ ({?job-billing}) show
+
+ % Then the CUPS logo....
+ gsave
+ pageWidth 4 mul
+ pageWidth 6 mul
+ translate
+ pageWidth 9 mul CUPSLOGO
+ grestore
+
+ % And the ESP logo....
+ gsave
+ pageWidth 59 mul
+ pageWidth 6 mul
+ translate
+ pageWidth 6 mul ESPLOGO
+ grestore
+% Show the page...
+grestore
+showpage
+%
+% End of "$Id: mls_template,v 1.1 2005/06/27 18:44:46 colmo Exp $".
+%
+%%EOF
Index: cups-1.1.23/data/Makefile
===================================================================
--- cups-1.1.23/data/Makefile (revision 3)
+++ cups-1.1.23/data/Makefile (working copy)
@@ -33,7 +33,8 @@
secret \
standard \
topsecret \
- unclassified
+ unclassified \
+ mls_template
CHARSETS = iso-8859-1 \
iso-8859-2 \
Index: cups-1.1.23/cups/http-addrlist.c
===================================================================
Index: cups-1.1.23/cups/ipp.c
===================================================================
--- cups-1.1.23/cups/ipp.c (revision 3)
+++ cups-1.1.23/cups/ipp.c (working copy)
@@ -64,6 +64,8 @@
* ipp_write_file() - Write IPP data to a file.
*/
+/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */
+
/*
* Include necessary headers...
*/
@@ -81,7 +83,11 @@
# include <io.h>
#endif // WIN32
+#ifdef WITH_LSPP
+#include <selinux/selinux.h>
+#endif /* WITH_LSPP */
+
/*
* Local functions...
*/
@@ -705,6 +711,41 @@
ippDeleteAttribute(ipp_t *ipp, /* I - IPP request */
ipp_attribute_t *attr) /* I - Attribute to delete */
{
+#ifdef WITH_LSPP
+ ipp_attribute_t *current; /* Current attribute */
+ ipp_attribute_t *prev; /* previous attribute */
+ ipp_tag_t value_tag; /* Value tag */
+ ipp_tag_t attr_value_tag; /* Value tag */
+
+ if (ipp == NULL || ipp->attrs == NULL || attr == NULL)
+ return;
+
+ current = prev = ipp->attrs;
+
+ attr_value_tag = (ipp_tag_t)(attr->value_tag & IPP_TAG_MASK);
+
+ while (current != NULL)
+ {
+ DEBUG_printf(("ippDeleteAttribute: current = %p, current = \'%s\'\n",
+ current, current->name));
+
+ value_tag = (ipp_tag_t)(current->value_tag & IPP_TAG_MASK);
+
+ if (current->name != NULL && strcasecmp(current->name, attr->name) == 0 &&
+ (value_tag == attr_value_tag))
+ {
+ prev->next = current->next;
+ ipp->current = NULL;
+ _ipp_free_attr(attr);
+
+ return;
+ }
+ prev = current;
+ current = current->next;
+ }
+
+ return;
+#endif /* WITH_LSPP */
}
Index: cups-1.1.23/cups/cups.h
===================================================================
--- cups-1.1.23/cups/cups.h (revision 3)
+++ cups-1.1.23/cups/cups.h (working copy)
@@ -24,6 +24,8 @@
* This file is subject to the Apple OS-Developed Software exception.
*/
+/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */
+
#ifndef _CUPS_CUPS_H_
# define _CUPS_CUPS_H_
@@ -55,6 +57,12 @@
# define CUPS_DATE_ANY -1
+# ifdef WITH_LSPP
+# define MLS_TEMPLATE "mls_template"
+# define MLS_CONFIG "mls"
+# define TE_CONFIG "te"
+# define SELINUX_CONFIG "SELinux"
+# endif /* WITH_LSPP */
/*
* Types and structures...
*/
Index: cups-1.1.23/configure.in
===================================================================
--- cups-1.1.23/configure.in (revision 3)
+++ cups-1.1.23/configure.in (working copy)
@@ -41,6 +41,8 @@
sinclude(config-scripts/cups-scripting.m4)
+sinclude(config-scripts/cups-lspp.m4)
+
AC_OUTPUT(Makedefs cups.list cups.sh cups-config conf/cupsd.conf conf/pam.std)
chmod +x cups-config
Index: cups-1.1.23/config.h.in
===================================================================
--- cups-1.1.23/config.h.in (revision 3)
+++ cups-1.1.23/config.h.in (working copy)
@@ -298,6 +298,12 @@
#define CUPS_PYTHON "/usr/bin/python"
+/*
+ * Are we trying to meet LSPP requirements?
+ */
+
+#undef WITH_LSPP
+
#endif /* !_CUPS_CONFIG_H_ */
/*
--
redhat-lspp mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/redhat-lspp