]> git.pld-linux.org Git - packages/cups.git/blame - cups-lspp.patch
- up to 2.2.8
[packages/cups.git] / cups-lspp.patch
CommitLineData
0f0e09b5
AM
1diff -up cups-2.2.8/config.h.in.lspp cups-2.2.8/config.h.in
2--- cups-2.2.8/config.h.in.lspp 2018-06-05 18:06:54.000000000 +0200
3+++ cups-2.2.8/config.h.in 2018-06-08 17:34:38.682653959 +0200
32548b83 4@@ -730,4 +730,11 @@ static __inline int _cups_abs(int i) { r
b3b50933
AM
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_ */
0f0e09b5
AM
16diff -up cups-2.2.8/config-scripts/cups-lspp.m4.lspp cups-2.2.8/config-scripts/cups-lspp.m4
17--- cups-2.2.8/config-scripts/cups-lspp.m4.lspp 2018-06-08 17:34:38.682653959 +0200
18+++ cups-2.2.8/config-scripts/cups-lspp.m4 2018-06-08 17:34:38.682653959 +0200
b3b50933
AM
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
0f0e09b5
AM
56diff -up cups-2.2.8/configure.ac.lspp cups-2.2.8/configure.ac
57--- cups-2.2.8/configure.ac.lspp 2018-06-05 18:06:54.000000000 +0200
58+++ cups-2.2.8/configure.ac 2018-06-08 17:34:38.682653959 +0200
b3b50933
AM
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=""
0f0e09b5
AM
68diff -up cups-2.2.8/filter/common.c.lspp cups-2.2.8/filter/common.c
69--- cups-2.2.8/filter/common.c.lspp 2018-06-05 18:06:54.000000000 +0200
70+++ cups-2.2.8/filter/common.c 2018-06-08 17:34:38.682653959 +0200
b3b50933
AM
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 /*
0f0e09b5
AM
239diff -up cups-2.2.8/filter/pstops.c.lspp cups-2.2.8/filter/pstops.c
240--- cups-2.2.8/filter/pstops.c.lspp 2018-06-05 18:06:54.000000000 +0200
241+++ cups-2.2.8/filter/pstops.c 2018-06-08 17:34:38.683653951 +0200
b3b50933
AM
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 /*
0f0e09b5
AM
397diff -up cups-2.2.8/Makedefs.in.lspp cups-2.2.8/Makedefs.in
398--- cups-2.2.8/Makedefs.in.lspp 2018-06-05 18:06:54.000000000 +0200
399+++ cups-2.2.8/Makedefs.in 2018-06-08 17:34:38.683653951 +0200
32548b83 400@@ -161,7 +161,7 @@ LDFLAGS = -L../cgi-bin -L../cups -L../f
b3b50933 401 @LDFLAGS@ @RELROFLAGS@ @PIEFLAGS@ $(OPTIM)
32548b83 402 LINKCUPS = @LINKCUPS@ $(LIBGSSAPI) $(DNSSDLIBS) $(SSLLIBS) $(LIBZ)
b3b50933
AM
403 LINKCUPSIMAGE = @LINKCUPSIMAGE@
404-LIBS = $(LINKCUPS) $(COMMONLIBS)
405+LIBS = $(LINKCUPS) $(COMMONLIBS) @LIBAUDIT@ @LIBSELINUX@
406 ONDEMANDFLAGS = @ONDEMANDFLAGS@
407 ONDEMANDLIBS = @ONDEMANDLIBS@
408 OPTIM = @OPTIM@
0f0e09b5
AM
409diff -up cups-2.2.8/scheduler/client.c.lspp cups-2.2.8/scheduler/client.c
410--- cups-2.2.8/scheduler/client.c.lspp 2018-06-05 18:06:54.000000000 +0200
411+++ cups-2.2.8/scheduler/client.c 2018-06-08 17:34:38.729653586 +0200
b3b50933
AM
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 /*
32548b83 433@@ -268,6 +276,59 @@ cupsdAcceptClient(cupsd_listener_t *lis)
b3b50933
AM
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 {
32548b83 493@@ -562,6 +623,13 @@ cupsdReadClient(cupsd_client_t *con) /*
b3b50933
AM
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;
0f0e09b5 507@@ -1938,6 +2006,73 @@ cupsdReadClient(cupsd_client_t *con) /*
b3b50933
AM
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))
0f0e09b5 581@@ -3485,6 +3620,49 @@ is_path_absolute(const char *path) /* I
b3b50933
AM
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.
0f0e09b5
AM
631diff -up cups-2.2.8/scheduler/client.h.lspp cups-2.2.8/scheduler/client.h
632--- cups-2.2.8/scheduler/client.h.lspp 2018-06-05 18:06:54.000000000 +0200
633+++ cups-2.2.8/scheduler/client.h 2018-06-08 17:34:38.729653586 +0200
b3b50933
AM
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 */
0f0e09b5 648@@ -66,6 +73,10 @@ struct cupsd_client_s
b3b50933
AM
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)
0f0e09b5 659@@ -139,6 +150,9 @@ extern void cupsdStartListening(void);
b3b50933
AM
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);
0f0e09b5
AM
669diff -up cups-2.2.8/scheduler/conf.c.lspp cups-2.2.8/scheduler/conf.c
670--- cups-2.2.8/scheduler/conf.c.lspp 2018-06-08 17:34:38.676654007 +0200
671+++ cups-2.2.8/scheduler/conf.c 2018-06-08 17:34:38.730653578 +0200
b3b50933
AM
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[] =
32548b83 693@@ -544,6 +551,9 @@ cupsdReadConfiguration(void)
b3b50933
AM
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 /*
0f0e09b5 703@@ -863,6 +873,25 @@ cupsdReadConfiguration(void)
b3b50933
AM
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
0f0e09b5 729@@ -1274,7 +1303,19 @@ cupsdReadConfiguration(void)
b3b50933
AM
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...
0f0e09b5 749@@ -3832,6 +3873,18 @@ read_location(cups_file_t *fp, /* I - C
b3b50933
AM
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.
0f0e09b5
AM
768diff -up cups-2.2.8/scheduler/conf.h.lspp cups-2.2.8/scheduler/conf.h
769--- cups-2.2.8/scheduler/conf.h.lspp 2018-06-05 18:06:54.000000000 +0200
770+++ cups-2.2.8/scheduler/conf.h 2018-06-08 17:34:38.730653578 +0200
771@@ -246,6 +246,13 @@ VAR char *ServerKeychain VALUE(NULL);
b3b50933
AM
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 */
0f0e09b5 785@@ -264,6 +271,9 @@ VAR int HaveServerCreds VALUE(0);
b3b50933
AM
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...
0f0e09b5
AM
795diff -up cups-2.2.8/scheduler/cupsd.h.lspp cups-2.2.8/scheduler/cupsd.h
796--- cups-2.2.8/scheduler/cupsd.h.lspp 2018-06-05 18:06:54.000000000 +0200
797+++ cups-2.2.8/scheduler/cupsd.h 2018-06-08 17:34:38.730653578 +0200
b3b50933
AM
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 */
0f0e09b5
AM
829diff -up cups-2.2.8/scheduler/ipp.c.lspp cups-2.2.8/scheduler/ipp.c
830--- cups-2.2.8/scheduler/ipp.c.lspp 2018-06-08 17:34:38.652654197 +0200
831+++ cups-2.2.8/scheduler/ipp.c 2018-06-08 17:37:19.166378937 +0200
b3b50933 832@@ -14,6 +14,9 @@
32548b83 833 * missing or damaged, see the license at "http://www.cups.org/".
b3b50933
AM
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,
0f0e09b5 867@@ -1250,6 +1264,21 @@ add_job(cupsd_client_t *con, /* I - Cl
b3b50933
AM
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))",
0f0e09b5
AM
889@@ -1578,6 +1607,106 @@ add_job(cupsd_client_t *con, /* I - Cl
890
891 attr = ippFindAttribute(con->request, "requesting-user-name", IPP_TAG_NAME);
b3b50933
AM
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,
0f0e09b5 996@@ -1586,6 +1715,32 @@ add_job(cupsd_client_t *con, /* I - Cl
b3b50933
AM
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;
0f0e09b5 1029@@ -1773,6 +1928,29 @@ add_job(cupsd_client_t *con, /* I - Cl
b3b50933
AM
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
0f0e09b5 1059@@ -1803,6 +1981,9 @@ add_job(cupsd_client_t *con, /* I - Cl
b3b50933
AM
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,
0f0e09b5 1069@@ -1821,6 +2002,9 @@ add_job(cupsd_client_t *con, /* I - Cl
b3b50933
AM
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") &&
0f0e09b5 1079@@ -1841,6 +2025,9 @@ add_job(cupsd_client_t *con, /* I - Cl
b3b50933
AM
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) &&
0f0e09b5 1089@@ -1881,8 +2068,52 @@ add_job(cupsd_client_t *con, /* I - Cl
b3b50933
AM
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 */
0f0e09b5 1096+ }
b3b50933
AM
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+ }
0f0e09b5 1130 }
b3b50933
AM
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...
0f0e09b5 1142@@ -3656,6 +3887,128 @@ check_rss_recipient(
b3b50933
AM
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 */
0f0e09b5 1271@@ -4112,6 +4465,15 @@ copy_banner(cupsd_client_t *con, /* I -
b3b50933
AM
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,
0f0e09b5 1287@@ -4147,6 +4509,85 @@ copy_banner(cupsd_client_t *con, /* I -
b3b50933
AM
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...
0f0e09b5 1373@@ -4241,6 +4682,24 @@ copy_banner(cupsd_client_t *con, /* I -
b3b50933
AM
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);
0f0e09b5 1398@@ -6480,6 +6939,22 @@ get_job_attrs(cupsd_client_t *con, /* I
b3b50933
AM
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 */
0f0e09b5 1421@@ -6877,6 +7352,11 @@ get_jobs(cupsd_client_t *con, /* I - C
b3b50933
AM
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
0f0e09b5 1433@@ -11475,6 +11955,11 @@ validate_user(cupsd_job_t *job, /* I
b3b50933
AM
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 */
0f0e09b5
AM
1445diff -up cups-2.2.8/scheduler/job.c.lspp cups-2.2.8/scheduler/job.c
1446--- cups-2.2.8/scheduler/job.c.lspp 2018-06-08 17:34:38.657654158 +0200
1447+++ cups-2.2.8/scheduler/job.c 2018-06-08 17:34:38.733653554 +0200
b3b50933 1448@@ -11,6 +11,9 @@
32548b83 1449 * missing or damaged, see the license at "http://www.cups.org/".
b3b50933
AM
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
32548b83 1473@@ -547,6 +558,14 @@ cupsdContinueJob(cupsd_job_t *job) /* I
b3b50933
AM
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,
32548b83 1488@@ -1083,6 +1102,67 @@ cupsdContinueJob(cupsd_job_t *job) /* I
b3b50933
AM
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",
0f0e09b5 1556@@ -1862,6 +1942,22 @@ cupsdLoadJob(cupsd_job_t *job) /* I - J
b3b50933
AM
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);
0f0e09b5 1579@@ -2275,6 +2371,14 @@ cupsdSaveJob(cupsd_job_t *job) /* I - J
b3b50933
AM
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",
0f0e09b5 1594@@ -2297,6 +2401,78 @@ cupsdSaveJob(cupsd_job_t *job) /* I - J
b3b50933
AM
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,
0f0e09b5 1673@@ -3943,6 +4119,19 @@ get_options(cupsd_job_t *job, /* I - Jo
b3b50933
AM
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 */
0f0e09b5 1693@@ -4704,6 +4893,18 @@ start_job(cupsd_job_t *job, /* I -
b3b50933
AM
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);
0f0e09b5 1712@@ -4892,6 +5093,113 @@ start_job(cupsd_job_t *job, /* I -
b3b50933
AM
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 */
0f0e09b5
AM
1826diff -up cups-2.2.8/scheduler/job.h.lspp cups-2.2.8/scheduler/job.h
1827--- cups-2.2.8/scheduler/job.h.lspp 2018-06-05 18:06:54.000000000 +0200
1828+++ cups-2.2.8/scheduler/job.h 2018-06-08 17:34:38.733653554 +0200
b3b50933 1829@@ -11,6 +11,13 @@
32548b83 1830 * missing or damaged, see the license at "http://www.cups.org/".
b3b50933
AM
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 ****/
0f0e09b5
AM
1854diff -up cups-2.2.8/scheduler/main.c.lspp cups-2.2.8/scheduler/main.c
1855--- cups-2.2.8/scheduler/main.c.lspp 2018-06-08 17:34:38.663654110 +0200
1856+++ cups-2.2.8/scheduler/main.c 2018-06-08 17:34:38.734653546 +0200
b3b50933
AM
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
0f0e09b5 1877@@ -495,6 +501,25 @@ main(int argc, /* I - Number of comm
b3b50933
AM
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 /*
32548b83 1901 * Let the system know we are busy while we bring up cupsd...
b3b50933 1902 */
0f0e09b5 1903@@ -1188,6 +1213,11 @@ main(int argc, /* I - Number of comm
b3b50933
AM
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
0f0e09b5
AM
1915diff -up cups-2.2.8/scheduler/printers.c.lspp cups-2.2.8/scheduler/printers.c
1916--- cups-2.2.8/scheduler/printers.c.lspp 2018-06-05 18:06:54.000000000 +0200
1917+++ cups-2.2.8/scheduler/printers.c 2018-06-08 17:34:38.734653546 +0200
b3b50933 1918@@ -11,6 +11,8 @@
32548b83 1919 * missing or damaged, see the license at "http://www.cups.org/".
b3b50933
AM
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...
0f0e09b5 1938@@ -2202,6 +2208,13 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)
b3b50933
AM
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,
0f0e09b5 1952@@ -2329,6 +2342,45 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)
b3b50933
AM
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.376153 seconds and 4 git commands to generate.