components/cups/patches/12-base-tx.patch
author sonam gupta - Sun Microsystems - Bangalore India <Sonam.Gupta@Sun.COM>
Fri, 19 Aug 2011 10:20:58 +0530
changeset 481 9ca5b97b5b08
parent 220 3ff562b51ff5
permissions -rw-r--r--
PSARC/2011/084 LP print service EOF 7079107 CUPS changes for LP EOF 7079183 Rename a2ps package because of LP EOF 7079201 man(1) is unable to find CUPS man pages.

Index: Makedefs.in
===================================================================
--- Makedefs.in (revision 8801)
+++ Makedefs.in	(working copy)
@@ -124,7 +124,7 @@
 BACKLIBS	=	@BACKLIBS@
 BANNERTOPS	=	@BANNERTOPS@
 CFLAGS		=	@CPPFLAGS@ @CFLAGS@
 COMMONLIBS	=	@LIBS@
-CUPSDLIBS	=	@CUPSDLIBS@
+CUPSDLIBS	=	@CUPSDLIBS@ @LABELING_LIBS@
 CXXFLAGS	=	@CPPFLAGS@ @CXXFLAGS@
 CXXLIBS		=	@CXXLIBS@
 DBUS_NOTIFIER	=	@DBUS_NOTIFIER@
Index: config-scripts/cups-labeling.m4
===================================================================
--- config-scripts/cups-labeling.m4	(revision 0)
+++ config-scripts/cups-labeling.m4	(revision 0)
@@ -0,0 +1,38 @@
+dnl
+dnl    Security Labeled environment support for the Common UNIX Printing System (CUPS).
+dnl
+dnl    Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+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
+
+AC_ARG_ENABLE(labeling, [   --enable-labeling      enable support for labeled environments like Solaris Trusted Extensions and SELinux, default=auto])
+
+if test x"$enable_labeling" != xno; then
+    case "$uname" in
+        SunOS)
+            AC_CHECK_LIB(tsol, str_to_label, [LABELING_LIBS="-zlazyload -lbsm -ltsol -znolazyload" AC_SUBST(LABELING_LIBS)
+                         AC_CHECK_HEADER(tsol/label.h)
+                         AC_DEFINE(HAVE_TSOL)])
+            ;;
+        Linux)
+            AC_CHECK_LIB(selinux, getpeercon, [LABELING_LIBS="-lselinux" AC_SUBST(LABELING_LIBS)
+                         AC_CHECK_HEADER(selinux/selinux.h)
+                         AC_DEFINE(HAVE_SELINUX)])
+            ;;
+        *)
+            # All others
+            ;;
+    esac
+fi
Index: data/Makefile
===================================================================
--- data/Makefile	(revision 8857)
+++ data/Makefile	(working copy)
@@ -22,6 +22,7 @@
 BANNERS	=	\
 		classified \
 		confidential \
+		labeled \
 		secret \
 		standard \
 		topsecret \
Index: data/labeled
===================================================================
--- data/labeled	(revision 0)
+++ data/labeled	(revision 0)
@@ -0,0 +1,4 @@
+#CUPS-BANNER
+Show job-id job-name job-originating-user-name job-originating-host-name job-billing
+Image images/cups.png
+
Index: configure.in
===================================================================
--- configure.in	(revision 8857)
+++ configure.in	(working copy)
@@ -41,6 +41,7 @@
 sinclude(config-scripts/cups-pap.m4)
 sinclude(config-scripts/cups-pdf.m4)
 sinclude(config-scripts/cups-scripting.m4)
+sinclude(config-scripts/cups-labeling.m4)
 
 INSTALL_LANGUAGES=""
 UNINSTALL_LANGUAGES=""
Index: config.h.in
===================================================================
--- config.h.in.orig	Thu Aug 12 21:11:46 2010
+++ config.h.in	Tue Aug 16 18:03:17 2011
@@ -665,7 +665,17 @@
 #undef HAVE_SYS_STATVFS_H
 #undef HAVE_SYS_VFS_H
 
+/*
+ * Do we have Solaris Trusted Extensions support?
+ */
 
