]> git.pld-linux.org Git - packages/cups.git/blob - cups-lspp.patch
- rel 2; fix http auth for browsers like google chrome
[packages/cups.git] / cups-lspp.patch
1 diff -up cups-2.2.5/config.h.in.lspp cups-2.2.5/config.h.in
2 --- cups-2.2.5/config.h.in.lspp 2017-10-13 20:22:26.000000000 +0200
3 +++ cups-2.2.5/config.h.in      2017-10-17 19:06:19.640228964 +0200
4 @@ -730,4 +730,11 @@ static __inline int _cups_abs(int i) { r
5  #  endif /* __GNUC__ || __STDC_VERSION__ */
6  #endif /* !HAVE_ABS && !abs */
7  
8 +/*
9 + * Are we trying to meet LSPP requirements?
10 + */
11 +
12 +#undef WITH_LSPP
13 +
14 +
15  #endif /* !_CUPS_CONFIG_H_ */
16 diff -up cups-2.2.5/config-scripts/cups-lspp.m4.lspp cups-2.2.5/config-scripts/cups-lspp.m4
17 --- cups-2.2.5/config-scripts/cups-lspp.m4.lspp 2017-10-17 19:06:19.640228964 +0200
18 +++ cups-2.2.5/config-scripts/cups-lspp.m4      2017-10-17 19:06:19.640228964 +0200
19 @@ -0,0 +1,36 @@
20 +dnl
21 +dnl   LSPP code for the Common UNIX Printing System (CUPS).
22 +dnl
23 +dnl   Copyright 2005-2006 by Hewlett-Packard Development Company, L.P.
24 +dnl
25 +dnl   This program is free software; you can redistribute it and/or modify
26 +dnl   it under the terms of the GNU General Public License as published by
27 +dnl   the Free Software Foundation; version 2.
28 +dnl
29 +dnl   This program is distributed in the hope that it will be useful, but
30 +dnl   WITHOUT ANY WARRANTY; without even the implied warranty of
31 +dnl   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
32 +dnl   General Public License for more details.
33 +dnl
34 +dnl   You should have received a copy of the GNU General Public License
35 +dnl   along with this program; if not, write to the Free Software Foundation,
36 +dnl   Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301 USA
37 +dnl
38 +
39 +dnl Are we trying to meet LSPP requirements
40 +AC_ARG_ENABLE(lspp, [  --enable-lspp           turn on auditing and label support, default=no])
41 +
42 +if test x"$enable_lspp" != xno; then
43 +    case "$uname" in
44 +        Linux)
45 +            AC_CHECK_LIB(audit,audit_log_user_message, [LIBAUDIT="-laudit" AC_SUBST(LIBAUDIT)])
46 +            AC_CHECK_HEADER(libaudit.h)
47 +            AC_CHECK_LIB(selinux,getpeercon, [LIBSELINUX="-lselinux" AC_SUBST(LIBSELINUX)])
48 +            AC_CHECK_HEADER(selinux/selinux.h)
49 +            AC_DEFINE(WITH_LSPP)
50 +            ;;
51 +        *)
52 +            # All others
53 +            ;;
54 +    esac
55 +fi
56 diff -up cups-2.2.5/configure.ac.lspp cups-2.2.5/configure.ac
57 --- cups-2.2.5/configure.ac.lspp        2017-10-13 20:22:26.000000000 +0200
58 +++ cups-2.2.5/configure.ac     2017-10-17 19:06:19.640228964 +0200
59 @@ -38,6 +38,8 @@ sinclude(config-scripts/cups-startup.m4)
60  sinclude(config-scripts/cups-defaults.m4)
61  sinclude(config-scripts/cups-scripting.m4)
62  
63 +sinclude(config-scripts/cups-lspp.m4)
64 +
65  INSTALL_LANGUAGES=""
66  UNINSTALL_LANGUAGES=""
67  LANGFILES=""
68 diff -up cups-2.2.5/filter/common.c.lspp cups-2.2.5/filter/common.c
69 --- cups-2.2.5/filter/common.c.lspp     2017-10-13 20:22:26.000000000 +0200
70 +++ cups-2.2.5/filter/common.c  2017-10-17 19:06:19.640228964 +0200
71 @@ -17,6 +17,12 @@
72   * Include necessary headers...
73   */
74  
75 +#include "config.h"
76 +#ifdef WITH_LSPP
77 +#define _GNU_SOURCE
78 +#include <string.h>
79 +#endif /* WITH_LSPP */
80 +
81  #include "common.h"
82  #include <locale.h>
83  
84 @@ -299,6 +305,18 @@ WriteLabelProlog(const char *label,        /* I
85  {
86    const char   *classification;        /* CLASSIFICATION environment variable */
87    const char   *ptr;                   /* Temporary string pointer */
88 +#ifdef WITH_LSPP
89 +  int           i,                      /* counter */
90 +                n,                      /* counter */
91 +                lines,                  /* number of lines needed */
92 +                line_len,               /* index into tmp_label */
93 +                label_len,              /* length of the label in characters */
94 +                label_index,            /* index into the label */
95 +                longest,                /* length of the longest line */
96 +                longest_line,           /* index to the longest line */
97 +                max_width;              /* maximum width in characters */
98 +  char          **wrapped_label;        /* label with line breaks */
99 +#endif /* WITH_LSPP */
100  
101  
102   /*
103 @@ -321,6 +339,124 @@ WriteLabelProlog(const char *label,       /* I
104      return;
105    }
106  
107 +#ifdef WITH_LSPP
108 +  if (strncmp(classification, "LSPP:", 5) == 0 && label == NULL)
109 +  {
110 +   /*
111 +    * Based on the 12pt fixed width font below determine the max_width
112 +    */
113 +    max_width = width / 8;
114 +    longest_line = 0;
115 +    longest = 0;
116 +    classification += 5; // Skip the "LSPP:"
117 +    label_len = strlen(classification);
118 +
119 +    if (label_len > max_width)
120 +    {
121 +      lines = 1 + (int)(label_len / max_width);
122 +      line_len = (int)(label_len / lines);
123 +      wrapped_label = malloc(sizeof(*wrapped_label) * lines);
124 +      label_index = i = n = 0;
125 +      while (classification[label_index])
126 +      {
127 +        if ((label_index + line_len) > label_len)
128 +          break;
129 +        switch (classification[label_index + line_len + i])
130 +        {
131 +          case ':':
132 +          case ',':
133 +          case '-':
134 +            i++;
135 +            wrapped_label[n++] = strndup(&classification[label_index], (line_len + i));
136 +            label_index += line_len + i;
137 +            i = 0;
138 +            break;
139 +          default:
140 +            i++;
141 +            break;
142 +        }
143 +        if ((i + line_len) == max_width)
144 +        {
145 +          wrapped_label[n++] = strndup(&(classification[label_index]), (line_len + i));
146 +          label_index = label_index + line_len + i;
147 +          i = 0;
148 +        }
149 +      }
150 +      wrapped_label[n] = strndup(&classification[label_index], label_len - label_index);
151 +    }
152 +    else
153 +    {
154 +      lines = 1;
155 +      wrapped_label = malloc(sizeof(*wrapped_label));
156 +      wrapped_label[0] = (char*)classification;
157 +    }
158 +
159 +    for (n = 0; n < lines; n++ )
160 +    {
161 +      printf("userdict/ESPp%c(", ('a' + n));
162 +      for (ptr = wrapped_label[n], i = 0; *ptr; ptr ++, i++)
163 +        if (*ptr < 32 || *ptr > 126)
164 +          printf("\\%03o", *ptr);
165 +        else
166 +        {
167 +          if (*ptr == '(' || *ptr == ')' || *ptr == '\\')
168 +            putchar('\\');
169 +
170 +          printf("%c", *ptr);
171 +        }
172 +      if (i > longest)
173 +      {
174 +        longest = i;
175 +        longest_line = n;
176 +      }
177 +      printf(")put\n");
178 +    }
179 +
180 +   /*
181 +    * For LSPP use a fixed width font so that line wrapping can be calculated
182 +    */
183 +
184 +    puts("userdict/ESPlf /Nimbus-Mono findfont 12 scalefont put");
185 +
186 +   /*
187 +    * Finally, the procedure to write the labels on the page...
188 +    */
189 +
190 +    printf("userdict/ESPwl{\n"
191 +           "  ESPlf setfont\n");
192 +    printf("  ESPp%c stringwidth pop dup 12 add exch -0.5 mul %.0f add\n ",
193 +           'a' + longest_line, width * 0.5f);
194 +    for (n = 1; n < lines; n++)
195 +      printf(" dup");
196 +    printf("\n  1 setgray\n");
197 +    printf("  dup 6 sub %.0f %d index %.0f ESPrf\n",
198 +           (bottom - 2.0), (2 + lines), 6.0 + (16.0 * lines));
199 +    printf("  dup 6 sub %.0f %d index %.0f ESPrf\n",
200 +           (top - 6.0 - (16.0 * lines)), (2 + lines), 4.0 + (16.0 * lines));
201 +    printf("  0 setgray\n");
202 +    printf("  dup 6 sub %.0f %d index %.0f ESPrs\n",
203 +           (bottom - 2.0), (2 + lines), 6.0 + (16.0 * lines));
204 +    printf("  dup 6 sub %.0f %d index %.0f ESPrs\n",
205 +           (top - 6.0 - (16.0 * lines)), (2 + lines), 4.0 + (16.0 * lines));
206 +    for (n = 0; n < lines; n ++)
207 +    {
208 +      printf("  dup %.0f moveto ESPp%c show\n",
209 +             bottom + 6.0 + ((lines - (n+1)) * 16.0), 'a' + n);
210 +      printf("  %.0f moveto ESPp%c show\n", top + 2.0 - ((n + 1) * 16.0), 'a' + n);
211 +    }
212 +    printf("  pop\n"
213 +           "}bind put\n");
214 +
215 +   /*
216 +    * Do some clean up at the end of the LSPP special case
217 +    */
218 +    free(wrapped_label);
219 +
220 +  }
221 +  else
222 +  {
223 +#endif /* !WITH_LSPP */
224 +  
225   /*
226    * Set the classification + page label string...
227    */
228 @@ -401,7 +537,10 @@ WriteLabelProlog(const char *label,        /* I
229    printf("  %.0f moveto ESPpl show\n", top - 14.0);
230    puts("pop");
231    puts("}bind put");
232 +  }
233 +#ifdef WITH_LSPP
234  }
235 +#endif /* WITH_LSPP */
236  
237  
238  /*
239 diff -up cups-2.2.5/filter/pstops.c.lspp cups-2.2.5/filter/pstops.c
240 --- cups-2.2.5/filter/pstops.c.lspp     2017-10-13 20:22:26.000000000 +0200
241 +++ cups-2.2.5/filter/pstops.c  2017-10-17 19:06:19.641228955 +0200
242 @@ -3176,6 +3176,18 @@ write_label_prolog(pstops_doc_t *doc,    /*
243  {
244    const char   *classification;        /* CLASSIFICATION environment variable */
245    const char   *ptr;                   /* Temporary string pointer */
246 +#ifdef WITH_LSPP
247 +  int           i,                      /* counter */
248 +                n,                      /* counter */
249 +                lines,                  /* number of lines needed */
250 +                line_len,               /* index into tmp_label */
251 +                label_len,              /* length of the label in characters */
252 +                label_index,            /* index into the label */
253 +                longest,                /* length of the longest line */
254 +                longest_line,           /* index to the longest line */
255 +                max_width;              /* maximum width in characters */
256 +  char          **wrapped_label;        /* label with line breaks */
257 +#endif /* WITH_LSPP */
258  
259  
260   /*
261 @@ -3198,6 +3210,124 @@ write_label_prolog(pstops_doc_t *doc,   /*
262      return;
263    }
264  
265 +#ifdef WITH_LSPP
266 +  if (strncmp(classification, "LSPP:", 5) == 0 && label == NULL)
267 +  {
268 +   /*
269 +    * Based on the 12pt fixed width font below determine the max_width
270 +    */
271 +    max_width = width / 8;
272 +    longest_line = 0;
273 +    longest = 0;
274 +    classification += 5; // Skip the "LSPP:"
275 +    label_len = strlen(classification);
276 +
277 +    if (label_len > max_width)
278 +    {
279 +      lines = 1 + (int)(label_len / max_width);
280 +      line_len = (int)(label_len / lines);
281 +      wrapped_label = malloc(sizeof(*wrapped_label) * lines);
282 +      label_index = i = n = 0;
283 +      while (classification[label_index])
284 +      {
285 +        if ((label_index + line_len) > label_len)
286 +          break;
287 +        switch (classification[label_index + line_len + i])
288 +        {
289 +          case ':':
290 +          case ',':
291 +          case '-':
292 +            i++;
293 +            wrapped_label[n++] = strndup(&classification[label_index], (line_len + i));
294 +            label_index += line_len + i;
295 +            i = 0;
296 +            break;
297 +          default:
298 +            i++;
299 +            break;
300 +        }
301 +        if ((i + line_len) == max_width)
302 +        {
303 +          wrapped_label[n++] = strndup(&(classification[label_index]), (line_len + i));
304 +          label_index = label_index + line_len + i;
305 +          i = 0;
306 +        }
307 +      }
308 +      wrapped_label[n] = strndup(&classification[label_index], label_len - label_index);
309 +    }
310 +    else
311 +    {
312 +      lines = 1;
313 +      wrapped_label = malloc(sizeof(*wrapped_label));
314 +      wrapped_label[0] = (char*)classification;
315 +    }
316 +
317 +    for (n = 0; n < lines; n++ )
318 +    {
319 +      printf("userdict/ESPp%c(", ('a' + n));
320 +      for (ptr = wrapped_label[n], i = 0; *ptr; ptr ++, i++)
321 +        if (*ptr < 32 || *ptr > 126)
322 +          printf("\\%03o", *ptr);
323 +        else
324 +        {
325 +          if (*ptr == '(' || *ptr == ')' || *ptr == '\\')
326 +            putchar('\\');
327 +
328 +          printf("%c", *ptr);
329 +        }
330 +      if (i > longest)
331 +      {
332 +        longest = i;
333 +        longest_line = n;
334 +      }
335 +      printf(")put\n");
336 +    }
337 +
338 +   /*
339 +    * For LSPP use a fixed width font so that line wrapping can be calculated
340 +    */
341 +
342 +    puts("userdict/ESPlf /Nimbus-Mono findfont 12 scalefont put");
343 +
344 +   /*
345 +    * Finally, the procedure to write the labels on the page...
346 +    */
347 +
348 +    printf("userdict/ESPwl{\n"
349 +           "  ESPlf setfont\n");
350 +    printf("  ESPp%c stringwidth pop dup 12 add exch -0.5 mul %.0f add\n ",
351 +           'a' + longest_line, width * 0.5f);
352 +    for (n = 1; n < lines; n++)
353 +      printf(" dup");
354 +    printf("\n  1 setgray\n");
355 +    printf("  dup 6 sub %.0f %d index %.0f ESPrf\n",
356 +           (bottom - 2.0), (2 + lines), 6.0 + (16.0 * lines));
357 +    printf("  dup 6 sub %.0f %d index %.0f ESPrf\n",
358 +           (top - 6.0 - (16.0 * lines)), (2 + lines), 4.0 + (16.0 * lines));
359 +    printf("  0 setgray\n");
360 +    printf("  dup 6 sub %.0f %d index %.0f ESPrs\n",
361 +           (bottom - 2.0), (2 + lines), 6.0 + (16.0 * lines));
362 +    printf("  dup 6 sub %.0f %d index %.0f ESPrs\n",
363 +           (top - 6.0 - (16.0 * lines)), (2 + lines), 4.0 + (16.0 * lines));
364 +    for (n = 0; n < lines; n ++)
365 +    {
366 +      printf("  dup %.0f moveto ESPp%c show\n",
367 +             bottom + 6.0 + ((lines - (n+1)) * 16.0), 'a' + n);
368 +      printf("  %.0f moveto ESPp%c show\n", top + 2.0 - ((n + 1) * 16.0), 'a' + n);
369 +    }
370 +    printf("  pop\n"
371 +           "}bind put\n");
372 +
373 +   /*
374 +    * Do some clean up at the end of the LSPP special case
375 +    */
376 +    free(wrapped_label);
377 +
378 +  }
379 +  else
380 +  {
381 +#endif /* !WITH_LSPP */
382 +
383   /*
384    * Set the classification + page label string...
385    */
386 @@ -3276,7 +3406,10 @@ write_label_prolog(pstops_doc_t *doc,    /*
387    doc_printf(doc, "  %.0f moveto ESPpl show\n", top - 14.0);
388    doc_puts(doc, "pop\n");
389    doc_puts(doc, "}bind put\n");
390 +  }
391 +#ifdef WITH_LSPP
392  }
393 +#endif /* WITH_LSPP */
394  
395  
396  /*
397 diff -up cups-2.2.5/Makedefs.in.lspp cups-2.2.5/Makedefs.in
398 --- cups-2.2.5/Makedefs.in.lspp 2017-10-13 20:22:26.000000000 +0200
399 +++ cups-2.2.5/Makedefs.in      2017-10-17 19:06:19.641228955 +0200
400 @@ -161,7 +161,7 @@ LDFLAGS             =       -L../cgi-bin -L../cups -L../f
401                         @LDFLAGS@ @RELROFLAGS@ @PIEFLAGS@ $(OPTIM)
402  LINKCUPS       =       @LINKCUPS@ $(LIBGSSAPI) $(DNSSDLIBS) $(SSLLIBS) $(LIBZ)
403  LINKCUPSIMAGE  =       @LINKCUPSIMAGE@
404 -LIBS           =       $(LINKCUPS) $(COMMONLIBS)
405 +LIBS           =       $(LINKCUPS) $(COMMONLIBS) @LIBAUDIT@ @LIBSELINUX@
406  ONDEMANDFLAGS  =       @ONDEMANDFLAGS@
407  ONDEMANDLIBS   =       @ONDEMANDLIBS@
408  OPTIM          =       @OPTIM@
409 diff -up cups-2.2.5/scheduler/client.c.lspp cups-2.2.5/scheduler/client.c
410 --- cups-2.2.5/scheduler/client.c.lspp  2017-10-13 20:22:26.000000000 +0200
411 +++ cups-2.2.5/scheduler/client.c       2017-10-17 19:06:19.689228556 +0200
412 @@ -22,12 +22,20 @@
413  #define _HTTP_NO_PRIVATE
414  #include "cupsd.h"
415  
416 +#ifndef _GNU_SOURCE
417 +#define _GNU_SOURCE
418 +#endif /* !defined(_GNU_SOURCE) */
419  #ifdef __APPLE__
420  #  include <libproc.h>
421  #endif /* __APPLE__ */
422  #ifdef HAVE_TCPD_H
423  #  include <tcpd.h>
424  #endif /* HAVE_TCPD_H */
425 +#ifdef WITH_LSPP
426 +#  include <selinux/selinux.h>
427 +#  include <selinux/context.h>
428 +#  include <fcntl.h>
429 +#endif /* WITH_LSPP */
430  
431  
432  /*
433 @@ -268,6 +276,59 @@ cupsdAcceptClient(cupsd_listener_t *lis)
434    }
435  #endif /* HAVE_TCPD_H */
436  
437 +#ifdef WITH_LSPP
438 +  if (is_lspp_config())
439 +  {
440 +    struct ucred cr;
441 +    unsigned int cl=sizeof(cr);
442 +
443 +    if (getsockopt(httpGetFd(con->http), SOL_SOCKET, SO_PEERCRED, &cr, &cl) == 0)
444 +    {
445 +     /*
446 +      * client_pid_to_auid() can be racey
447 +      * In this case the pid is based on a socket connected to the client
448 +      */
449 +      if ((con->auid = client_pid_to_auid(cr.pid)) == -1)
450 +      {
451 +        httpClose(con->http);
452 +        cupsdLogClient(con, CUPSD_LOG_ERROR,
453 +                      "Unable to determine client auid for client pid=%d",
454 +                      cr.pid);
455 +        free(con);
456 +        return;
457 +      }
458 +      cupsdLogClient(con, CUPSD_LOG_INFO,
459 +                    "peer's pid=%d, uid=%d, gid=%d, auid=%d",
460 +                    cr.pid, cr.uid, cr.gid, con->auid);
461 +    }
462 +    else
463 +    {
464 +      httpClose(con->http);
465 +      cupsdLogClient(con, CUPSD_LOG_ERROR, "getsockopt() failed");
466 +      free(con);
467 +      return; 
468 +    }
469 +
470 +   /*
471 +    * get the context of the peer connection
472 +    */
473 +    if (getpeercon(httpGetFd(con->http), &con->scon))
474 +    {
475 +      httpClose(con->http);
476 +      cupsdLogClient(con, CUPSD_LOG_ERROR, "getpeercon() failed");
477 +      free(con);
478 +      return; 
479 +    }
480 +
481 +    cupsdLogClient(con, CUPSD_LOG_INFO, "client context=%s", con->scon);
482 +  }
483 +  else
484 +  {
485 +    cupsdLogClient(con, CUPSD_LOG_DEBUG, "skipping getpeercon()");
486 +    cupsdSetString(&con->scon, UNKNOWN_SL);
487 +  }
488 +#endif /* WITH_LSPP */
489 +
490  #ifdef AF_LOCAL
491    if (httpAddrFamily(httpGetAddress(con->http)) == AF_LOCAL)
492    {
493 @@ -562,6 +623,13 @@ cupsdReadClient(cupsd_client_t *con)       /*
494    mime_type_t          *type;          /* MIME type of file */
495    cupsd_printer_t      *p;             /* Printer */
496    static unsigned      request_id = 0; /* Request ID for temp files */
497 +#ifdef WITH_LSPP
498 +  security_context_t   spoolcon;       /* context of the job file */
499 +  context_t            clicon;         /* contex_t container for con->scon */
500 +  context_t            tmpcon;         /* temp context to swap the level */
501 +  char                 *clirange;      /* SELinux sensitivity range */
502 +  char                 *cliclearance;  /* SELinux low end clearance */
503 +#endif /* WITH_LSPP */
504  
505  
506    status = HTTP_STATUS_CONTINUE;
507 @@ -1926,6 +1994,73 @@ cupsdReadClient(cupsd_client_t *con)     /*
508              fcntl(con->file, F_SETFD, fcntl(con->file, F_GETFD) | FD_CLOEXEC);
509           }
510  
511 +#ifdef WITH_LSPP
512 +         if (strncmp(con->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) != 0)
513 +         {
514 +           if (getfilecon(con->filename, &spoolcon) == -1)
515 +           {
516 +             cupsdSendError(con, HTTP_STATUS_SERVER_ERROR, CUPSD_AUTH_NONE);
517 +             cupsdCloseClient(con);
518 +             return;
519 +           }
520 +           clicon = context_new(con->scon);
521 +           tmpcon = context_new(spoolcon);
522 +           freecon(spoolcon);
523 +           if (!clicon || !tmpcon)
524 +           {
525 +             cupsdSendError(con, HTTP_STATUS_SERVER_ERROR, CUPSD_AUTH_NONE);
526 +             if (clicon)
527 +               context_free(clicon);
528 +             if (tmpcon)
529 +               context_free(tmpcon);
530 +             cupsdCloseClient(con);
531 +             return;
532 +           }
533 +           clirange = (char *) context_range_get(clicon);
534 +           if (clirange)
535 +           {
536 +             clirange = strdup(clirange);
537 +             if ((cliclearance = strtok(clirange, "-")) != NULL)
538 +             {
539 +               if (context_range_set(tmpcon, cliclearance) == -1)
540 +               {
541 +                 cupsdSendError(con, HTTP_STATUS_SERVER_ERROR, CUPSD_AUTH_NONE);
542 +                 free(clirange);
543 +                 context_free(tmpcon);
544 +                 context_free(clicon);
545 +                 cupsdCloseClient(con);
546 +                 return;
547 +               }
548 +             }
549 +             else
550 +             {
551 +               if (context_range_set(tmpcon, (context_range_get(clicon))) == -1)
552 +               {
553 +                 cupsdSendError(con, HTTP_STATUS_SERVER_ERROR, CUPSD_AUTH_NONE);
554 +                 free(clirange);
555 +                 context_free(tmpcon);
556 +                 context_free(clicon);
557 +                 cupsdCloseClient(con);
558 +                 return;
559 +               }
560 +             }
561 +             free(clirange);
562 +           }
563 +           if (setfilecon(con->filename, context_str(tmpcon)) == -1)
564 +           {
565 +             cupsdSendError(con, HTTP_STATUS_SERVER_ERROR, CUPSD_AUTH_NONE);
566 +             context_free(tmpcon);
567 +             context_free(clicon);
568 +             cupsdCloseClient(con);
569 +             return;
570 +           }
571 +           cupsdLogClient(con, CUPSD_LOG_DEBUG2, "%s set to %s", 
572 +                          con->filename, context_str(tmpcon));
573 +           context_free(tmpcon);
574 +           context_free(clicon);
575 +         }
576 +#endif /* WITH_LSPP */
577 +
578           if (httpGetState(con->http) != HTTP_STATE_POST_SEND)
579           {
580             if (!httpWait(con->http, 0))
581 @@ -3456,6 +3591,49 @@ is_path_absolute(const char *path)       /* I
582    return (1);
583  }
584  
585 +#ifdef WITH_LSPP
586 +/*
587 + * 'client_pid_to_auid()' - Using the client's pid, read /proc and determine the loginuid.
588 + */
589 +
590 +uid_t client_pid_to_auid(pid_t clipid)
591 +{
592 +  uid_t uid;
593 +  int len, in;
594 +  char buf[16] = {0};
595 +  char fname[32] = {0};
596 +
597 +
598 + /*
599 +  * Hopefully this pid is still the one we are interested in.
600 +  */
601 +  snprintf(fname, 32, "/proc/%d/loginuid", clipid);
602 +  in = open(fname, O_NOFOLLOW|O_RDONLY);
603 +
604 +  if (in < 0)
605 +    return (uid_t) -1;
606 +
607 +  errno = 0;
608 +
609 +  do {
610 +    len = read(in, buf, sizeof(buf));
611 +  } while (len < 0 && errno == EINTR);
612 +
613 +  close(in);
614 +
615 +  if (len < 0 || len >= sizeof(buf))
616 +    return (uid_t) -1;
617 +
618 +  errno = 0;
619 +  buf[len] = 0;
620 +  uid = strtol(buf, 0, 10);
621 +
622 +  if (errno != 0)
623 +    return (uid_t) -1;
624 +  else
625 +    return uid;
626 +}
627 +#endif /* WITH_LSPP */
628  
629  /*
630   * 'pipe_command()' - Pipe the output of a command to the remote client.
631 diff -up cups-2.2.5/scheduler/client.h.lspp cups-2.2.5/scheduler/client.h
632 --- cups-2.2.5/scheduler/client.h.lspp  2017-10-13 20:22:26.000000000 +0200
633 +++ cups-2.2.5/scheduler/client.h       2017-10-17 19:06:19.690228548 +0200
634 @@ -16,6 +16,13 @@
635  #endif /* HAVE_AUTHORIZATION_H */
636  
637  
638 +/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */
639 +/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */
640 +
641 +#ifdef WITH_LSPP
642 +#include <selinux/selinux.h>
643 +#endif /* WITH_LSPP */
644 +
645  /*
646   * HTTP client structure...
647   */
648 @@ -65,6 +72,10 @@ struct cupsd_client_s
649  #ifdef HAVE_AUTHORIZATION_H
650    AuthorizationRef     authref;        /* Authorization ref */
651  #endif /* HAVE_AUTHORIZATION_H */
652 +#ifdef WITH_LSPP
653 +  security_context_t   scon;           /* Security context of connection */
654 +  uid_t                        auid;           /* Audit loginuid of the client */
655 +#endif /* WITH_LSPP */
656  };
657  
658  #define HTTP(con) ((con)->http)
659 @@ -138,6 +149,9 @@ extern void cupsdStartListening(void);
660  extern void    cupsdStopListening(void);
661  extern void    cupsdUpdateCGI(void);
662  extern void    cupsdWriteClient(cupsd_client_t *con);
663 +#ifdef WITH_LSPP
664 +extern uid_t   client_pid_to_auid(pid_t clipid);
665 +#endif /* WITH_LSPP */
666  
667  #ifdef HAVE_SSL
668  extern int     cupsdEndTLS(cupsd_client_t *con);
669 diff -up cups-2.2.5/scheduler/conf.c.lspp cups-2.2.5/scheduler/conf.c
670 --- cups-2.2.5/scheduler/conf.c.lspp    2017-10-17 19:06:19.637228989 +0200
671 +++ cups-2.2.5/scheduler/conf.c 2017-10-17 19:06:19.691228540 +0200
672 @@ -40,6 +40,9 @@
673  #  define INADDR_NONE  0xffffffff
674  #endif /* !INADDR_NONE */
675  
676 +#ifdef WITH_LSPP
677 +#  include <libaudit.h>
678 +#endif /* WITH_LSPP */
679  
680  /*
681   * Configuration variable structure...
682 @@ -131,6 +134,10 @@ static const cupsd_var_t   cupsd_vars[] =
683    { "ServerName",              &ServerName,            CUPSD_VARTYPE_STRING },
684    { "StrictConformance",       &StrictConformance,     CUPSD_VARTYPE_BOOLEAN },
685    { "Timeout",                 &Timeout,               CUPSD_VARTYPE_TIME },
686 +#ifdef WITH_LSPP
687 +  { "AuditLog",                        &AuditLog,              CUPSD_VARTYPE_INTEGER },
688 +  { "PerPageLabels",           &PerPageLabels,         CUPSD_VARTYPE_BOOLEAN },
689 +#endif /* WITH_LSPP */
690    { "WebInterface",            &WebInterface,          CUPSD_VARTYPE_BOOLEAN }
691  };
692  static const cupsd_var_t       cupsfiles_vars[] =
693 @@ -544,6 +551,9 @@ cupsdReadConfiguration(void)
694    const char   *tmpdir;                /* TMPDIR environment variable */
695    struct stat  tmpinfo;                /* Temporary directory info */
696    cupsd_policy_t *p;                   /* Policy */
697 +#ifdef WITH_LSPP
698 +  char         *audit_message;         /* Audit message string */
699 +#endif /* WITH_LSPP */
700  
701  
702   /*
703 @@ -866,6 +876,25 @@ cupsdReadConfiguration(void)
704  
705    RunUser = getuid();
706  
707 +#ifdef WITH_LSPP
708 +  if (AuditLog != -1)
709 +  {
710 +   /*
711 +    * ClassifyOverride is set during read_configuration, if its ON, report it now
712 +    */
713 +    if (ClassifyOverride)
714 +      audit_log_user_message(AuditLog, AUDIT_USYS_CONFIG,
715 +                "[Config] ClassifyOverride=enabled Users can override print banners",
716 +                ServerName, NULL, NULL, 1);
717 +   /*
718 +    * PerPageLabel is set during read_configuration, if its OFF, report it now
719 +    */
720 +    if (!PerPageLabels)
721 +      audit_log_user_message(AuditLog, AUDIT_USYS_CONFIG,
722 +                "[Config] PerPageLabels=disabled", ServerName, NULL, NULL, 1);
723 +  }
724 +#endif /* WITH_LSPP */
725 +
726    cupsdLogMessage(CUPSD_LOG_INFO, "Remote access is %s.",
727                    RemotePort ? "enabled" : "disabled");
728  
729 @@ -1286,7 +1315,19 @@ cupsdReadConfiguration(void)
730      cupsdClearString(&Classification);
731  
732    if (Classification)
733 +  {
734      cupsdLogMessage(CUPSD_LOG_INFO, "Security set to \"%s\"", Classification);
735 +#ifdef WITH_LSPP
736 +    if (AuditLog != -1)
737 +    {
738 +      audit_message = NULL;
739 +      cupsdSetStringf(&audit_message, "[Config] Classification=%s", Classification);
740 +      audit_log_user_message(AuditLog, AUDIT_LABEL_LEVEL_CHANGE, audit_message,
741 +                             ServerName, NULL, NULL, 1);
742 +      cupsdClearString(&audit_message);
743 +    }
744 +#endif /* WITH_LSPP */
745 +  }
746  
747   /*
748    * Check the MaxClients setting, and then allocate memory for it...
749 @@ -3770,6 +3811,18 @@ read_location(cups_file_t *fp,           /* I - C
750    return ((FatalErrors & CUPSD_FATAL_CONFIG) ? 0 : linenum);
751  }
752  
753 +#ifdef WITH_LSPP
754 +int is_lspp_config()
755 +{
756 +  if (Classification != NULL)
757 +    return ((_cups_strcasecmp(Classification, MLS_CONFIG) == 0) 
758 +            || (_cups_strcasecmp(Classification, TE_CONFIG) == 0)
759 +            || (_cups_strcasecmp(Classification, SELINUX_CONFIG) == 0));
760 +  else
761 +    return 0;
762 +}
763 +#endif /* WITH_LSPP */
764 +
765  
766  /*
767   * 'read_policy()' - Read a <Policy name> definition.
768 diff -up cups-2.2.5/scheduler/conf.h.lspp cups-2.2.5/scheduler/conf.h
769 --- cups-2.2.5/scheduler/conf.h.lspp    2017-10-17 19:06:19.585229421 +0200
770 +++ cups-2.2.5/scheduler/conf.h 2017-10-17 19:06:19.691228540 +0200
771 @@ -250,6 +250,13 @@ VAR char           *ServerKeychain         VALUE(NULL);
772                                         /* Keychain holding cert + key */
773  #endif /* HAVE_SSL */
774  
775 +#ifdef WITH_LSPP
776 +VAR int                        AuditLog                VALUE(-1),
777 +                                       /* File descriptor for audit */
778 +                       PerPageLabels           VALUE(TRUE);
779 +                                       /* Put the label on each page */
780 +#endif /* WITH_LSPP */
781 +
782  #ifdef HAVE_ONDEMAND
783  VAR int                        IdleExitTimeout         VALUE(60);
784                                         /* Time after which an idle cupsd will exit */
785 @@ -268,6 +275,9 @@ VAR int                     HaveServerCreds         VALUE(0);
786  VAR gss_cred_id_t      ServerCreds;    /* Server's GSS credentials */
787  #endif /* HAVE_GSSAPI */
788  
789 +#ifdef WITH_LSPP
790 +extern int             is_lspp_config(void);
791 +#endif /* WITH_LSPP */
792  
793  /*
794   * Prototypes...
795 diff -up cups-2.2.5/scheduler/cupsd.h.lspp cups-2.2.5/scheduler/cupsd.h
796 --- cups-2.2.5/scheduler/cupsd.h.lspp   2017-10-17 19:06:19.626229080 +0200
797 +++ cups-2.2.5/scheduler/cupsd.h        2017-10-17 19:06:19.691228540 +0200
798 @@ -11,6 +11,8 @@
799   * file is missing or damaged, see the license at "http://www.cups.org/".
800   */
801  
802 +/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */
803 +/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */
804  
805  /*
806   * Include necessary headers.
807 @@ -36,13 +38,20 @@
808  #  include <unistd.h>
809  #endif /* WIN32 */
810  
811 +#include "config.h"
812 +#ifdef WITH_LSPP
813 +#  define MLS_CONFIG "mls"
814 +#  define TE_CONFIG "te"
815 +#  define SELINUX_CONFIG "SELinux"
816 +#  define UNKNOWN_SL "UNKNOWN SL"
817 +#endif /* WITH_LSPP */
818 +
819  #include "mime.h"
820  
821  #if defined(HAVE_CDSASSL)
822  #  include <CoreFoundation/CoreFoundation.h>
823  #endif /* HAVE_CDSASSL */
824  
825 -
826  /*
827   * Some OS's don't have hstrerror(), most notably Solaris...
828   */
829 diff -up cups-2.2.5/scheduler/ipp.c.lspp cups-2.2.5/scheduler/ipp.c
830 --- cups-2.2.5/scheduler/ipp.c.lspp     2017-10-17 19:06:19.599229305 +0200
831 +++ cups-2.2.5/scheduler/ipp.c  2017-10-17 19:06:19.695228506 +0200
832 @@ -14,6 +14,9 @@
833   * missing or damaged, see the license at "http://www.cups.org/".
834   */
835  
836 +/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */
837 +/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */
838 +
839  /*
840   * Include necessary headers...
841   */
842 @@ -37,6 +40,14 @@ extern int mbr_check_membership_by_id(uu
843  #  endif /* HAVE_MEMBERSHIPPRIV_H */
844  #endif /* __APPLE__ */
845  
846 +#ifdef WITH_LSPP
847 +#include <libaudit.h>
848 +#include <selinux/selinux.h>
849 +#include <selinux/context.h>
850 +#include <selinux/avc.h>
851 +#include <selinux/flask.h>
852 +#include <selinux/av_permissions.h>
853 +#endif /* WITH_LSPP */
854  
855  /*
856   * Local functions...
857 @@ -61,6 +72,9 @@ static void   cancel_all_jobs(cupsd_client
858  static void    cancel_job(cupsd_client_t *con, ipp_attribute_t *uri);
859  static void    cancel_subscription(cupsd_client_t *con, int id);
860  static int     check_rss_recipient(const char *recipient);
861 +#ifdef WITH_LSPP
862 +static int     check_context(cupsd_client_t *con, cupsd_job_t *job);
863 +#endif /* WITH_LSPP */
864  static int     check_quotas(cupsd_client_t *con, cupsd_printer_t *p);
865  static void    close_job(cupsd_client_t *con, ipp_attribute_t *uri);
866  static void    copy_attrs(ipp_t *to, ipp_t *from, cups_array_t *ra,
867 @@ -1286,6 +1300,21 @@ add_job(cupsd_client_t  *con,            /* I - Cl
868      "time-at-creation",
869      "time-at-processing"
870    };
871 +#ifdef WITH_LSPP
872 +  char         *audit_message;         /* Audit message string */
873 +  char         *printerfile;           /* device file pointed to by the printer */
874 +  char         *userheader = NULL;     /* User supplied job-sheets[0] */
875 +  char         *userfooter = NULL;     /* User supplied job-sheets[1] */
876 +  int          override = 0;           /* Was a banner overrode on a job */
877 +  security_id_t        clisid;                 /* SELinux SID for the client */
878 +  security_id_t        psid;                   /* SELinux SID for the printer */
879 +  context_t    printercon;             /* Printer's context string */
880 +  struct stat  printerstat;            /* Printer's stat buffer */
881 +  security_context_t   devcon;         /* Printer's SELinux context */
882 +  struct avc_entry_ref avcref;         /* Pointer to the access vector cache */
883 +  security_class_t     tclass;         /* Object class for the SELinux check */
884 +  access_vector_t      avr;            /* Access method being requested */
885 +#endif /* WITH_LSPP */
886  
887  
888    cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_job(%p[%d], %p(%s), %p(%s/%s))",
889 @@ -1597,6 +1626,106 @@ add_job(cupsd_client_t  *con,           /* I - Cl
890      return (NULL);
891    }
892  
893 +#ifdef WITH_LSPP
894 +  if (is_lspp_config())
895 +  {
896 +    if (!con->scon || strncmp(con->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) == 0)
897 +    {
898 +      cupsdLogMessage(CUPSD_LOG_ERROR, "add_job: missing classification for connection \'%s\'!", printer->name);
899 +      send_ipp_status(con, IPP_INTERNAL_ERROR, _("Missing required security attributes."));
900 +      return (NULL);
901 +    }
902 +
903 +   /*
904 +    * Perform an access check so that if the user gets feedback at enqueue time
905 +    */
906 +
907 +    printerfile = strstr(printer->device_uri, "/dev/");
908 +    if (printerfile == NULL && (strncmp(printer->device_uri, "file:/", 6) == 0))
909 +      printerfile = printer->device_uri + strlen("file:");
910 +
911 +    if (printerfile != NULL)
912 +    {
913 +      cupsdLogMessage(CUPSD_LOG_DEBUG, "add_job: Attempting an access check on printer device %s",
914 +                      printerfile);
915 +
916 +      if (lstat(printerfile, &printerstat) < 0)
917 +      {
918 +       if (errno != ENOENT)
919 +       {
920 +         send_ipp_status(con, IPP_NOT_AUTHORIZED, _("Unable to stat the printer"));
921 +         return (NULL);
922 +       }
923 +       /*
924 +        * The printer does not exist, so for now assume it's a FileDevice
925 +        */
926 +       tclass = SECCLASS_FILE;
927 +       avr = FILE__WRITE;
928 +      }
929 +      else if (S_ISCHR(printerstat.st_mode))
930 +      {
931 +       tclass = SECCLASS_CHR_FILE;
932 +       avr = CHR_FILE__WRITE;
933 +      }
934 +      else if (S_ISREG(printerstat.st_mode))
935 +      {
936 +       tclass = SECCLASS_FILE;
937 +       avr = FILE__WRITE;
938 +      }
939 +      else
940 +      {
941 +       send_ipp_status(con, IPP_NOT_AUTHORIZED, _("Printer is not a character device or regular file"));
942 +       return (NULL);
943 +      }
944 +      static int avc_initialized = 0;
945 +      if (!avc_initialized++)
946 +          avc_init("cupsd_enqueue_", NULL, NULL, NULL, NULL);
947 +      avc_entry_ref_init(&avcref);
948 +      if (avc_context_to_sid(con->scon, &clisid) != 0)
949 +      {
950 +        send_ipp_status(con, IPP_NOT_AUTHORIZED, _("Unable to get the SELinux sid of the client"));
951 +        return (NULL);
952 +      }
953 +      if (getfilecon(printerfile, &devcon) == -1)
954 +      {
955 +        send_ipp_status(con, IPP_NOT_AUTHORIZED, _("Unable to get the SELinux context of the printer"));
956 +        return (NULL);
957 +      }
958 +      printercon = context_new(devcon);
959 +      cupsdLogMessage(CUPSD_LOG_DEBUG, "add_job: printer context %s client context %s",
960 +                      context_str(printercon), con->scon);
961 +      context_free(printercon);
962 +
963 +      if (avc_context_to_sid(devcon, &psid) != 0)
964 +      {
965 +        send_ipp_status(con, IPP_NOT_AUTHORIZED, _("Unable to get the SELinux sid of the printer"));
966 +        freecon(devcon);
967 +        return (NULL);
968 +      }
969 +      freecon(devcon);
970 +      if (avc_has_perm(clisid, psid, tclass, avr, &avcref, NULL) != 0)
971 +      {
972 +       /*
973 +        * The access check failed, so cancel the job and send an audit message
974 +        */
975 +        if (AuditLog != -1)
976 +        {
977 +          audit_message = NULL;
978 +          cupsdSetStringf(&audit_message, "job=? auid=%u acct=%s obj=%s refused"
979 +                          " unable to access printer=%s", con->auid,
980 +                          con->username, con->scon, printer->name);
981 +          audit_log_user_message(AuditLog, AUDIT_USER_LABELED_EXPORT, audit_message,
982 +                                 ServerName, NULL, NULL, 0);
983 +          cupsdClearString(&audit_message);
984 +        }
985 +
986 +        send_ipp_status(con, IPP_NOT_AUTHORIZED, _("SELinux prohibits access to the printer"));
987 +        return (NULL);
988 +      }
989 +    }
990 +  }
991 +#endif /* WITH_LSPP */
992 +
993    if ((job = cupsdAddJob(priority, printer->name)) == NULL)
994    {
995      send_ipp_status(con, IPP_INTERNAL_ERROR,
996 @@ -1605,6 +1734,32 @@ add_job(cupsd_client_t  *con,            /* I - Cl
997      return (NULL);
998    }
999  
1000 +#ifdef WITH_LSPP
1001 +  if (is_lspp_config())
1002 +  {
1003 +   /*
1004 +    * duplicate the security context and auid of the connection into the job structure
1005 +    */
1006 +    job->scon = strdup(con->scon);
1007 +    job->auid = con->auid;
1008 +
1009 +   /* 
1010 +    * add the security context to the request so that on a restart the security
1011 +    * attributes will be able to be restored
1012 +    */
1013 +    ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_NAME, "security-context", 
1014 +                NULL, job->scon);
1015 +  }
1016 +  else
1017 +  {
1018 +   /*
1019 +    * Fill in the security context of the job as unlabeled
1020 +    */
1021 +    cupsdLogMessage(CUPSD_LOG_DEBUG, "add_job: setting context of job to %s", UNKNOWN_SL);
1022 +    cupsdSetString(&job->scon, UNKNOWN_SL);
1023 +  }
1024 +#endif /* WITH_LSPP */
1025 +
1026    job->dtype   = printer->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE);
1027    job->attrs   = con->request;
1028    job->dirty   = 1;
1029 @@ -1794,6 +1949,29 @@ add_job(cupsd_client_t  *con,            /* I - Cl
1030        ippSetString(job->attrs, &attr, 0, printer->job_sheets[0]);
1031        ippSetString(job->attrs, &attr, 1, printer->job_sheets[1]);
1032      }
1033 +#ifdef WITH_LSPP
1034 +    else
1035 +    {
1036 +     /*
1037 +      * The option was present, so capture the user supplied strings
1038 +      */
1039 +      userheader = strdup(attr->values[0].string.text);
1040 +
1041 +      if (attr->num_values > 1)
1042 +        userfooter = strdup(attr->values[1].string.text);
1043 +
1044 +      if (Classification != NULL && (strcmp(userheader, Classification) == 0)
1045 +          && userfooter &&(strcmp(userfooter, Classification) == 0))
1046 +      {
1047 +       /*
1048 +        * Since both values are Classification, the user is not trying to Override
1049 +        */
1050 +        free(userheader);
1051 +        if (userfooter) free(userfooter);
1052 +        userheader = userfooter = NULL;
1053 +      }
1054 +    }
1055 +#endif /* WITH_LSPP */
1056  
1057      job->job_sheets = attr;
1058  
1059 @@ -1824,6 +2002,9 @@ add_job(cupsd_client_t  *con,             /* I - Cl
1060                                              "job-sheets=\"%s,none\", "
1061                                              "job-originating-user-name=\"%s\"",
1062                       Classification, job->username);
1063 +#ifdef WITH_LSPP
1064 +         override = 1;
1065 +#endif /* WITH_LSPP */
1066         }
1067         else if (attr->num_values == 2 &&
1068                  strcmp(attr->values[0].string.text,
1069 @@ -1842,6 +2023,9 @@ add_job(cupsd_client_t  *con,             /* I - Cl
1070                                              "job-originating-user-name=\"%s\"",
1071                       attr->values[0].string.text,
1072                       attr->values[1].string.text, job->username);
1073 +#ifdef WITH_LSPP
1074 +         override = 1;
1075 +#endif /* WITH_LSPP */
1076         }
1077         else if (strcmp(attr->values[0].string.text, Classification) &&
1078                  strcmp(attr->values[0].string.text, "none") &&
1079 @@ -1862,6 +2046,9 @@ add_job(cupsd_client_t  *con,             /* I - Cl
1080                         "job-originating-user-name=\"%s\"",
1081                         attr->values[0].string.text,
1082                         attr->values[1].string.text, job->username);
1083 +#ifdef WITH_LSPP
1084 +         override = 1;
1085 +#endif /* WITH_LSPP */
1086          }
1087        }
1088        else if (strcmp(attr->values[0].string.text, Classification) &&
1089 @@ -1902,8 +2089,52 @@ add_job(cupsd_client_t  *con,            /* I - Cl
1090                       "job-sheets=\"%s\", "
1091                       "job-originating-user-name=\"%s\"",
1092                       Classification, job->username);
1093 +#ifdef WITH_LSPP
1094 +       override = 1;
1095 +#endif /* WITH_LSPP */
1096        }
1097 +#ifdef WITH_LSPP
1098 +      if (is_lspp_config() && AuditLog != -1)
1099 +      {
1100 +        audit_message = NULL;
1101 +
1102 +        if (userheader || userfooter)
1103 +        {
1104 +          if (!override)
1105 +          {
1106 +           /*
1107 +            * The user overrode the banner, so audit it
1108 +            */
1109 +            cupsdSetStringf(&audit_message, "job=%d user supplied job-sheets=%s,%s"
1110 +                            " using banners=%s,%s", job->id, userheader,
1111 +                            userfooter, attr->values[0].string.text,
1112 +                            (attr->num_values > 1) ? attr->values[1].string.text : "(null)");
1113 +            audit_log_user_message(AuditLog, AUDIT_LABEL_OVERRIDE, audit_message,
1114 +                                   ServerName, NULL, NULL, 1);
1115 +         }
1116 +          else
1117 +          {
1118 +           /*
1119 +            * The user tried to override the banner, audit the failure
1120 +            */
1121 +            cupsdSetStringf(&audit_message, "job=%d user supplied job-sheets=%s,%s"
1122 +                            " ignored banners=%s,%s", job->id, userheader,
1123 +                            userfooter, attr->values[0].string.text,
1124 +                            (attr->num_values > 1) ? attr->values[1].string.text : "(null)");
1125 +            audit_log_user_message(AuditLog, AUDIT_LABEL_OVERRIDE, audit_message,
1126 +                                   ServerName, NULL, NULL, 0);
1127 +         }
1128 +          cupsdClearString(&audit_message);
1129 +       }
1130 +      }
1131 +
1132 +      if (userheader)
1133 +        free(userheader);
1134 +      if (userfooter)
1135 +        free(userfooter);
1136 +#endif /* WITH_LSPP */
1137      }
1138 +    
1139  
1140     /*
1141      * See if we need to add the starting sheet...
1142 @@ -3686,6 +3917,128 @@ check_rss_recipient(
1143  }
1144  
1145  
1146 +#ifdef WITH_LSPP
1147 +/*
1148 + * 'check_context()' - Check SELinux security context of a user and job
1149 + */
1150 +
1151 +static int                             /* O - 1 if OK, 0 if not, -1 on error */
1152 +check_context(cupsd_client_t *con,     /* I - Client connection */
1153 +             cupsd_job_t    *job)      /* I - Job */
1154 +{
1155 +  int                  enforcing;      /* is SELinux in enforcing mode */
1156 +  char                 filename[1024]; /* Filename of the spool file */
1157 +  security_id_t                clisid;         /* SELinux SID of the client */
1158 +  security_id_t                jobsid;         /* SELinux SID of the job */
1159 +  security_id_t                filesid;        /* SELinux SID of the spool file */
1160 +  struct avc_entry_ref avcref;         /* AVC entry cache pointer */
1161 +  security_class_t     tclass;         /* SELinux security class */
1162 +  access_vector_t      avr;            /* SELinux access being queried */
1163 +  security_context_t   spoolfilecon;   /* SELinux context of the spool file */
1164 +
1165 +
1166 + /*
1167 +  * Validate the input to be sure there are contexts to work with...
1168 +  */
1169 +
1170 +  if (con->scon == NULL || job->scon == NULL
1171 +      || strncmp(con->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) == 0
1172 +      || strncmp(job->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) == 0)
1173 +    return -1;
1174 +
1175 +  if ((enforcing = security_getenforce()) == -1)
1176 +  {
1177 +    cupsdLogJob(job, CUPSD_LOG_ERROR,
1178 +               "Error while determining SELinux enforcement");
1179 +    return -1;
1180 +  }
1181 +  cupsdLogJob(job, CUPSD_LOG_DEBUG,
1182 +             "check_context: client context %s job context %s",
1183 +             con->scon, job->scon);
1184 +
1185 +
1186 + /*
1187 +  * Initialize the avc engine...
1188 +  */
1189 +
1190 +  static int avc_initialized = 0;
1191 +  if (! avc_initialized++)
1192 +  {
1193 +    if (avc_init("cupsd", NULL, NULL, NULL, NULL) < 0)
1194 +    {
1195 +      cupsdLogJob(job, CUPSD_LOG_ERROR, "check_context: unable avc_init");
1196 +      return -1;
1197 +    } 
1198 +  } 
1199 +  if (avc_context_to_sid(con->scon, &clisid) != 0)
1200 +  {
1201 +    cupsdLogJob(job, CUPSD_LOG_ERROR,
1202 +               "check_context: unable to convert %s to SELinux sid",
1203 +               con->scon);
1204 +    return -1;
1205 +  }
1206 +  if (avc_context_to_sid(job->scon, &jobsid) != 0)
1207 +  {
1208 +    cupsdLogJob(job, CUPSD_LOG_ERROR,
1209 +               "check_context: unable to convert %s to SELinux sid",
1210 +               job->scon);
1211 +    return -1;
1212 +  }
1213 +  avc_entry_ref_init(&avcref);
1214 +  tclass = SECCLASS_FILE;
1215 +  avr = FILE__READ;
1216 +
1217 + /*
1218 +  * Perform the check with the client as the subject, first with the job as the object
1219 +  *   if that fails then with the spool file as the object...
1220 +  */
1221 +
1222 +  if (avc_has_perm_noaudit(clisid, jobsid, tclass, avr, &avcref, NULL) != 0)
1223 +  {
1224 +    cupsdLogJob(job, CUPSD_LOG_INFO,
1225 +               "check_context: SELinux denied access "
1226 +               "based on the client context");
1227 +
1228 +    snprintf(filename, sizeof(filename), "%s/c%05d", RequestRoot, job->id);
1229 +    if (getfilecon(filename, &spoolfilecon) == -1)
1230 +    {
1231 +      cupsdLogJob(job, CUPSD_LOG_ERROR,
1232 +                 "check_context: Unable to get spoolfile context");
1233 +      return -1;
1234 +    }
1235 +    if (avc_context_to_sid(spoolfilecon, &filesid) != 0)
1236 +    {
1237 +      cupsdLogJob(job, CUPSD_LOG_ERROR,
1238 +                 "check_context: Unable to determine the "
1239 +                 "SELinux sid for the spool file");
1240 +      freecon(spoolfilecon);
1241 +      return -1;
1242 +    }
1243 +    freecon(spoolfilecon);
1244 +    if (avc_has_perm_noaudit(clisid, filesid, tclass, avr, &avcref, NULL) != 0)
1245 +    {
1246 +      cupsdLogJob(job, CUPSD_LOG_INFO,
1247 +                 "check_context: SELinux denied access to the spool file");
1248 +      return 0;
1249 +    }
1250 +    cupsdLogJob(job, CUPSD_LOG_INFO,
1251 +               "check_context: SELinux allowed access to the spool file");
1252 +    return 1;
1253 +  }
1254 +  else
1255 +    if (enforcing == 0)
1256 +      cupsdLogJob(job, CUPSD_LOG_INFO,
1257 +                 "check_context: allowing operation due to permissive mode");
1258 +    else
1259 +      cupsdLogJob(job, CUPSD_LOG_INFO,
1260 +                 "check_context: SELinux allowed access based on the "
1261 +                 "client context");
1262 +
1263 +  return 1;
1264 +}
1265 +#endif /* WITH_LSPP */
1266 +
1267 +
1268  /*
1269   * 'check_quotas()' - Check quotas for a printer and user.
1270   */
1271 @@ -4142,6 +4495,15 @@ copy_banner(cupsd_client_t *con, /* I -
1272    char         attrname[255],          /* Name of attribute */
1273                 *s;                     /* Pointer into name */
1274    ipp_attribute_t *attr;               /* Attribute */
1275 +#ifdef WITH_LSPP
1276 +  const char   *mls_label;             /* SL of print job */
1277 +  char         *jobrange;              /* SELinux sensitivity range */
1278 +  char         *jobclearance;          /* SELinux low end clearance */
1279 +  context_t    jobcon;                 /* SELinux context of the job */
1280 +  context_t    tmpcon;                 /* Temp context to set the level */
1281 +  security_context_t   spoolcon;       /* Context of the file in the spool */
1282 +#endif /* WITH_LSPP */
1283 +
1284  
1285  
1286    cupsdLogMessage(CUPSD_LOG_DEBUG2,
1287 @@ -4177,6 +4539,85 @@ copy_banner(cupsd_client_t *con, /* I -
1288  
1289    fchmod(cupsFileNumber(out), 0640);
1290    fchown(cupsFileNumber(out), RunUser, Group);
1291 +#ifdef WITH_LSPP
1292 +  if (job->scon != NULL &&
1293 +      strncmp(job->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) != 0)
1294 +  {
1295 +    if (getfilecon(filename, &spoolcon) == -1)
1296 +    {
1297 +      cupsdLogJob(job, CUPSD_LOG_ERROR,
1298 +                 "Unable to get the context of the banner file %s - %s",
1299 +                 filename, strerror(errno));
1300 +      job->num_files --;
1301 +      return (0);
1302 +    }
1303 +    tmpcon = context_new(spoolcon);
1304 +    jobcon = context_new(job->scon);
1305 +    freecon(spoolcon);
1306 +    if (!tmpcon || !jobcon)
1307 +    {
1308 +      if (tmpcon)
1309 +        context_free(tmpcon);
1310 +      if (jobcon)
1311 +        context_free(jobcon);
1312 +      cupsdLogJob(job, CUPSD_LOG_ERROR,
1313 +                 "copy_banner: Unable to get the SELinux contexts");
1314 +      job->num_files --;
1315 +      return (0);
1316 +    }
1317 +    jobrange = (char *) context_range_get(jobcon);
1318 +    if (jobrange)
1319 +    {
1320 +      jobrange = strdup(jobrange);
1321 +      if ((jobclearance = strtok(jobrange, "-")) != NULL)
1322 +      {
1323 +       if (context_range_set(tmpcon, jobclearance) == -1)
1324 +       {
1325 +         cupsdLogJob(job, CUPSD_LOG_ERROR,
1326 +                     "copy_banner: Unable to set the "
1327 +                     "level of the context for file %s - %s",
1328 +                     filename, strerror(errno));
1329 +         free(jobrange);
1330 +         context_free(jobcon);
1331 +         context_free(tmpcon);
1332 +         job->num_files --;
1333 +         return (0);
1334 +       }
1335 +      }
1336 +      else
1337 +      {
1338 +       if (context_range_set(tmpcon, (context_range_get(jobcon))) == -1)
1339 +       {
1340 +         cupsdLogJob(job, CUPSD_LOG_ERROR,
1341 +                     "copy_banner: Unable to set the "
1342 +                     "level of the context for file %s - %s",
1343 +                     filename, strerror(errno));
1344 +         free(jobrange);
1345 +         context_free(jobcon);
1346 +         context_free(tmpcon);
1347 +         job->num_files --;
1348 +         return (0);
1349 +       }
1350 +      }
1351 +      free(jobrange);
1352 +    }
1353 +    if (setfilecon(filename, context_str(tmpcon)) == -1)
1354 +    {
1355 +      cupsdLogJob(job, CUPSD_LOG_ERROR,
1356 +                 "copy_banner: Unable to set the "
1357 +                 "context of the banner file %s - %s",
1358 +                 filename, strerror(errno));
1359 +      context_free(jobcon);
1360 +      context_free(tmpcon);
1361 +      job->num_files --;
1362 +      return (0);
1363 +    }
1364 +    cupsdLogJob(job, CUPSD_LOG_DEBUG2, "copy_banner: %s set to %s",
1365 +               filename, context_str(tmpcon));
1366 +    context_free(jobcon);
1367 +    context_free(tmpcon);
1368 +  }
1369 +#endif /* WITH_LSPP */
1370  
1371   /*
1372    * Try the localized banner file under the subdirectory...
1373 @@ -4271,6 +4712,24 @@ copy_banner(cupsd_client_t *con, /* I -
1374        else
1375          s = attrname;
1376  
1377 +#ifdef WITH_LSPP
1378 +      if (strcmp(s, "mls-label") == 0)
1379 +      {
1380 +        if (job->scon != NULL && strncmp(job->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) != 0)
1381 +        {
1382 +          jobcon = context_new(job->scon);
1383 +          if (_cups_strcasecmp(name, MLS_CONFIG) == 0)
1384 +            mls_label = context_range_get(jobcon);
1385 +          else if (_cups_strcasecmp(name, TE_CONFIG) == 0)
1386 +            mls_label = context_type_get(jobcon);
1387 +          else // default to using the whole context string
1388 +            mls_label = context_str(jobcon);
1389 +          cupsFilePuts(out, mls_label);
1390 +          context_free(jobcon);
1391 +        }
1392 +        continue;
1393 +      }
1394 +#endif /* WITH_LSPP */
1395        if (!strcmp(s, "printer-name"))
1396        {
1397          cupsFilePuts(out, job->dest);
1398 @@ -6459,6 +6918,22 @@ get_job_attrs(cupsd_client_t  *con,      /* I
1399  
1400    exclude = cupsdGetPrivateAttrs(policy, con, printer, job->username);
1401  
1402 +
1403 +#ifdef WITH_LSPP
1404 + /*
1405 +  * Check SELinux...
1406 +  */
1407 +  if (is_lspp_config() && check_context(con, job) != 1)
1408 +  {
1409 +   /*
1410 +    * Unfortunately we have to lie to the user...
1411 +    */
1412 +    send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist!"), jobid);
1413 +    return;
1414 +  }
1415 +#endif /* WITH_LSPP */
1416 +
1417 +
1418   /*
1419    * Copy attributes...
1420    */
1421 @@ -6856,6 +7331,11 @@ get_jobs(cupsd_client_t  *con,           /* I - C
1422        if (username[0] && _cups_strcasecmp(username, job->username))
1423         continue;
1424  
1425 +#ifdef WITH_LSPP
1426 +      if (is_lspp_config() && check_context(con, job) != 1)
1427 +       continue;
1428 +#endif /* WITH_LSPP */
1429 +
1430        if (count > 0)
1431         ippAddSeparator(con->response);
1432  
1433 @@ -11487,6 +11967,11 @@ validate_user(cupsd_job_t    *job,     /* I
1434  
1435    strlcpy(username, get_username(con), userlen);
1436  
1437 +#ifdef WITH_LSPP
1438 +  if (is_lspp_config() && check_context(con, job) != 1)
1439 +    return 0;
1440 +#endif /* WITH_LSPP */
1441 +
1442   /*
1443    * Check the username against the owner...
1444    */
1445 diff -up cups-2.2.5/scheduler/job.c.lspp cups-2.2.5/scheduler/job.c
1446 --- cups-2.2.5/scheduler/job.c.lspp     2017-10-17 19:06:19.607229238 +0200
1447 +++ cups-2.2.5/scheduler/job.c  2017-10-17 19:06:19.696228498 +0200
1448 @@ -11,6 +11,9 @@
1449   * missing or damaged, see the license at "http://www.cups.org/".
1450   */
1451  
1452 +/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */
1453 +/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */
1454 +
1455  /*
1456   * Include necessary headers...
1457   */
1458 @@ -26,6 +29,14 @@
1459  #  endif /* HAVE_IOKIT_PWR_MGT_IOPMLIBPRIVATE_H */
1460  #endif /* __APPLE__ */
1461  
1462 +#ifdef WITH_LSPP
1463 +#include <libaudit.h>
1464 +#include <selinux/selinux.h>
1465 +#include <selinux/context.h>
1466 +#include <selinux/avc.h>
1467 +#include <selinux/flask.h>
1468 +#include <selinux/av_permissions.h>
1469 +#endif /* WITH_LSPP */
1470  
1471  /*
1472   * Design Notes for Job Management
1473 @@ -547,6 +558,14 @@ cupsdContinueJob(cupsd_job_t *job) /* I
1474                                         /* PRINTER_STATE_REASONS env var */
1475                         rip_max_cache[255];
1476                                         /* RIP_MAX_CACHE env variable */
1477 +#ifdef WITH_LSPP
1478 +  char                 *audit_message = NULL;  /* Audit message string */
1479 +  context_t            jobcon;         /* SELinux context of the job */
1480 +  char                 *label_template = NULL; /* SL to put in classification
1481 +                                                  env var */
1482 +  const char           *mls_label = NULL;      /* SL to put in classification
1483 +                                                  env var */
1484 +#endif /* WITH_LSPP */
1485  
1486  
1487    cupsdLogMessage(CUPSD_LOG_DEBUG2,
1488 @@ -1083,6 +1102,67 @@ cupsdContinueJob(cupsd_job_t *job)       /* I
1489    if (final_content_type[0])
1490      envp[envc ++] = final_content_type;
1491  
1492 +#ifdef WITH_LSPP
1493 +  if (is_lspp_config())
1494 +  {
1495 +    if (!job->scon || strncmp(job->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) == 0)
1496 +    {
1497 +      if (AuditLog != -1)
1498 +      {
1499 +        audit_message = NULL;
1500 +        cupsdSetStringf(&audit_message, "job=%d auid=%u acct=%s printer=%s title=%s",
1501 +                        job->id, job->auid, job->username, job->printer->name, title);
1502 +        audit_log_user_message(AuditLog, AUDIT_USER_UNLABELED_EXPORT, audit_message,
1503 +                               ServerName, NULL, NULL, 1);
1504 +        cupsdClearString(&audit_message);
1505 +      }
1506 +    }
1507 +    else 
1508 +    {
1509 +      jobcon = context_new(job->scon);
1510 +
1511 +      if ((attr = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_NAME)) == NULL)
1512 +        label_template = strdup(Classification);
1513 +      else if (attr->num_values > 1 &&
1514 +               strcmp(attr->values[1].string.text, "none") != 0)
1515 +        label_template = strdup(attr->values[1].string.text);
1516 +      else
1517 +        label_template = strdup(attr->values[0].string.text);
1518 +
1519 +      if (_cups_strcasecmp(label_template, MLS_CONFIG) == 0)
1520 +        mls_label = context_range_get(jobcon);
1521 +      else if (_cups_strcasecmp(label_template, TE_CONFIG) == 0)
1522 +        mls_label = context_type_get(jobcon);
1523 +      else if (_cups_strcasecmp(label_template, SELINUX_CONFIG) == 0)
1524 +        mls_label = context_str(jobcon);
1525 +      else
1526 +        mls_label = label_template;
1527 +
1528 +      if (mls_label && (PerPageLabels || banner_page))
1529 +      {
1530 +        snprintf(classification, sizeof(classification), "CLASSIFICATION=LSPP:%s", mls_label);
1531 +        envp[envc ++] = classification;
1532 +      }
1533 +
1534 +      if ((AuditLog != -1) && !banner_page)
1535 +      {
1536 +        audit_message = NULL;
1537 +        cupsdSetStringf(&audit_message, "job=%d auid=%u acct=%s printer=%s title=%s"
1538 +                        " obj=%s label=%s", job->id, job->auid, job->username,
1539 +                        job->printer->name, title, job->scon, mls_label?mls_label:"none");
1540 +        audit_log_user_message(AuditLog, AUDIT_USER_LABELED_EXPORT, audit_message,
1541 +                               ServerName, NULL, NULL, 1);
1542 +        cupsdClearString(&audit_message);
1543 +      }
1544 +      context_free(jobcon);
1545 +      free(label_template);
1546 +    }
1547 +  }
1548 +  else
1549 +   /*
1550 +    * Fall through to the non-LSPP behavior
1551 +    */
1552 +#endif /* WITH_LSPP */
1553    if (Classification && !banner_page)
1554    {
1555      if ((attr = ippFindAttribute(job->attrs, "job-sheets",
1556 @@ -1908,6 +1988,22 @@ cupsdLoadJob(cupsd_job_t *job)           /* I - J
1557        ippSetString(job->attrs, &job->reasons, 0, "none");
1558    }
1559  
1560 +#ifdef WITH_LSPP
1561 +  if ((attr = ippFindAttribute(job->attrs, "security-context", IPP_TAG_NAME)) != NULL)
1562 +    cupsdSetString(&job->scon, attr->values[0].string.text);
1563 +  else if (is_lspp_config())
1564 +  {
1565 +   /*
1566 +    * There was no security context so delete the job
1567 +    */
1568 +    cupsdLogJob(job, CUPSD_LOG_ERROR,
1569 +               "Missing or bad security-context attribute "
1570 +               "in control file \"%s\"!",
1571 +               jobfile);
1572 +    goto error;
1573 +  }
1574 +#endif /* WITH_LSPP */
1575 +
1576    job->impressions = ippFindAttribute(job->attrs, "job-impressions-completed", IPP_TAG_INTEGER);
1577    job->sheets      = ippFindAttribute(job->attrs, "job-media-sheets-completed", IPP_TAG_INTEGER);
1578    job->job_sheets  = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_NAME);
1579 @@ -2321,6 +2417,14 @@ cupsdSaveJob(cupsd_job_t *job)           /* I - J
1580  {
1581    char         filename[1024];         /* Job control filename */
1582    cups_file_t  *fp;                    /* Job file */
1583 +#ifdef WITH_LSPP
1584 +  security_context_t   spoolcon;       /* context of the job control file */
1585 +  context_t            jobcon;         /* contex_t container for job->scon */
1586 +  context_t            tmpcon;         /* Temp context to swap the level */
1587 +  char                 *jobclearance;  /* SELinux low end clearance */
1588 +  const char           *jobrange;      /* SELinux sensitivity range */
1589 +  char                 *jobrange_copy; /* SELinux sensitivity range */
1590 +#endif /* WITH_LSPP */
1591  
1592  
1593    cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdSaveJob(job=%p(%d)): job->attrs=%p",
1594 @@ -2343,6 +2447,78 @@ cupsdSaveJob(cupsd_job_t *job)           /* I - J
1595  
1596    fchown(cupsFileNumber(fp), RunUser, Group);
1597  
1598 +#ifdef WITH_LSPP
1599 +  if (job->scon && strncmp(job->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) != 0)
1600 +  {
1601 +    if (getfilecon(filename, &spoolcon) == -1)
1602 +    {
1603 +      cupsdLogJob(job, CUPSD_LOG_ERROR,
1604 +                 "Unable to get context of job control file \"%s\" - %s.",
1605 +                 filename, strerror(errno));
1606 +      return;
1607 +    }
1608 +    jobcon = context_new(job->scon);
1609 +    tmpcon = context_new(spoolcon);
1610 +    freecon(spoolcon);
1611 +    if (!jobcon || !tmpcon)
1612 +    {
1613 +      if (jobcon)
1614 +        context_free(jobcon);
1615 +      if (tmpcon)
1616 +        context_free(tmpcon);
1617 +      cupsdLogJob(job, CUPSD_LOG_ERROR, "Unable to get SELinux contexts");
1618 +      return;
1619 +    }
1620 +    jobrange = context_range_get(jobcon);
1621 +    if (jobrange)
1622 +    {
1623 +      jobrange_copy = strdup(jobrange);
1624 +      if ((jobclearance = strtok(jobrange_copy, "-")) != NULL)
1625 +      {
1626 +       if (context_range_set(tmpcon, jobclearance) == -1)
1627 +       {
1628 +         cupsdLogJob(job, CUPSD_LOG_ERROR,
1629 +                     "Unable to set the range for "
1630 +                     "job control file \"%s\" - %s.",
1631 +                     filename, strerror(errno));
1632 +         free(jobrange_copy);
1633 +         context_free(tmpcon);
1634 +         context_free(jobcon);
1635 +         return;
1636 +       }
1637 +      }
1638 +      else
1639 +      {
1640 +       if (context_range_set(tmpcon, (context_range_get(jobcon))) == -1)
1641 +       {
1642 +         cupsdLogJob(job, CUPSD_LOG_ERROR,
1643 +                     "Unable to set the range for "
1644 +                     "job control file \"%s\" - %s.",
1645 +                     filename, strerror(errno));
1646 +         free(jobrange_copy);
1647 +         context_free(tmpcon);
1648 +         context_free(jobcon);
1649 +         return;
1650 +       }
1651 +      }
1652 +      free(jobrange_copy);
1653 +    }
1654 +    if (setfilecon(filename, context_str(tmpcon)) == -1)
1655 +    {
1656 +      cupsdLogJob(job, CUPSD_LOG_ERROR,
1657 +                 "Unable to set context of job control file \"%s\" - %s.",
1658 +                 filename, strerror(errno));
1659 +      context_free(tmpcon);
1660 +      context_free(jobcon);
1661 +      return;
1662 +    }
1663 +    cupsdLogJob(job, CUPSD_LOG_DEBUG2, "New spool file context=%s",
1664 +                context_str(tmpcon));
1665 +    context_free(tmpcon);
1666 +    context_free(jobcon);
1667 +  }
1668 +#endif /* WITH_LSPP */
1669 +
1670    job->attrs->state = IPP_IDLE;
1671  
1672    if (ippWriteIO(fp, (ipp_iocb_t)cupsFileWrite, 1, NULL,
1673 @@ -3989,6 +4165,19 @@ get_options(cupsd_job_t *job,            /* I - Jo
1674           banner_page)
1675          continue;
1676  
1677 +#ifdef WITH_LSPP
1678 +     /*
1679 +      * In LSPP mode refuse to honor the page-label
1680 +      */
1681 +      if (is_lspp_config() &&
1682 +          !strcmp(attr->name, "page-label"))
1683 +      {
1684 +        cupsdLogJob(job, CUPSD_LOG_DEBUG,
1685 +                   "Ignoring page-label option due to LSPP mode");
1686 +        continue;
1687 +      }
1688 +#endif /* WITH_LSPP */
1689 +
1690       /*
1691        * Otherwise add them to the list...
1692        */
1693 @@ -4750,6 +4939,18 @@ start_job(cupsd_job_t     *job,          /* I -
1694            cupsd_printer_t *printer)    /* I - Printer to print job */
1695  {
1696    const char   *filename;              /* Support filename */
1697 +#ifdef WITH_LSPP
1698 +  char                 *audit_message = NULL;  /* Audit message string */
1699 +  char                 *printerfile = NULL;    /* Device file pointed to by the printer */
1700 +  security_id_t                clisid;         /* SELinux SID for the client */
1701 +  security_id_t                psid;           /* SELinux SID for the printer */
1702 +  context_t            printercon;     /* Printer's context string */
1703 +  struct stat          printerstat;    /* Printer's stat buffer */
1704 +  security_context_t   devcon;         /* Printer's SELinux context */
1705 +  struct avc_entry_ref avcref;         /* Pointer to the access vector cache */
1706 +  security_class_t     tclass;         /* Object class for the SELinux check */
1707 +  access_vector_t      avr;            /* Access method being requested */
1708 +#endif /* WITH_LSPP */
1709    ipp_attribute_t *cancel_after = ippFindAttribute(job->attrs,
1710                                                    "job-cancel-after",
1711                                                    IPP_TAG_INTEGER);
1712 @@ -4926,6 +5127,113 @@ start_job(cupsd_job_t     *job,         /* I -
1713    fcntl(job->side_pipes[1], F_SETFD,
1714         fcntl(job->side_pipes[1], F_GETFD) | FD_CLOEXEC);
1715  
1716 +#ifdef WITH_LSPP
1717 +  if (is_lspp_config())
1718 +  {
1719 +   /*
1720 +    * Perform an access check before printing, but only if the printer starts with /dev/
1721 +    */
1722 +    printerfile = strstr(printer->device_uri, "/dev/");
1723 +    if (printerfile == NULL && (strncmp(printer->device_uri, "file:/", 6) == 0))
1724 +      printerfile = printer->device_uri + strlen("file:");
1725 +
1726 +    if (printerfile != NULL)
1727 +    {
1728 +      cupsdLogJob(job, CUPSD_LOG_DEBUG,
1729 +                 "Attempting to check access on printer device %s",
1730 +                 printerfile);
1731 +      if (lstat(printerfile, &printerstat) < 0)
1732 +      {
1733 +       if (errno != ENOENT)
1734 +       {
1735 +         cupsdLogJob(job, CUPSD_LOG_ERROR,
1736 +                     "Unable to stat the printer");
1737 +         cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT, NULL);
1738 +         return ;
1739 +       }
1740 +       /*
1741 +        * The printer does not exist, so for now assume it's a FileDevice
1742 +        */
1743 +       tclass = SECCLASS_FILE;
1744 +       avr = FILE__WRITE;
1745 +      }
1746 +      else if (S_ISCHR(printerstat.st_mode))
1747 +      {
1748 +       tclass = SECCLASS_CHR_FILE;
1749 +       avr = CHR_FILE__WRITE;
1750 +      }
1751 +      else if (S_ISREG(printerstat.st_mode))
1752 +      {
1753 +       tclass = SECCLASS_FILE;
1754 +       avr = FILE__WRITE;
1755 +      }
1756 +      else
1757 +      {
1758 +       cupsdLogJob(job, CUPSD_LOG_ERROR,
1759 +                   "StartJob: Printer is not a character device or "
1760 +                   "regular file");
1761 +       cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT, NULL);
1762 +       return ;
1763 +      }
1764 +      static int avc_initialized = 0;
1765 +      if (!avc_initialized++)
1766 +          avc_init("cupsd_dequeue_", NULL, NULL, NULL, NULL);
1767 +      avc_entry_ref_init(&avcref);
1768 +      if (avc_context_to_sid(job->scon, &clisid) != 0)
1769 +      {
1770 +        cupsdLogJob(job, CUPSD_LOG_ERROR,
1771 +                   "Unable to determine the SELinux sid for the job");
1772 +        cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT, NULL);
1773 +        return ;
1774 +      }
1775 +      if (getfilecon(printerfile, &devcon) == -1)
1776 +      {
1777 +        cupsdLogJob(job, CUPSD_LOG_ERROR,
1778 +                   "Unable to get the SELinux context of %s",
1779 +                   printerfile);
1780 +        cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT, NULL);
1781 +        return ;
1782 +      }
1783 +      printercon = context_new(devcon);
1784 +      cupsdLogJob(job, CUPSD_LOG_DEBUG,
1785 +                 "Printer context %s client context %s",
1786 +                 context_str(printercon), job->scon);
1787 +      context_free(printercon);
1788 +
1789 +      if (avc_context_to_sid(devcon, &psid) != 0)
1790 +      {
1791 +        cupsdLogJob(job, CUPSD_LOG_ERROR,
1792 +                   "Unable to determine the SELinux sid for the printer");
1793 +        freecon(devcon);
1794 +        cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT, NULL);
1795 +        return ;
1796 +      }
1797 +      freecon(devcon);
1798 +
1799 +      if (avc_has_perm(clisid, psid, tclass, avr, &avcref, NULL) != 0)
1800 +      {
1801 +       /*
1802 +        * The access check failed, so cancel the job and send an audit message
1803 +        */
1804 +        if (AuditLog != -1)
1805 +        {
1806 +          audit_message = NULL;
1807 +          cupsdSetStringf(&audit_message, "job=%d auid=%u acct=%s obj=%s canceled"
1808 +                                          " unable to access printer=%s", job->id,
1809 +                          job->auid, (job->username)?job->username:"?", job->scon, printer->name);
1810 +          audit_log_user_message(AuditLog, AUDIT_USER_LABELED_EXPORT, audit_message,
1811 +                                 ServerName, NULL, NULL, 0);
1812 +          cupsdClearString(&audit_message);
1813 +        }
1814 +
1815 +        cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT, NULL);
1816 +
1817 +        return ;
1818 +      }
1819 +    }
1820 +  }
1821 +#endif /* WITH_LSPP */
1822 +
1823   /*
1824    * Now start the first file in the job...
1825    */
1826 diff -up cups-2.2.5/scheduler/job.h.lspp cups-2.2.5/scheduler/job.h
1827 --- cups-2.2.5/scheduler/job.h.lspp     2017-10-13 20:22:26.000000000 +0200
1828 +++ cups-2.2.5/scheduler/job.h  2017-10-17 19:06:19.696228498 +0200
1829 @@ -11,6 +11,13 @@
1830   * missing or damaged, see the license at "http://www.cups.org/".
1831   */
1832  
1833 +/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */
1834 +/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */
1835 +
1836 +#ifdef WITH_LSPP
1837 +#include <selinux/selinux.h>
1838 +#endif /* WITH_LSPP */
1839 +
1840  /*
1841   * Constants...
1842   */
1843 @@ -88,6 +95,10 @@ struct cupsd_job_s                   /**** Job request *
1844    int                  progress;       /* Printing progress */
1845    int                  num_keywords;   /* Number of PPD keywords */
1846    cups_option_t                *keywords;      /* PPD keywords */
1847 +#ifdef WITH_LSPP
1848 +  security_context_t   scon;           /* Security context of job */
1849 +  uid_t                        auid;           /* Audit loginuid for this job */
1850 +#endif /* WITH_LSPP */
1851  };
1852  
1853  typedef struct cupsd_joblog_s          /**** Job log message ****/
1854 diff -up cups-2.2.5/scheduler/main.c.lspp cups-2.2.5/scheduler/main.c
1855 --- cups-2.2.5/scheduler/main.c.lspp    2017-10-17 19:06:19.637228989 +0200
1856 +++ cups-2.2.5/scheduler/main.c 2017-10-17 19:08:26.642173026 +0200
1857 @@ -56,6 +56,9 @@
1858  #  include <sys/param.h>
1859  #endif /* HAVE_SYS_PARAM_H */
1860  
1861 +#ifdef WITH_LSPP
1862 +#  include <libaudit.h>
1863 +#endif /* WITH_LSPP */
1864  
1865  /*
1866   * Local functions...
1867 @@ -122,6 +125,9 @@ main(int  argc,                             /* I - Number of comm
1868  #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
1869    struct sigaction     action;         /* Actions for POSIX signals */
1870  #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
1871 +#if WITH_LSPP
1872 +  auditfail_t           failmode;       /* Action for audit_open failure */
1873 +#endif /* WITH_LSPP */
1874  #ifdef __APPLE__
1875    int                  use_sysman = 1; /* Use system management functions? */
1876  #else
1877 @@ -516,6 +522,25 @@ main(int  argc,                            /* I - Number of comm
1878      exit(errno);
1879    }
1880  
1881 +#ifdef WITH_LSPP
1882 +  if ((AuditLog = audit_open()) < 0 )
1883 +  {
1884 +    if (get_auditfail_action(&failmode) == 0)
1885 +    {
1886 +      if (failmode == FAIL_LOG)
1887 +      {
1888 +        cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to connect to audit subsystem.");
1889 +        AuditLog = -1;
1890 +      }
1891 +      else if (failmode == FAIL_TERMINATE)
1892 +      {
1893 +        fprintf(stderr, "cupsd: unable to start auditing, terminating");
1894 +        return -1;
1895 +      }
1896 +    }
1897 +  }
1898 +#endif /* WITH_LSPP */
1899 +
1900   /*
1901    * Let the system know we are busy while we bring up cupsd...
1902    */
1903 @@ -1227,6 +1252,11 @@ main(int  argc,                          /* I - Number of comm
1904  
1905    cupsdStopSelect();
1906  
1907 +#ifdef WITH_LSPP
1908 +  if (AuditLog != -1)
1909 +    audit_close(AuditLog);
1910 +#endif /* WITH_LSPP */
1911 +
1912    return (!stop_scheduler);
1913  }
1914  
1915 diff -up cups-2.2.5/scheduler/printers.c.lspp cups-2.2.5/scheduler/printers.c
1916 --- cups-2.2.5/scheduler/printers.c.lspp        2017-10-17 19:06:19.587229404 +0200
1917 +++ cups-2.2.5/scheduler/printers.c     2017-10-17 19:06:19.697228490 +0200
1918 @@ -11,6 +11,8 @@
1919   * missing or damaged, see the license at "http://www.cups.org/".
1920   */
1921  
1922 +/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */
1923 +
1924  /*
1925   * Include necessary headers...
1926   */
1927 @@ -35,6 +37,10 @@
1928  #  include <asl.h>
1929  #endif /* __APPLE__ */
1930  
1931 +#ifdef WITH_LSPP
1932 +#  include <libaudit.h>
1933 +#  include <selinux/context.h>
1934 +#endif /* WITH_LSPP */
1935  
1936  /*
1937   * Local functions...
1938 @@ -2212,6 +2218,13 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)
1939    ipp_attribute_t *attr;               /* Attribute data */
1940    char         *name,                  /* Current user/group name */
1941                 *filter;                /* Current filter */
1942 +#ifdef WITH_LSPP
1943 +  char         *audit_message;         /* Audit message string */
1944 +  char         *printerfile;           /* Path to a local printer dev */
1945 +  char         *rangestr;              /* Printer's range if its available */
1946 +  security_context_t   devcon;         /* Printer SELinux context */
1947 +  context_t    printercon;             /* context_t for the printer */
1948 +#endif /* WITH_LSPP */
1949  
1950  
1951    DEBUG_printf(("cupsdSetPrinterAttrs: entering name = %s, type = %x\n", p->name,
1952 @@ -2339,6 +2352,45 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)
1953        attr->values[1].string.text = _cupsStrAlloc(Classification ?
1954                                            Classification : p->job_sheets[1]);
1955      }
1956 +#ifdef WITH_LSPP
1957 +    if (AuditLog != -1)
1958 +    {
1959 +      audit_message = NULL;
1960 +      rangestr = NULL;
1961 +      printercon = 0;
1962 +      printerfile = strstr(p->device_uri, "/dev/");
1963 +      if (printerfile == NULL && (strncmp(p->device_uri, "file:/", 6) == 0))
1964 +        printerfile = p->device_uri + strlen("file:");
1965 +
1966 +      if (printerfile != NULL)
1967 +      {
1968 +        if (getfilecon(printerfile, &devcon) == -1)
1969 +        {
1970 +          if(is_selinux_enabled())
1971 +            cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdSetPrinterAttrs: Unable to get printer context");
1972 +        }
1973 +        else
1974 +        {
1975 +          printercon = context_new(devcon);
1976 +          freecon(devcon);
1977 +        }
1978 +      }
1979 +
1980 +      if (printercon && context_range_get(printercon))
1981 +        rangestr = strdup(context_range_get(printercon));
1982 +      else
1983 +        rangestr = strdup("unknown");
1984 +
1985 +      cupsdSetStringf(&audit_message, "printer=%s uri=%s banners=%s,%s range=%s",
1986 +                      p->name, p->sanitized_device_uri, p->job_sheets[0], p->job_sheets[1], rangestr);
1987 +      audit_log_user_message(AuditLog, AUDIT_LABEL_LEVEL_CHANGE, audit_message,
1988 +                             ServerName, NULL, NULL, 1);
1989 +      if (printercon)
1990 +        context_free(printercon);
1991 +      free(rangestr);
1992 +      cupsdClearString(&audit_message);
1993 +    }
1994 +#endif /* WITH_LSPP */
1995    }
1996  
1997    p->raw    = 0;
This page took 0.295662 seconds and 3 git commands to generate.