+#undef HAVE_TSOL
+
+/*
+ * Do we have SELinux support?
+ */
+#undef HAVE_SELINUX
+
 #endif /* !_CUPS_CONFIG_H_ */
 
 /*
Index: scheduler/ipp.c
===================================================================
--- scheduler/ipp.c.orig	Thu Oct  7 01:37:44 2010
+++ scheduler/ipp.c	Tue Aug 16 18:03:17 2011
@@ -856,7 +856,52 @@
   return (0);
 }
 
+static int
+compare_labels(char *label1, char *label2)
+{
+  int result = 0;
 
+  if ((label1 != NULL) && (label2 != NULL))
+  {
+#if defined(HAVE_TSOL)
+    if (is_system_labeled())
+    {
+      result = (strcmp(label1, label2) != 0);
+
+      cupsdLogMessage(CUPSD_LOG_DEBUG2, "compare_labels(%s, %s): %d",
+                      label1, label2, result);
+    }
+#elif defined(HAVE_SELINUX)
+#endif /* HAVE_TSOL || HAVE_SELINUX */
+  }
+
+  return(result);
+}
+
+static char *
+label_to_page_top_bottom_string(char *label)
+{
+  char *result = label;
+
+#if defined(HAVE_TSOL)
+  if (is_system_labeled())
+  {
+    m_label_t *sl = NULL;
+
+    if (str_to_label(label, &sl, USER_CLEAR, L_NO_CORRECTION, NULL) == 0)
+    {
+      (void) label_to_str(sl, &result, PRINTER_TOP_BOTTOM, DEF_NAMES);
+      if (result == NULL)
+        result = label;
+
+      m_label_free(sl);
+    }
+  }
+#endif
+
+  return (result);
+}
+
 /*
  * 'accept_jobs()' - Accept print jobs to a printer.
  */
@@ -1361,6 +1406,17 @@
 		  filetype, filetype ? filetype->super : "none",
 		  filetype ? filetype->type : "none");
 
+  /*
+   * Validate that the label associated with the connection is acceptable for
+   * printing on the printer.
+   */
+  if (cupsdInPrinterLabelRange(con->slabel, printer) == 0)
+  {
+    send_ipp_status(con, IPP_NOT_AUTHORIZED, _("label violation."));
+    return (NULL);
+  }
+  
+
  /*
   * Check remote printing to non-shared printer...
   */
@@ -1620,6 +1676,19 @@
     return (NULL);
   }
 
+  /*
+   *  Add the label to the job...
+   */
+  if (con->slabel)
+  {
+    job->slabel = strdup(con->slabel);
+    ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_NAME, "security-label",
+		 NULL, job->slabel);
+    /* used by filters to add header/footer labels to output */
+    ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_NAME, "page-label",
+		 NULL, label_to_page_top_bottom_string(job->slabel));
+  }
+
   job->dtype   = printer->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT |
                                   CUPS_PRINTER_REMOTE);
   job->attrs   = con->request;
@@ -3761,6 +3830,15 @@
     return;
   }
 
+  if (compare_labels(con->slabel, job->slabel) != 0)
+  {
+   /*
+    * If the labels don't match, we can't tell them about it.
+    */
+    send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist!"), jobid);
+    return;
+  }
+
  /*
   * See if the job has been completed...
   */
@@ -4129,6 +4207,16 @@
     return;
   }
 
+  if (compare_labels(con->slabel, job->slabel) != 0)
+  {
+   /*
+    * If the labels don't match, we can't tell them about it.
+    */
+    send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist!"), jobid);
+    return;
+  }
+
+
  /*
   * See if the job is owned by the requesting user...
   */
@@ -6389,6 +6477,16 @@
 	send_ipp_status(con, IPP_NOT_FOUND, _("Job %d not found!"), jobid);
 	return;
       }
+
+      if (compare_labels(con->slabel, job->slabel) != 0)
+      {
+       /*
+        * If the labels don't match, we can't tell them about it.
+        */
+        send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist!"),
+                        jobid);
+        return;
+      }
     }
     else
       job = NULL;
@@ -6936,6 +7034,15 @@
     return;
   }
 
+  if (compare_labels(con->slabel, job->slabel) != 0)
+  {
+   /*
+    * If the labels don't match, we can't tell them about it.
+    */
+    send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist!"), jobid);
+    return;
+  }
+
  /*
   * Copy attributes...
   */
@@ -7156,6 +7263,14 @@
 
     cupsdLoadJob(job);
 
+    if (compare_labels(con->slabel, job->slabel) != 0)
+    {
+     /*
+      * If the labels don't match, we can't tell them about it.
+      */
+      continue;
+    }
+
     if (!job->attrs)
     {
       cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs: No attributes for job %d!",
@@ -8212,6 +8327,15 @@
     return;
   }
 
+  if (compare_labels(con->slabel, job->slabel) != 0)
+  {
+   /*
+    * If the labels don't match, we can't tell them about it.
+    */
+    send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist!"), jobid);
+    return;
+  }
+
  /*
   * See if the job is owned by the requesting user...
   */
@@ -8466,6 +8590,14 @@
                       _("Job #%d does not exist!"), jobid);
       return;
     }
+    else if (compare_labels(con->slabel, job->slabel) != 0)
+    {
+     /*
+      * If the labels don't match, we can't tell them about it.
+      */
+      send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist!"), jobid);
+      return;
+    }
     else
     {
      /*
@@ -8488,6 +8620,27 @@
     return;
   }
 
+  /*
+   * Validate that the label associated with the connection is acceptable for
+   * printing on the printer.
+   */
+  if (cupsdInPrinterLabelRange(con->slabel, dprinter) == 0)
+  {
+    send_ipp_status(con, IPP_NOT_AUTHORIZED, _("label violation."));
+    return;
+  }
+  
+  /*
+   * Validate that the label associated with the job is acceptable for
+   * printing on the printer.
+   */
+  if (cupsdInPrinterLabelRange(job->slabel, dprinter) == 0)
+  {
+    send_ipp_status(con, IPP_NOT_AUTHORIZED, _("label violation."));
+    return;
+  }
+  
+
  /*
   * Now move the job or jobs...
   */
@@ -9318,6 +9471,16 @@
     return;
   }
 
+  if (compare_labels(con->slabel, job->slabel) != 0)
+  {
+   /*
+    * If the labels don't match, we can't tell them about it.
+    */
+    send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist!"), jobid);
+    return;
+  }
+
+
  /*
   * See if job is "held"...
   */
@@ -9544,6 +9707,15 @@
     return;
   }
 
+  if (compare_labels(con->slabel, job->slabel) != 0)
+  {
+   /*
+    * If the labels don't match, we can't tell them about it.
+    */
+    send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist!"), jobid);
+    return;
+  }
+
  /*
   * See if job is in any of the "completed" states...
   */
@@ -9899,6 +10071,15 @@
     return;
   }
 
+  if (compare_labels(con->slabel, job->slabel) != 0)
+  {
+   /*
+    * If the labels don't match, we can't tell them about it.
+    */
+    send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist!"), jobid);
+    return;
+  }
+
   printer = cupsdFindDest(job->dest);
 
  /*
@@ -10488,6 +10669,15 @@
     return;
   }
 
+  if (compare_labels(con->slabel, job->slabel) != 0)
+  {
+   /*
+    * If the labels don't match, we can't tell them about it.
+    */
+    send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist!"), jobid);
+    return;
+  }
+
  /*
   * See if the job has been completed...
   */
@@ -10825,7 +11015,6 @@
  /*
   * Return a list of attributes that can be set via Set-Printer-Attributes.
   */
-
   if ((attr = ippFindAttribute(con->request, "printer-location",
                                IPP_TAG_TEXT)) != NULL)
   {
@@ -11584,6 +11773,11 @@
 
   strlcpy(username, get_username(con), userlen);
 
+  if (compare_labels(con->slabel, job->slabel) != 0)
+  {
+    return (0);
+  }
+
  /*
   * Check the username against the owner...
   */
Index: scheduler/printers.c
===================================================================
--- scheduler/printers.c.orig	Thu Sep 23 00:05:07 2010
+++ scheduler/printers.c	Tue Aug 16 18:03:34 2011
@@ -1011,7 +1011,93 @@
   p->users     = NULL;
 }
 
+#if defined(HAVE_TSOL)
+static char *
+log_tsol_str_to_label_error(char *s, int e)
+{
+  char *mesg = strerror(errno);
 
+  if (errno == EINVAL)
+  {
+    switch (e) {
+    case M_BAD_STRING:
+      mesg = "bad string";
+      break;
+    case M_BAD_LABEL:
+      mesg = "bad label";
+      break;
+    case M_OUTSIDE_AR:
+      mesg = "outside DIA Accreditation Range";
+      break;
+    }
+  }
+
+  return (mesg);
+}
+#endif /* HAVE_TSOL */
+
+/* 
+ * 'cupsdInPrinterLabelRange()' - validate that the supplied slabel is in the
+ *                                label range of the supplied printer.
+ *     0 - failure, 1 - success
+ */
+int
+cupsdInPrinterLabelRange(char *slabel, cupsd_printer_t *p)
+{
+  /* unlabeled client objects are always in range. */
+  if (slabel == NULL)
+    return (1);
+
+  if (p == NULL) /* this should never happen */
+    return (0);
+
+#if defined(HAVE_TSOL)
+  if (is_system_labeled())
+  {
+    int in_range = 0;
+    int err = 0;
+    m_range_t *range;
+    m_label_t *sl = NULL;
+
+    if (p->device_uri == 0) /* this should never happen */
+      return (0);
+
+    if (str_to_label(slabel, &sl, USER_CLEAR, L_NO_CORRECTION, &err) < 0)
+    {
+      cupsdLogMessage(CUPSD_LOG_ERROR, "str_to_label(%s): %s", slabel,
+                      log_tsol_str_to_label_error(slabel, err));
+      return (0);
+    }
+
+    if ((range = getdevicerange((const char *)(p->device_uri))) == NULL)
+    {
+      cupsdLogMessage(CUPSD_LOG_ERROR,
+                    "cupsdInPrinterLabelRange(%s, %s): getdevicerange(%s): %s",
+                    slabel, p->name, p->device_uri, strerror(errno));
+      m_label_free(sl);
+      return (0);
+    }
+
+    /* is the client supplied object label is within the printer label range? */
+    in_range = blinrange(sl, range);
+
+    cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdInPrinterLabelRange(%s, %s): %d",
+                    slabel, p->name, in_range);
+
+    m_label_free(sl);
+    m_label_free(range->lower_bound);
+    m_label_free(range->upper_bound);
+    free(range);
+
+    return (in_range);
+  }
+#elif defined(HAVE_SELINUX)
+#endif /* HAVE_TSOL || HAVE_SELINUX */
+
+  /* we should probably never get here */
+  return (0);
+}
+
 /*
  * 'cupsdLoadAllPrinters()' - Load printers from the printers.conf file.
  */
Index: scheduler/job.c
===================================================================

--- scheduler/job.c.orig	Sun Oct 17 09:43:56 2010
+++ scheduler/job.c	Tue Aug 16 18:03:43 2011
@@ -911,8 +911,14 @@
     }
   }
 
-  if (Classification && !banner_page)
+  if (job->slabel != NULL)
   {
+    snprintf(classification, sizeof(classification), "CLASSIFICATION=%s",
+             job->slabel);
+    envp[envc ++] = classification;
+  }
+  else if (Classification && !banner_page)
+  {
     if ((attr = ippFindAttribute(job->attrs, "job-sheets",
                                  IPP_TAG_NAME)) == NULL)
       snprintf(classification, sizeof(classification), "CLASSIFICATION=%s",
@@ -1276,6 +1282,12 @@
     job->num_files = 0;
   }
 
+  if (job->slabel)
+  {
+    free(job->slabel);
+    job->slabel = NULL;
+  }
+
   if (job->history)
     free_job_history(job);
 
@@ -1562,6 +1574,10 @@
     goto error;
   }
 
+  if ((attr = ippFindAttribute(job->attrs, "security-label",
+                                IPP_TAG_NAME)) != NULL)
+    cupsdSetString(&job->slabel, attr->values[0].string.text);
+
   job->sheets     = ippFindAttribute(job->attrs, "job-media-sheets-completed",
                                      IPP_TAG_INTEGER);
   job->job_sheets = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_NAME);
@@ -3977,6 +3993,18 @@
   if (!cupsdLoadJob(job))
     return;
 
+  /*
+   * Verify that the job sensitivity label is in range of the printer.
+   */
+  if (cupsdInPrinterLabelRange(job->slabel, printer) == 0) {
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+                    "start_job(): job label outside of printer label range");
+    cupsdSetJobState(job, IPP_JOB_CANCELED, CUPSD_JOB_DEFAULT,
+                     "job label is outside of printer label range");
+    cupsdCheckJobs();
+    return;
+  }
+
   cupsdSetJobState(job, IPP_JOB_PROCESSING, CUPSD_JOB_DEFAULT, NULL);
   cupsdSetPrinterState(printer, IPP_PRINTER_PROCESSING, 0);

Index: scheduler/printers.h
===================================================================
--- scheduler/printers.h.orig	Wed Mar 31 03:37:33 2010
+++ scheduler/printers.h	Tue Aug 16 18:03:51 2011
@@ -151,6 +151,8 @@
 			                const char *username);
 extern void		cupsdFreePrinterUsers(cupsd_printer_t *p);
 extern void		cupsdFreeQuotas(cupsd_printer_t *p);
+extern int              cupsdInPrinterLabelRange(char *slabel,
+						 cupsd_printer_t *p);
 extern void		cupsdLoadAllPrinters(void);
 extern void		cupsdRenamePrinter(cupsd_printer_t *p,
 			                   const char *name);
Index: scheduler/job.h
===================================================================
--- scheduler/job.h	(revision 8857)
+++ scheduler/job.h	(working copy)
@@ -83,6 +83,8 @@
   krb5_ccache		ccache;		/* Kerberos credential cache */
   char			*ccname;	/* KRB5CCNAME environment variable */
 #endif /* HAVE_GSSAPI */
+  char                  *slabel;		/* security context for security
+					   labeled environments */
 };
 
 typedef struct cupsd_joblog_s		/**** Job log message ****/
Index: scheduler/client.c
===================================================================
--- scheduler/client.c.orig	Sun Oct 17 09:43:56 2010
+++ scheduler/client.c	Tue Aug 16 18:04:07 2011
@@ -90,7 +90,12 @@
 #  include <tcpd.h>
 #endif /* HAVE_TCPD_H */
 
+#ifdef HAVE_TSOL
+#include <ucred.h>
+#include <tsol/label.h>
+#endif /* HAVE_TSOL */
 
+
 /*
  * Local functions...
  */
@@ -123,7 +128,40 @@
 				   struct stat *filestats);
 static void		write_pipe(cupsd_client_t *con);
 
+#ifdef HAVE_TSOL
+/*
+ * Retrieve the sensitivity label from the peer connection.
+ */
+static int
+getpeerseclabel(int fd, char **label)
+{
+  if ((fd < 0) || (label == NULL)) {
+    errno = EINVAL;
+    return (-1);
+  }
 
+  *label = NULL; /* default to unlabeled */
+
+  if (is_system_labeled()) {
+    ucred_t *cred = NULL;
+    m_label_t *slabel;
+
+    if (getpeerucred(fd, &cred) == -1)
+      return (-1);
+
+    slabel = ucred_getlabel(cred);
+    *label = NULL;
+    if (label_to_str(slabel, label, M_INTERNAL, DEF_NAMES) != 0)
+      cupsdLogMessage(CUPSD_LOG_ERROR, "getpeercon(%d, 0x%8.8x): %s",
+                      fd, (int)label, strerror(errno));
+    ucred_free(cred);
+  }
+
+  return (0);
+}
+#endif /* HAVE_TSOL */
+
+
 /*
  * 'cupsdAcceptClient()' - Accept a new client.
  */
@@ -391,6 +429,21 @@
   }
 #endif /* HAVE_TCPD_H */
 
+#if defined(HAVE_TSOL) || defined(HAVE_SELINUX)
+ /*
+  * Get the sensitivity label from the peer connection.
+  */
+  if (getpeerseclabel(con->http.fd, &con->slabel))
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+                    "cupsdAcceptClient: failed to retrieve label from peer: %s",
+                    con->http.hostname);
+    con->slabel = NULL;
+  }
+  else
+    cupsdLogMessage(CUPSD_LOG_INFO, "cupsdAcceptClient: label=%s", con->slabel);
+#endif /* HAVE_TSOL || HAVE_SELINUX */
+
 #ifdef AF_INET6
   if (con->http.hostaddr->addr.sa_family == AF_INET6)
     cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdAcceptClient: %d from %s:%d (IPv6)",
@@ -680,6 +733,12 @@
     }
   }
 
+  if (con->slabel != NULL)
+  {
+    free(con->slabel);
+    con->slabel = NULL;
+  }
+
   if (!partial)
   {
    /*
Index: scheduler/client.h
===================================================================
--- scheduler/client.h	(revision 8857)
+++ scheduler/client.h	(working copy)
@@ -64,6 +64,8 @@
 #ifdef HAVE_AUTHORIZATION_H
   AuthorizationRef	authref;	/* Authorization ref */
 #endif /* HAVE_AUTHORIZATION_H */
+  char                  *slabel;		/* security context for security
+					   labeled environments */
 };
 
 #define HTTP(con) &((con)->http)
Index: scheduler/cupsd.h
===================================================================
--- scheduler/cupsd.h	(revision 8857)
+++ scheduler/cupsd.h	(working copy)
@@ -50,7 +50,19 @@
 #  include <CoreFoundation/CoreFoundation.h>
 #endif /* HAVE_CDSASSL */
 
+#if defined(HAVE_TSOL)
+#include <tsol/label.h>
+#endif /* HAVE_TSOL */
 
+#if defined(HAVE_SELINUX)
+#include <selinux/selinux.h>
+#include <selinux/context.h>
+#include <selinux/avc.h>
+#include <selinux/flask.h>
+#include <selinux/av_permissions.h>
+#include <selinux/get_context_list.h>
+#endif /* HAVE_SELINUX */
+
 /*
  * Some OS's don't have hstrerror(), most notably Solaris...
  */