]> git.pld-linux.org Git - packages/cups.git/blame - cups-lspp.patch
Release 4 (by relup.sh)
[packages/cups.git] / cups-lspp.patch
CommitLineData
5565574e
AM
1diff -up cups-2.3.0/config.h.in.lspp cups-2.3.0/config.h.in
2--- cups-2.3.0/config.h.in.lspp 2019-08-23 17:19:38.000000000 +0200
3+++ cups-2.3.0/config.h.in 2019-10-07 12:24:43.058597468 +0200
4@@ -684,4 +684,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_ */
5565574e
AM
16diff -up cups-2.3.0/config-scripts/cups-lspp.m4.lspp cups-2.3.0/config-scripts/cups-lspp.m4
17--- cups-2.3.0/config-scripts/cups-lspp.m4.lspp 2019-10-07 12:24:43.058597468 +0200
18+++ cups-2.3.0/config-scripts/cups-lspp.m4 2019-10-07 12:24:43.058597468 +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
5565574e
AM
56diff -up cups-2.3.0/configure.ac.lspp cups-2.3.0/configure.ac
57--- cups-2.3.0/configure.ac.lspp 2019-10-07 12:24:43.058597468 +0200
58+++ cups-2.3.0/configure.ac 2019-10-07 12:39:20.122546282 +0200
59@@ -34,6 +34,8 @@ sinclude(config-scripts/cups-dnssd.m4)
60 sinclude(config-scripts/cups-startup.m4)
b3b50933 61 sinclude(config-scripts/cups-defaults.m4)
b3b50933
AM
62
63+sinclude(config-scripts/cups-lspp.m4)
64+
65 INSTALL_LANGUAGES=""
66 UNINSTALL_LANGUAGES=""
67 LANGFILES=""
5565574e
AM
68diff -up cups-2.3.0/filter/common.c.lspp cups-2.3.0/filter/common.c
69--- cups-2.3.0/filter/common.c.lspp 2019-08-23 17:19:38.000000000 +0200
70+++ cups-2.3.0/filter/common.c 2019-10-07 12:24:43.059597461 +0200
71@@ -11,6 +11,12 @@
b3b50933
AM
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
5565574e 84@@ -293,6 +299,18 @@ WriteLabelProlog(const char *label, /* I
b3b50933
AM
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 /*
5565574e 103@@ -315,6 +333,124 @@ WriteLabelProlog(const char *label, /* I
b3b50933
AM
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 */
5565574e 228@@ -395,7 +531,10 @@ WriteLabelProlog(const char *label, /* I
b3b50933
AM
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 /*
5565574e
AM
239diff -up cups-2.3.0/filter/pstops.c.lspp cups-2.3.0/filter/pstops.c
240--- cups-2.3.0/filter/pstops.c.lspp 2019-08-23 17:19:38.000000000 +0200
241+++ cups-2.3.0/filter/pstops.c 2019-10-07 12:24:43.059597461 +0200
242@@ -3170,6 +3170,18 @@ write_label_prolog(pstops_doc_t *doc, /*
b3b50933
AM
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 /*
5565574e 261@@ -3192,6 +3204,124 @@ write_label_prolog(pstops_doc_t *doc, /*
b3b50933
AM
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 */
5565574e 386@@ -3270,7 +3400,10 @@ write_label_prolog(pstops_doc_t *doc, /*
b3b50933
AM
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 /*
5565574e
AM
397diff -up cups-2.3.0/Makedefs.in.lspp cups-2.3.0/Makedefs.in
398--- cups-2.3.0/Makedefs.in.lspp 2019-10-07 12:24:43.059597461 +0200
399+++ cups-2.3.0/Makedefs.in 2019-10-07 12:37:19.200565805 +0200
400@@ -174,7 +174,7 @@ IPPFIND_MAN = @IPPFIND_MAN@
401 LDFLAGS = @LDFLAGS@
402 LINKCUPS = @LINKCUPS@
403 LINKCUPSSTATIC = ../cups/$(LIBCUPSSTATIC) $(LIBS)
404-LIBS = $(LIBGSSAPI) $(DNSSDLIBS) $(SSLLIBS) $(LIBZ) $(COMMONLIBS)
405+LIBS = $(LIBGSSAPI) $(DNSSDLIBS) $(SSLLIBS) $(LIBZ) $(COMMONLIBS) @LIBAUDIT@ @LIBSELINUX@
b3b50933
AM
406 ONDEMANDFLAGS = @ONDEMANDFLAGS@
407 ONDEMANDLIBS = @ONDEMANDLIBS@
408 OPTIM = @OPTIM@
5565574e
AM
409diff -up cups-2.3.0/scheduler/client.c.lspp cups-2.3.0/scheduler/client.c
410--- cups-2.3.0/scheduler/client.c.lspp 2019-08-23 17:19:38.000000000 +0200
411+++ cups-2.3.0/scheduler/client.c 2019-10-07 12:33:10.459693580 +0200
412@@ -19,12 +19,20 @@
b3b50933
AM
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 /*
5565574e 433@@ -265,6 +273,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 {
5565574e
AM
493@@ -558,6 +619,13 @@ cupsdReadClient(cupsd_client_t *con) /*
494 struct stat filestats; /* File information */
b3b50933 495 mime_type_t *type; /* MIME type of file */
b3b50933
AM
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;
5565574e 507@@ -1679,6 +1747,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))
5565574e 581@@ -3174,6 +3309,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.
5565574e
AM
631diff -up cups-2.3.0/scheduler/client.h.lspp cups-2.3.0/scheduler/client.h
632--- cups-2.3.0/scheduler/client.h.lspp 2019-08-23 17:19:38.000000000 +0200
633+++ cups-2.3.0/scheduler/client.h 2019-10-07 12:24:43.113597079 +0200
634@@ -13,6 +13,13 @@
b3b50933
AM
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 */
5565574e 648@@ -63,6 +70,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)
5565574e 659@@ -136,6 +147,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);
5565574e
AM
669diff -up cups-2.3.0/scheduler/conf.c.lspp cups-2.3.0/scheduler/conf.c
670--- cups-2.3.0/scheduler/conf.c.lspp 2019-10-07 12:24:43.049597531 +0200
671+++ cups-2.3.0/scheduler/conf.c 2019-10-07 12:24:43.113597079 +0200
672@@ -37,6 +37,9 @@
b3b50933
AM
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 /*
5565574e 703@@ -864,6 +874,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
5565574e 729@@ -1275,7 +1304,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...
5565574e 749@@ -3830,6 +3871,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.
5565574e
AM
768diff -up cups-2.3.0/scheduler/conf.h.lspp cups-2.3.0/scheduler/conf.h
769--- cups-2.3.0/scheduler/conf.h.lspp 2019-08-23 17:19:38.000000000 +0200
770+++ cups-2.3.0/scheduler/conf.h 2019-10-07 12:24:43.113597079 +0200
771@@ -243,6 +243,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 */
5565574e 785@@ -261,6 +268,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...
5565574e
AM
795diff -up cups-2.3.0/scheduler/cupsd.h.lspp cups-2.3.0/scheduler/cupsd.h
796--- cups-2.3.0/scheduler/cupsd.h.lspp 2019-08-23 17:19:38.000000000 +0200
797+++ cups-2.3.0/scheduler/cupsd.h 2019-10-07 12:31:38.458480578 +0200
798@@ -8,6 +8,8 @@
799 * information.
b3b50933
AM
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.
5565574e 807@@ -33,6 +35,14 @@
b3b50933 808 # include <unistd.h>
5565574e 809 #endif /* _WIN32 */
b3b50933
AM
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)
5565574e
AM
822diff -up cups-2.3.0/scheduler/ipp.c.lspp cups-2.3.0/scheduler/ipp.c
823--- cups-2.3.0/scheduler/ipp.c.lspp 2019-10-07 12:24:43.016597764 +0200
824+++ cups-2.3.0/scheduler/ipp.c 2019-10-07 12:31:01.243798920 +0200
825@@ -11,6 +11,9 @@
826 * information.
b3b50933
AM
827 */
828
829+/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */
830+/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */
831+
832 /*
833 * Include necessary headers...
834 */
5565574e
AM
835@@ -27,6 +30,14 @@ extern int mbr_group_name_to_uuid(const
836 extern int mbr_check_membership_by_id(uuid_t user, gid_t group, int* ismember);
b3b50933
AM
837 #endif /* __APPLE__ */
838
839+#ifdef WITH_LSPP
840+#include <libaudit.h>
841+#include <selinux/selinux.h>
842+#include <selinux/context.h>
843+#include <selinux/avc.h>
844+#include <selinux/flask.h>
845+#include <selinux/av_permissions.h>
846+#endif /* WITH_LSPP */
847
848 /*
849 * Local functions...
5565574e 850@@ -51,6 +62,9 @@ static void cancel_all_jobs(cupsd_client
b3b50933
AM
851 static void cancel_job(cupsd_client_t *con, ipp_attribute_t *uri);
852 static void cancel_subscription(cupsd_client_t *con, int id);
853 static int check_rss_recipient(const char *recipient);
854+#ifdef WITH_LSPP
855+static int check_context(cupsd_client_t *con, cupsd_job_t *job);
856+#endif /* WITH_LSPP */
857 static int check_quotas(cupsd_client_t *con, cupsd_printer_t *p);
858 static void close_job(cupsd_client_t *con, ipp_attribute_t *uri);
859 static void copy_attrs(ipp_t *to, ipp_t *from, cups_array_t *ra,
5565574e 860@@ -1240,6 +1254,21 @@ add_job(cupsd_client_t *con, /* I - Cl
b3b50933
AM
861 "time-at-creation",
862 "time-at-processing"
863 };
864+#ifdef WITH_LSPP
865+ char *audit_message; /* Audit message string */
866+ char *printerfile; /* device file pointed to by the printer */
867+ char *userheader = NULL; /* User supplied job-sheets[0] */
868+ char *userfooter = NULL; /* User supplied job-sheets[1] */
869+ int override = 0; /* Was a banner overrode on a job */
870+ security_id_t clisid; /* SELinux SID for the client */
871+ security_id_t psid; /* SELinux SID for the printer */
872+ context_t printercon; /* Printer's context string */
873+ struct stat printerstat; /* Printer's stat buffer */
874+ security_context_t devcon; /* Printer's SELinux context */
875+ struct avc_entry_ref avcref; /* Pointer to the access vector cache */
876+ security_class_t tclass; /* Object class for the SELinux check */
877+ access_vector_t avr; /* Access method being requested */
878+#endif /* WITH_LSPP */
879
880
881 cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_job(%p[%d], %p(%s), %p(%s/%s))",
5565574e 882@@ -1568,6 +1597,106 @@ add_job(cupsd_client_t *con, /* I - Cl
0f0e09b5
AM
883
884 attr = ippFindAttribute(con->request, "requesting-user-name", IPP_TAG_NAME);
b3b50933
AM
885
886+#ifdef WITH_LSPP
887+ if (is_lspp_config())
888+ {
889+ if (!con->scon || strncmp(con->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) == 0)
890+ {
891+ cupsdLogMessage(CUPSD_LOG_ERROR, "add_job: missing classification for connection \'%s\'!", printer->name);
892+ send_ipp_status(con, IPP_INTERNAL_ERROR, _("Missing required security attributes."));
893+ return (NULL);
894+ }
895+
896+ /*
897+ * Perform an access check so that if the user gets feedback at enqueue time
898+ */
899+
900+ printerfile = strstr(printer->device_uri, "/dev/");
901+ if (printerfile == NULL && (strncmp(printer->device_uri, "file:/", 6) == 0))
902+ printerfile = printer->device_uri + strlen("file:");
903+
904+ if (printerfile != NULL)
905+ {
906+ cupsdLogMessage(CUPSD_LOG_DEBUG, "add_job: Attempting an access check on printer device %s",
907+ printerfile);
908+
909+ if (lstat(printerfile, &printerstat) < 0)
910+ {
911+ if (errno != ENOENT)
912+ {
913+ send_ipp_status(con, IPP_NOT_AUTHORIZED, _("Unable to stat the printer"));
914+ return (NULL);
915+ }
916+ /*
917+ * The printer does not exist, so for now assume it's a FileDevice
918+ */
919+ tclass = SECCLASS_FILE;
920+ avr = FILE__WRITE;
921+ }
922+ else if (S_ISCHR(printerstat.st_mode))
923+ {
924+ tclass = SECCLASS_CHR_FILE;
925+ avr = CHR_FILE__WRITE;
926+ }
927+ else if (S_ISREG(printerstat.st_mode))
928+ {
929+ tclass = SECCLASS_FILE;
930+ avr = FILE__WRITE;
931+ }
932+ else
933+ {
934+ send_ipp_status(con, IPP_NOT_AUTHORIZED, _("Printer is not a character device or regular file"));
935+ return (NULL);
936+ }
937+ static int avc_initialized = 0;
938+ if (!avc_initialized++)
939+ avc_init("cupsd_enqueue_", NULL, NULL, NULL, NULL);
940+ avc_entry_ref_init(&avcref);
941+ if (avc_context_to_sid(con->scon, &clisid) != 0)
942+ {
943+ send_ipp_status(con, IPP_NOT_AUTHORIZED, _("Unable to get the SELinux sid of the client"));
944+ return (NULL);
945+ }
946+ if (getfilecon(printerfile, &devcon) == -1)
947+ {
948+ send_ipp_status(con, IPP_NOT_AUTHORIZED, _("Unable to get the SELinux context of the printer"));
949+ return (NULL);
950+ }
951+ printercon = context_new(devcon);
952+ cupsdLogMessage(CUPSD_LOG_DEBUG, "add_job: printer context %s client context %s",
953+ context_str(printercon), con->scon);
954+ context_free(printercon);
955+
956+ if (avc_context_to_sid(devcon, &psid) != 0)
957+ {
958+ send_ipp_status(con, IPP_NOT_AUTHORIZED, _("Unable to get the SELinux sid of the printer"));
959+ freecon(devcon);
960+ return (NULL);
961+ }
962+ freecon(devcon);
963+ if (avc_has_perm(clisid, psid, tclass, avr, &avcref, NULL) != 0)
964+ {
965+ /*
966+ * The access check failed, so cancel the job and send an audit message
967+ */
968+ if (AuditLog != -1)
969+ {
970+ audit_message = NULL;
971+ cupsdSetStringf(&audit_message, "job=? auid=%u acct=%s obj=%s refused"
972+ " unable to access printer=%s", con->auid,
973+ con->username, con->scon, printer->name);
974+ audit_log_user_message(AuditLog, AUDIT_USER_LABELED_EXPORT, audit_message,
975+ ServerName, NULL, NULL, 0);
976+ cupsdClearString(&audit_message);
977+ }
978+
979+ send_ipp_status(con, IPP_NOT_AUTHORIZED, _("SELinux prohibits access to the printer"));
980+ return (NULL);
981+ }
982+ }
983+ }
984+#endif /* WITH_LSPP */
985+
986 if ((job = cupsdAddJob(priority, printer->name)) == NULL)
987 {
988 send_ipp_status(con, IPP_INTERNAL_ERROR,
5565574e 989@@ -1576,6 +1705,32 @@ add_job(cupsd_client_t *con, /* I - Cl
b3b50933
AM
990 return (NULL);
991 }
992
993+#ifdef WITH_LSPP
994+ if (is_lspp_config())
995+ {
996+ /*
997+ * duplicate the security context and auid of the connection into the job structure
998+ */
999+ job->scon = strdup(con->scon);
1000+ job->auid = con->auid;
1001+
1002+ /*
1003+ * add the security context to the request so that on a restart the security
1004+ * attributes will be able to be restored
1005+ */
1006+ ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_NAME, "security-context",
1007+ NULL, job->scon);
1008+ }
1009+ else
1010+ {
1011+ /*
1012+ * Fill in the security context of the job as unlabeled
1013+ */
1014+ cupsdLogMessage(CUPSD_LOG_DEBUG, "add_job: setting context of job to %s", UNKNOWN_SL);
1015+ cupsdSetString(&job->scon, UNKNOWN_SL);
1016+ }
1017+#endif /* WITH_LSPP */
1018+
1019 job->dtype = printer->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE);
1020 job->attrs = con->request;
1021 job->dirty = 1;
5565574e 1022@@ -1763,6 +1918,29 @@ add_job(cupsd_client_t *con, /* I - Cl
b3b50933
AM
1023 ippSetString(job->attrs, &attr, 0, printer->job_sheets[0]);
1024 ippSetString(job->attrs, &attr, 1, printer->job_sheets[1]);
1025 }
1026+#ifdef WITH_LSPP
1027+ else
1028+ {
1029+ /*
1030+ * The option was present, so capture the user supplied strings
1031+ */
1032+ userheader = strdup(attr->values[0].string.text);
1033+
1034+ if (attr->num_values > 1)
1035+ userfooter = strdup(attr->values[1].string.text);
1036+
1037+ if (Classification != NULL && (strcmp(userheader, Classification) == 0)
1038+ && userfooter &&(strcmp(userfooter, Classification) == 0))
1039+ {
1040+ /*
1041+ * Since both values are Classification, the user is not trying to Override
1042+ */
1043+ free(userheader);
1044+ if (userfooter) free(userfooter);
1045+ userheader = userfooter = NULL;
1046+ }
1047+ }
1048+#endif /* WITH_LSPP */
1049
1050 job->job_sheets = attr;
1051
5565574e 1052@@ -1793,6 +1971,9 @@ add_job(cupsd_client_t *con, /* I - Cl
b3b50933
AM
1053 "job-sheets=\"%s,none\", "
1054 "job-originating-user-name=\"%s\"",
1055 Classification, job->username);
1056+#ifdef WITH_LSPP
1057+ override = 1;
1058+#endif /* WITH_LSPP */
1059 }
1060 else if (attr->num_values == 2 &&
1061 strcmp(attr->values[0].string.text,
5565574e 1062@@ -1811,6 +1992,9 @@ add_job(cupsd_client_t *con, /* I - Cl
b3b50933
AM
1063 "job-originating-user-name=\"%s\"",
1064 attr->values[0].string.text,
1065 attr->values[1].string.text, job->username);
1066+#ifdef WITH_LSPP
1067+ override = 1;
1068+#endif /* WITH_LSPP */
1069 }
1070 else if (strcmp(attr->values[0].string.text, Classification) &&
1071 strcmp(attr->values[0].string.text, "none") &&
5565574e 1072@@ -1831,6 +2015,9 @@ add_job(cupsd_client_t *con, /* I - Cl
b3b50933
AM
1073 "job-originating-user-name=\"%s\"",
1074 attr->values[0].string.text,
1075 attr->values[1].string.text, job->username);
1076+#ifdef WITH_LSPP
1077+ override = 1;
1078+#endif /* WITH_LSPP */
1079 }
1080 }
1081 else if (strcmp(attr->values[0].string.text, Classification) &&
5565574e 1082@@ -1871,8 +2058,52 @@ add_job(cupsd_client_t *con, /* I - Cl
b3b50933
AM
1083 "job-sheets=\"%s\", "
1084 "job-originating-user-name=\"%s\"",
1085 Classification, job->username);
1086+#ifdef WITH_LSPP
1087+ override = 1;
1088+#endif /* WITH_LSPP */
0f0e09b5 1089+ }
b3b50933
AM
1090+#ifdef WITH_LSPP
1091+ if (is_lspp_config() && AuditLog != -1)
1092+ {
1093+ audit_message = NULL;
1094+
1095+ if (userheader || userfooter)
1096+ {
1097+ if (!override)
1098+ {
1099+ /*
1100+ * The user overrode the banner, so audit it
1101+ */
1102+ cupsdSetStringf(&audit_message, "job=%d user supplied job-sheets=%s,%s"
1103+ " using banners=%s,%s", job->id, userheader,
1104+ userfooter, attr->values[0].string.text,
1105+ (attr->num_values > 1) ? attr->values[1].string.text : "(null)");
1106+ audit_log_user_message(AuditLog, AUDIT_LABEL_OVERRIDE, audit_message,
1107+ ServerName, NULL, NULL, 1);
1108+ }
1109+ else
1110+ {
1111+ /*
1112+ * The user tried to override the banner, audit the failure
1113+ */
1114+ cupsdSetStringf(&audit_message, "job=%d user supplied job-sheets=%s,%s"
1115+ " ignored banners=%s,%s", job->id, userheader,
1116+ userfooter, attr->values[0].string.text,
1117+ (attr->num_values > 1) ? attr->values[1].string.text : "(null)");
1118+ audit_log_user_message(AuditLog, AUDIT_LABEL_OVERRIDE, audit_message,
1119+ ServerName, NULL, NULL, 0);
1120+ }
1121+ cupsdClearString(&audit_message);
1122+ }
0f0e09b5 1123 }
b3b50933
AM
1124+
1125+ if (userheader)
1126+ free(userheader);
1127+ if (userfooter)
1128+ free(userfooter);
1129+#endif /* WITH_LSPP */
1130 }
1131+
1132
1133 /*
1134 * See if we need to add the starting sheet...
5565574e 1135@@ -3648,6 +3879,128 @@ check_rss_recipient(
b3b50933
AM
1136 }
1137
1138
1139+#ifdef WITH_LSPP
1140+/*
1141+ * 'check_context()' - Check SELinux security context of a user and job
1142+ */
1143+
1144+static int /* O - 1 if OK, 0 if not, -1 on error */
1145+check_context(cupsd_client_t *con, /* I - Client connection */
1146+ cupsd_job_t *job) /* I - Job */
1147+{
1148+ int enforcing; /* is SELinux in enforcing mode */
1149+ char filename[1024]; /* Filename of the spool file */
1150+ security_id_t clisid; /* SELinux SID of the client */
1151+ security_id_t jobsid; /* SELinux SID of the job */
1152+ security_id_t filesid; /* SELinux SID of the spool file */
1153+ struct avc_entry_ref avcref; /* AVC entry cache pointer */
1154+ security_class_t tclass; /* SELinux security class */
1155+ access_vector_t avr; /* SELinux access being queried */
1156+ security_context_t spoolfilecon; /* SELinux context of the spool file */
1157+
1158+
1159+ /*
1160+ * Validate the input to be sure there are contexts to work with...
1161+ */
1162+
1163+ if (con->scon == NULL || job->scon == NULL
1164+ || strncmp(con->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) == 0
1165+ || strncmp(job->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) == 0)
1166+ return -1;
1167+
1168+ if ((enforcing = security_getenforce()) == -1)
1169+ {
1170+ cupsdLogJob(job, CUPSD_LOG_ERROR,
1171+ "Error while determining SELinux enforcement");
1172+ return -1;
1173+ }
1174+ cupsdLogJob(job, CUPSD_LOG_DEBUG,
1175+ "check_context: client context %s job context %s",
1176+ con->scon, job->scon);
1177+
1178+
1179+ /*
1180+ * Initialize the avc engine...
1181+ */
1182+
1183+ static int avc_initialized = 0;
1184+ if (! avc_initialized++)
1185+ {
1186+ if (avc_init("cupsd", NULL, NULL, NULL, NULL) < 0)
1187+ {
1188+ cupsdLogJob(job, CUPSD_LOG_ERROR, "check_context: unable avc_init");
1189+ return -1;
1190+ }
1191+ }
1192+ if (avc_context_to_sid(con->scon, &clisid) != 0)
1193+ {
1194+ cupsdLogJob(job, CUPSD_LOG_ERROR,
1195+ "check_context: unable to convert %s to SELinux sid",
1196+ con->scon);
1197+ return -1;
1198+ }
1199+ if (avc_context_to_sid(job->scon, &jobsid) != 0)
1200+ {
1201+ cupsdLogJob(job, CUPSD_LOG_ERROR,
1202+ "check_context: unable to convert %s to SELinux sid",
1203+ job->scon);
1204+ return -1;
1205+ }
1206+ avc_entry_ref_init(&avcref);
1207+ tclass = SECCLASS_FILE;
1208+ avr = FILE__READ;
1209+
1210+ /*
1211+ * Perform the check with the client as the subject, first with the job as the object
1212+ * if that fails then with the spool file as the object...
1213+ */
1214+
1215+ if (avc_has_perm_noaudit(clisid, jobsid, tclass, avr, &avcref, NULL) != 0)
1216+ {
1217+ cupsdLogJob(job, CUPSD_LOG_INFO,
1218+ "check_context: SELinux denied access "
1219+ "based on the client context");
1220+
1221+ snprintf(filename, sizeof(filename), "%s/c%05d", RequestRoot, job->id);
1222+ if (getfilecon(filename, &spoolfilecon) == -1)
1223+ {
1224+ cupsdLogJob(job, CUPSD_LOG_ERROR,
1225+ "check_context: Unable to get spoolfile context");
1226+ return -1;
1227+ }
1228+ if (avc_context_to_sid(spoolfilecon, &filesid) != 0)
1229+ {
1230+ cupsdLogJob(job, CUPSD_LOG_ERROR,
1231+ "check_context: Unable to determine the "
1232+ "SELinux sid for the spool file");
1233+ freecon(spoolfilecon);
1234+ return -1;
1235+ }
1236+ freecon(spoolfilecon);
1237+ if (avc_has_perm_noaudit(clisid, filesid, tclass, avr, &avcref, NULL) != 0)
1238+ {
1239+ cupsdLogJob(job, CUPSD_LOG_INFO,
1240+ "check_context: SELinux denied access to the spool file");
1241+ return 0;
1242+ }
1243+ cupsdLogJob(job, CUPSD_LOG_INFO,
1244+ "check_context: SELinux allowed access to the spool file");
1245+ return 1;
1246+ }
1247+ else
1248+ if (enforcing == 0)
1249+ cupsdLogJob(job, CUPSD_LOG_INFO,
1250+ "check_context: allowing operation due to permissive mode");
1251+ else
1252+ cupsdLogJob(job, CUPSD_LOG_INFO,
1253+ "check_context: SELinux allowed access based on the "
1254+ "client context");
1255+
1256+ return 1;
1257+}
1258+#endif /* WITH_LSPP */
1259+
1260+
1261 /*
1262 * 'check_quotas()' - Check quotas for a printer and user.
1263 */
5565574e 1264@@ -4103,6 +4456,15 @@ copy_banner(cupsd_client_t *con, /* I -
b3b50933
AM
1265 char attrname[255], /* Name of attribute */
1266 *s; /* Pointer into name */
1267 ipp_attribute_t *attr; /* Attribute */
1268+#ifdef WITH_LSPP
1269+ const char *mls_label; /* SL of print job */
1270+ char *jobrange; /* SELinux sensitivity range */
1271+ char *jobclearance; /* SELinux low end clearance */
1272+ context_t jobcon; /* SELinux context of the job */
1273+ context_t tmpcon; /* Temp context to set the level */
1274+ security_context_t spoolcon; /* Context of the file in the spool */
1275+#endif /* WITH_LSPP */
1276+
1277
1278
1279 cupsdLogMessage(CUPSD_LOG_DEBUG2,
5565574e 1280@@ -4138,6 +4500,85 @@ copy_banner(cupsd_client_t *con, /* I -
b3b50933
AM
1281
1282 fchmod(cupsFileNumber(out), 0640);
1283 fchown(cupsFileNumber(out), RunUser, Group);
1284+#ifdef WITH_LSPP
1285+ if (job->scon != NULL &&
1286+ strncmp(job->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) != 0)
1287+ {
1288+ if (getfilecon(filename, &spoolcon) == -1)
1289+ {
1290+ cupsdLogJob(job, CUPSD_LOG_ERROR,
1291+ "Unable to get the context of the banner file %s - %s",
1292+ filename, strerror(errno));
1293+ job->num_files --;
1294+ return (0);
1295+ }
1296+ tmpcon = context_new(spoolcon);
1297+ jobcon = context_new(job->scon);
1298+ freecon(spoolcon);
1299+ if (!tmpcon || !jobcon)
1300+ {
1301+ if (tmpcon)
1302+ context_free(tmpcon);
1303+ if (jobcon)
1304+ context_free(jobcon);
1305+ cupsdLogJob(job, CUPSD_LOG_ERROR,
1306+ "copy_banner: Unable to get the SELinux contexts");
1307+ job->num_files --;
1308+ return (0);
1309+ }
1310+ jobrange = (char *) context_range_get(jobcon);
1311+ if (jobrange)
1312+ {
1313+ jobrange = strdup(jobrange);
1314+ if ((jobclearance = strtok(jobrange, "-")) != NULL)
1315+ {
1316+ if (context_range_set(tmpcon, jobclearance) == -1)
1317+ {
1318+ cupsdLogJob(job, CUPSD_LOG_ERROR,
1319+ "copy_banner: Unable to set the "
1320+ "level of the context for file %s - %s",
1321+ filename, strerror(errno));
1322+ free(jobrange);
1323+ context_free(jobcon);
1324+ context_free(tmpcon);
1325+ job->num_files --;
1326+ return (0);
1327+ }
1328+ }
1329+ else
1330+ {
1331+ if (context_range_set(tmpcon, (context_range_get(jobcon))) == -1)
1332+ {
1333+ cupsdLogJob(job, CUPSD_LOG_ERROR,
1334+ "copy_banner: Unable to set the "
1335+ "level of the context for file %s - %s",
1336+ filename, strerror(errno));
1337+ free(jobrange);
1338+ context_free(jobcon);
1339+ context_free(tmpcon);
1340+ job->num_files --;
1341+ return (0);
1342+ }
1343+ }
1344+ free(jobrange);
1345+ }
1346+ if (setfilecon(filename, context_str(tmpcon)) == -1)
1347+ {
1348+ cupsdLogJob(job, CUPSD_LOG_ERROR,
1349+ "copy_banner: Unable to set the "
1350+ "context of the banner file %s - %s",
1351+ filename, strerror(errno));
1352+ context_free(jobcon);
1353+ context_free(tmpcon);
1354+ job->num_files --;
1355+ return (0);
1356+ }
1357+ cupsdLogJob(job, CUPSD_LOG_DEBUG2, "copy_banner: %s set to %s",
1358+ filename, context_str(tmpcon));
1359+ context_free(jobcon);
1360+ context_free(tmpcon);
1361+ }
1362+#endif /* WITH_LSPP */
1363
1364 /*
1365 * Try the localized banner file under the subdirectory...
5565574e 1366@@ -4232,6 +4673,24 @@ copy_banner(cupsd_client_t *con, /* I -
b3b50933
AM
1367 else
1368 s = attrname;
1369
1370+#ifdef WITH_LSPP
1371+ if (strcmp(s, "mls-label") == 0)
1372+ {
1373+ if (job->scon != NULL && strncmp(job->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) != 0)
1374+ {
1375+ jobcon = context_new(job->scon);
1376+ if (_cups_strcasecmp(name, MLS_CONFIG) == 0)
1377+ mls_label = context_range_get(jobcon);
1378+ else if (_cups_strcasecmp(name, TE_CONFIG) == 0)
1379+ mls_label = context_type_get(jobcon);
1380+ else // default to using the whole context string
1381+ mls_label = context_str(jobcon);
1382+ cupsFilePuts(out, mls_label);
1383+ context_free(jobcon);
1384+ }
1385+ continue;
1386+ }
1387+#endif /* WITH_LSPP */
1388 if (!strcmp(s, "printer-name"))
1389 {
1390 cupsFilePuts(out, job->dest);
5565574e 1391@@ -6439,6 +6898,22 @@ get_job_attrs(cupsd_client_t *con, /* I
b3b50933
AM
1392
1393 exclude = cupsdGetPrivateAttrs(policy, con, printer, job->username);
1394
1395+
1396+#ifdef WITH_LSPP
1397+ /*
1398+ * Check SELinux...
1399+ */
1400+ if (is_lspp_config() && check_context(con, job) != 1)
1401+ {
1402+ /*
1403+ * Unfortunately we have to lie to the user...
1404+ */
1405+ send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist!"), jobid);
1406+ return;
1407+ }
1408+#endif /* WITH_LSPP */
1409+
1410+
1411 /*
1412 * Copy attributes...
1413 */
5565574e 1414@@ -6836,6 +7311,11 @@ get_jobs(cupsd_client_t *con, /* I - C
b3b50933
AM
1415 if (username[0] && _cups_strcasecmp(username, job->username))
1416 continue;
1417
1418+#ifdef WITH_LSPP
1419+ if (is_lspp_config() && check_context(con, job) != 1)
1420+ continue;
1421+#endif /* WITH_LSPP */
1422+
1423 if (count > 0)
1424 ippAddSeparator(con->response);
1425
5565574e 1426@@ -11445,6 +11925,11 @@ validate_user(cupsd_job_t *job, /* I
b3b50933
AM
1427
1428 strlcpy(username, get_username(con), userlen);
1429
1430+#ifdef WITH_LSPP
1431+ if (is_lspp_config() && check_context(con, job) != 1)
1432+ return 0;
1433+#endif /* WITH_LSPP */
1434+
1435 /*
1436 * Check the username against the owner...
1437 */
5565574e
AM
1438diff -up cups-2.3.0/scheduler/job.c.lspp cups-2.3.0/scheduler/job.c
1439--- cups-2.3.0/scheduler/job.c.lspp 2019-10-07 12:24:43.024597707 +0200
1440+++ cups-2.3.0/scheduler/job.c 2019-10-07 12:30:13.092210820 +0200
1441@@ -8,6 +8,9 @@
1442 * information.
b3b50933
AM
1443 */
1444
1445+/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */
1446+/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */
1447+
1448 /*
1449 * Include necessary headers...
1450 */
5565574e 1451@@ -23,6 +26,14 @@
b3b50933
AM
1452 # endif /* HAVE_IOKIT_PWR_MGT_IOPMLIBPRIVATE_H */
1453 #endif /* __APPLE__ */
1454
1455+#ifdef WITH_LSPP
1456+#include <libaudit.h>
1457+#include <selinux/selinux.h>
1458+#include <selinux/context.h>
1459+#include <selinux/avc.h>
1460+#include <selinux/flask.h>
1461+#include <selinux/av_permissions.h>
1462+#endif /* WITH_LSPP */
1463
1464 /*
1465 * Design Notes for Job Management
5565574e 1466@@ -544,6 +555,14 @@ cupsdContinueJob(cupsd_job_t *job) /* I
b3b50933
AM
1467 /* PRINTER_STATE_REASONS env var */
1468 rip_max_cache[255];
1469 /* RIP_MAX_CACHE env variable */
1470+#ifdef WITH_LSPP
1471+ char *audit_message = NULL; /* Audit message string */
1472+ context_t jobcon; /* SELinux context of the job */
1473+ char *label_template = NULL; /* SL to put in classification
1474+ env var */
1475+ const char *mls_label = NULL; /* SL to put in classification
1476+ env var */
1477+#endif /* WITH_LSPP */
1478
1479
1480 cupsdLogMessage(CUPSD_LOG_DEBUG2,
5565574e 1481@@ -1080,6 +1099,67 @@ cupsdContinueJob(cupsd_job_t *job) /* I
b3b50933
AM
1482 if (final_content_type[0])
1483 envp[envc ++] = final_content_type;
1484
1485+#ifdef WITH_LSPP
1486+ if (is_lspp_config())
1487+ {
1488+ if (!job->scon || strncmp(job->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) == 0)
1489+ {
1490+ if (AuditLog != -1)
1491+ {
1492+ audit_message = NULL;
1493+ cupsdSetStringf(&audit_message, "job=%d auid=%u acct=%s printer=%s title=%s",
1494+ job->id, job->auid, job->username, job->printer->name, title);
1495+ audit_log_user_message(AuditLog, AUDIT_USER_UNLABELED_EXPORT, audit_message,
1496+ ServerName, NULL, NULL, 1);
1497+ cupsdClearString(&audit_message);
1498+ }
1499+ }
1500+ else
1501+ {
1502+ jobcon = context_new(job->scon);
1503+
1504+ if ((attr = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_NAME)) == NULL)
1505+ label_template = strdup(Classification);
1506+ else if (attr->num_values > 1 &&
1507+ strcmp(attr->values[1].string.text, "none") != 0)
1508+ label_template = strdup(attr->values[1].string.text);
1509+ else
1510+ label_template = strdup(attr->values[0].string.text);
1511+
1512+ if (_cups_strcasecmp(label_template, MLS_CONFIG) == 0)
1513+ mls_label = context_range_get(jobcon);
1514+ else if (_cups_strcasecmp(label_template, TE_CONFIG) == 0)
1515+ mls_label = context_type_get(jobcon);
1516+ else if (_cups_strcasecmp(label_template, SELINUX_CONFIG) == 0)
1517+ mls_label = context_str(jobcon);
1518+ else
1519+ mls_label = label_template;
1520+
1521+ if (mls_label && (PerPageLabels || banner_page))
1522+ {
1523+ snprintf(classification, sizeof(classification), "CLASSIFICATION=LSPP:%s", mls_label);
1524+ envp[envc ++] = classification;
1525+ }
1526+
1527+ if ((AuditLog != -1) && !banner_page)
1528+ {
1529+ audit_message = NULL;
1530+ cupsdSetStringf(&audit_message, "job=%d auid=%u acct=%s printer=%s title=%s"
1531+ " obj=%s label=%s", job->id, job->auid, job->username,
1532+ job->printer->name, title, job->scon, mls_label?mls_label:"none");
1533+ audit_log_user_message(AuditLog, AUDIT_USER_LABELED_EXPORT, audit_message,
1534+ ServerName, NULL, NULL, 1);
1535+ cupsdClearString(&audit_message);
1536+ }
1537+ context_free(jobcon);
1538+ free(label_template);
1539+ }
1540+ }
1541+ else
1542+ /*
1543+ * Fall through to the non-LSPP behavior
1544+ */
1545+#endif /* WITH_LSPP */
1546 if (Classification && !banner_page)
1547 {
1548 if ((attr = ippFindAttribute(job->attrs, "job-sheets",
5565574e 1549@@ -1858,6 +1938,22 @@ cupsdLoadJob(cupsd_job_t *job) /* I - J
b3b50933
AM
1550 ippSetString(job->attrs, &job->reasons, 0, "none");
1551 }
1552
1553+#ifdef WITH_LSPP
1554+ if ((attr = ippFindAttribute(job->attrs, "security-context", IPP_TAG_NAME)) != NULL)
1555+ cupsdSetString(&job->scon, attr->values[0].string.text);
1556+ else if (is_lspp_config())
1557+ {
1558+ /*
1559+ * There was no security context so delete the job
1560+ */
1561+ cupsdLogJob(job, CUPSD_LOG_ERROR,
1562+ "Missing or bad security-context attribute "
1563+ "in control file \"%s\"!",
1564+ jobfile);
1565+ goto error;
1566+ }
1567+#endif /* WITH_LSPP */
1568+
1569 job->impressions = ippFindAttribute(job->attrs, "job-impressions-completed", IPP_TAG_INTEGER);
1570 job->sheets = ippFindAttribute(job->attrs, "job-media-sheets-completed", IPP_TAG_INTEGER);
1571 job->job_sheets = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_NAME);
5565574e 1572@@ -2273,6 +2369,14 @@ cupsdSaveJob(cupsd_job_t *job) /* I - J
b3b50933
AM
1573 {
1574 char filename[1024]; /* Job control filename */
1575 cups_file_t *fp; /* Job file */
1576+#ifdef WITH_LSPP
1577+ security_context_t spoolcon; /* context of the job control file */
1578+ context_t jobcon; /* contex_t container for job->scon */
1579+ context_t tmpcon; /* Temp context to swap the level */
1580+ char *jobclearance; /* SELinux low end clearance */
1581+ const char *jobrange; /* SELinux sensitivity range */
1582+ char *jobrange_copy; /* SELinux sensitivity range */
1583+#endif /* WITH_LSPP */
1584
1585
1586 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdSaveJob(job=%p(%d)): job->attrs=%p",
5565574e 1587@@ -2295,6 +2399,78 @@ cupsdSaveJob(cupsd_job_t *job) /* I - J
b3b50933
AM
1588
1589 fchown(cupsFileNumber(fp), RunUser, Group);
1590
1591+#ifdef WITH_LSPP
1592+ if (job->scon && strncmp(job->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) != 0)
1593+ {
1594+ if (getfilecon(filename, &spoolcon) == -1)
1595+ {
1596+ cupsdLogJob(job, CUPSD_LOG_ERROR,
1597+ "Unable to get context of job control file \"%s\" - %s.",
1598+ filename, strerror(errno));
1599+ return;
1600+ }
1601+ jobcon = context_new(job->scon);
1602+ tmpcon = context_new(spoolcon);
1603+ freecon(spoolcon);
1604+ if (!jobcon || !tmpcon)
1605+ {
1606+ if (jobcon)
1607+ context_free(jobcon);
1608+ if (tmpcon)
1609+ context_free(tmpcon);
1610+ cupsdLogJob(job, CUPSD_LOG_ERROR, "Unable to get SELinux contexts");
1611+ return;
1612+ }
1613+ jobrange = context_range_get(jobcon);
1614+ if (jobrange)
1615+ {
1616+ jobrange_copy = strdup(jobrange);
1617+ if ((jobclearance = strtok(jobrange_copy, "-")) != NULL)
1618+ {
1619+ if (context_range_set(tmpcon, jobclearance) == -1)
1620+ {
1621+ cupsdLogJob(job, CUPSD_LOG_ERROR,
1622+ "Unable to set the range for "
1623+ "job control file \"%s\" - %s.",
1624+ filename, strerror(errno));
1625+ free(jobrange_copy);
1626+ context_free(tmpcon);
1627+ context_free(jobcon);
1628+ return;
1629+ }
1630+ }
1631+ else
1632+ {
1633+ if (context_range_set(tmpcon, (context_range_get(jobcon))) == -1)
1634+ {
1635+ cupsdLogJob(job, CUPSD_LOG_ERROR,
1636+ "Unable to set the range for "
1637+ "job control file \"%s\" - %s.",
1638+ filename, strerror(errno));
1639+ free(jobrange_copy);
1640+ context_free(tmpcon);
1641+ context_free(jobcon);
1642+ return;
1643+ }
1644+ }
1645+ free(jobrange_copy);
1646+ }
1647+ if (setfilecon(filename, context_str(tmpcon)) == -1)
1648+ {
1649+ cupsdLogJob(job, CUPSD_LOG_ERROR,
1650+ "Unable to set context of job control file \"%s\" - %s.",
1651+ filename, strerror(errno));
1652+ context_free(tmpcon);
1653+ context_free(jobcon);
1654+ return;
1655+ }
1656+ cupsdLogJob(job, CUPSD_LOG_DEBUG2, "New spool file context=%s",
1657+ context_str(tmpcon));
1658+ context_free(tmpcon);
1659+ context_free(jobcon);
1660+ }
1661+#endif /* WITH_LSPP */
1662+
1663 job->attrs->state = IPP_IDLE;
1664
1665 if (ippWriteIO(fp, (ipp_iocb_t)cupsFileWrite, 1, NULL,
5565574e 1666@@ -3995,6 +4171,19 @@ get_options(cupsd_job_t *job, /* I - Jo
b3b50933
AM
1667 banner_page)
1668 continue;
1669
1670+#ifdef WITH_LSPP
1671+ /*
1672+ * In LSPP mode refuse to honor the page-label
1673+ */
1674+ if (is_lspp_config() &&
1675+ !strcmp(attr->name, "page-label"))
1676+ {
1677+ cupsdLogJob(job, CUPSD_LOG_DEBUG,
1678+ "Ignoring page-label option due to LSPP mode");
1679+ continue;
1680+ }
1681+#endif /* WITH_LSPP */
1682+
1683 /*
1684 * Otherwise add them to the list...
1685 */
5565574e 1686@@ -4805,6 +4994,18 @@ start_job(cupsd_job_t *job, /* I -
b3b50933
AM
1687 cupsd_printer_t *printer) /* I - Printer to print job */
1688 {
1689 const char *filename; /* Support filename */
1690+#ifdef WITH_LSPP
1691+ char *audit_message = NULL; /* Audit message string */
1692+ char *printerfile = NULL; /* Device file pointed to by the printer */
1693+ security_id_t clisid; /* SELinux SID for the client */
1694+ security_id_t psid; /* SELinux SID for the printer */
1695+ context_t printercon; /* Printer's context string */
1696+ struct stat printerstat; /* Printer's stat buffer */
1697+ security_context_t devcon; /* Printer's SELinux context */
1698+ struct avc_entry_ref avcref; /* Pointer to the access vector cache */
1699+ security_class_t tclass; /* Object class for the SELinux check */
1700+ access_vector_t avr; /* Access method being requested */
1701+#endif /* WITH_LSPP */
1702 ipp_attribute_t *cancel_after = ippFindAttribute(job->attrs,
1703 "job-cancel-after",
1704 IPP_TAG_INTEGER);
5565574e 1705@@ -4993,6 +5194,113 @@ start_job(cupsd_job_t *job, /* I -
b3b50933
AM
1706 fcntl(job->side_pipes[1], F_SETFD,
1707 fcntl(job->side_pipes[1], F_GETFD) | FD_CLOEXEC);
1708
1709+#ifdef WITH_LSPP
1710+ if (is_lspp_config())
1711+ {
1712+ /*
1713+ * Perform an access check before printing, but only if the printer starts with /dev/
1714+ */
1715+ printerfile = strstr(printer->device_uri, "/dev/");
1716+ if (printerfile == NULL && (strncmp(printer->device_uri, "file:/", 6) == 0))
1717+ printerfile = printer->device_uri + strlen("file:");
1718+
1719+ if (printerfile != NULL)
1720+ {
1721+ cupsdLogJob(job, CUPSD_LOG_DEBUG,
1722+ "Attempting to check access on printer device %s",
1723+ printerfile);
1724+ if (lstat(printerfile, &printerstat) < 0)
1725+ {
1726+ if (errno != ENOENT)
1727+ {
1728+ cupsdLogJob(job, CUPSD_LOG_ERROR,
1729+ "Unable to stat the printer");
1730+ cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT, NULL);
1731+ return ;
1732+ }
1733+ /*
1734+ * The printer does not exist, so for now assume it's a FileDevice
1735+ */
1736+ tclass = SECCLASS_FILE;
1737+ avr = FILE__WRITE;
1738+ }
1739+ else if (S_ISCHR(printerstat.st_mode))
1740+ {
1741+ tclass = SECCLASS_CHR_FILE;
1742+ avr = CHR_FILE__WRITE;
1743+ }
1744+ else if (S_ISREG(printerstat.st_mode))
1745+ {
1746+ tclass = SECCLASS_FILE;
1747+ avr = FILE__WRITE;
1748+ }
1749+ else
1750+ {
1751+ cupsdLogJob(job, CUPSD_LOG_ERROR,
1752+ "StartJob: Printer is not a character device or "
1753+ "regular file");
1754+ cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT, NULL);
1755+ return ;
1756+ }
1757+ static int avc_initialized = 0;
1758+ if (!avc_initialized++)
1759+ avc_init("cupsd_dequeue_", NULL, NULL, NULL, NULL);
1760+ avc_entry_ref_init(&avcref);
1761+ if (avc_context_to_sid(job->scon, &clisid) != 0)
1762+ {
1763+ cupsdLogJob(job, CUPSD_LOG_ERROR,
1764+ "Unable to determine the SELinux sid for the job");
1765+ cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT, NULL);
1766+ return ;
1767+ }
1768+ if (getfilecon(printerfile, &devcon) == -1)
1769+ {
1770+ cupsdLogJob(job, CUPSD_LOG_ERROR,
1771+ "Unable to get the SELinux context of %s",
1772+ printerfile);
1773+ cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT, NULL);
1774+ return ;
1775+ }
1776+ printercon = context_new(devcon);
1777+ cupsdLogJob(job, CUPSD_LOG_DEBUG,
1778+ "Printer context %s client context %s",
1779+ context_str(printercon), job->scon);
1780+ context_free(printercon);
1781+
1782+ if (avc_context_to_sid(devcon, &psid) != 0)
1783+ {
1784+ cupsdLogJob(job, CUPSD_LOG_ERROR,
1785+ "Unable to determine the SELinux sid for the printer");
1786+ freecon(devcon);
1787+ cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT, NULL);
1788+ return ;
1789+ }
1790+ freecon(devcon);
1791+
1792+ if (avc_has_perm(clisid, psid, tclass, avr, &avcref, NULL) != 0)
1793+ {
1794+ /*
1795+ * The access check failed, so cancel the job and send an audit message
1796+ */
1797+ if (AuditLog != -1)
1798+ {
1799+ audit_message = NULL;
1800+ cupsdSetStringf(&audit_message, "job=%d auid=%u acct=%s obj=%s canceled"
1801+ " unable to access printer=%s", job->id,
1802+ job->auid, (job->username)?job->username:"?", job->scon, printer->name);
1803+ audit_log_user_message(AuditLog, AUDIT_USER_LABELED_EXPORT, audit_message,
1804+ ServerName, NULL, NULL, 0);
1805+ cupsdClearString(&audit_message);
1806+ }
1807+
1808+ cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT, NULL);
1809+
1810+ return ;
1811+ }
1812+ }
1813+ }
1814+#endif /* WITH_LSPP */
1815+
1816 /*
1817 * Now start the first file in the job...
1818 */
5565574e
AM
1819diff -up cups-2.3.0/scheduler/job.h.lspp cups-2.3.0/scheduler/job.h
1820--- cups-2.3.0/scheduler/job.h.lspp 2019-08-23 17:19:38.000000000 +0200
1821+++ cups-2.3.0/scheduler/job.h 2019-10-07 12:29:54.364371023 +0200
1822@@ -7,6 +7,13 @@
1823 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
b3b50933
AM
1824 */
1825
1826+/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */
1827+/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */
1828+
1829+#ifdef WITH_LSPP
1830+#include <selinux/selinux.h>
1831+#endif /* WITH_LSPP */
1832+
1833 /*
1834 * Constants...
1835 */
5565574e 1836@@ -84,6 +91,10 @@ struct cupsd_job_s /**** Job request *
b3b50933
AM
1837 int progress; /* Printing progress */
1838 int num_keywords; /* Number of PPD keywords */
1839 cups_option_t *keywords; /* PPD keywords */
1840+#ifdef WITH_LSPP
1841+ security_context_t scon; /* Security context of job */
1842+ uid_t auid; /* Audit loginuid for this job */
1843+#endif /* WITH_LSPP */
1844 };
1845
1846 typedef struct cupsd_joblog_s /**** Job log message ****/
5565574e
AM
1847diff -up cups-2.3.0/scheduler/main.c.lspp cups-2.3.0/scheduler/main.c
1848--- cups-2.3.0/scheduler/main.c.lspp 2019-10-07 12:24:43.037597616 +0200
1849+++ cups-2.3.0/scheduler/main.c 2019-10-07 12:24:43.119597037 +0200
1850@@ -57,6 +57,9 @@
b3b50933
AM
1851 # include <sys/param.h>
1852 #endif /* HAVE_SYS_PARAM_H */
1853
1854+#ifdef WITH_LSPP
1855+# include <libaudit.h>
1856+#endif /* WITH_LSPP */
1857
1858 /*
1859 * Local functions...
5565574e 1860@@ -123,6 +126,9 @@ main(int argc, /* I - Number of comm
b3b50933
AM
1861 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
1862 struct sigaction action; /* Actions for POSIX signals */
1863 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
1864+#if WITH_LSPP
1865+ auditfail_t failmode; /* Action for audit_open failure */
1866+#endif /* WITH_LSPP */
1867 #ifdef __APPLE__
1868 int use_sysman = 1; /* Use system management functions? */
1869 #else
0f0e09b5 1870@@ -495,6 +501,25 @@ main(int argc, /* I - Number of comm
b3b50933
AM
1871 exit(errno);
1872 }
1873
1874+#ifdef WITH_LSPP
1875+ if ((AuditLog = audit_open()) < 0 )
1876+ {
1877+ if (get_auditfail_action(&failmode) == 0)
1878+ {
1879+ if (failmode == FAIL_LOG)
1880+ {
1881+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to connect to audit subsystem.");
1882+ AuditLog = -1;
1883+ }
1884+ else if (failmode == FAIL_TERMINATE)
1885+ {
1886+ fprintf(stderr, "cupsd: unable to start auditing, terminating");
1887+ return -1;
1888+ }
1889+ }
1890+ }
1891+#endif /* WITH_LSPP */
1892+
1893 /*
32548b83 1894 * Let the system know we are busy while we bring up cupsd...
b3b50933 1895 */
5565574e 1896@@ -1201,6 +1226,11 @@ main(int argc, /* I - Number of comm
b3b50933
AM
1897
1898 cupsdStopSelect();
1899
1900+#ifdef WITH_LSPP
1901+ if (AuditLog != -1)
1902+ audit_close(AuditLog);
1903+#endif /* WITH_LSPP */
1904+
1905 return (!stop_scheduler);
1906 }
1907
5565574e
AM
1908diff -up cups-2.3.0/scheduler/printers.c.lspp cups-2.3.0/scheduler/printers.c
1909--- cups-2.3.0/scheduler/printers.c.lspp 2019-08-23 17:19:38.000000000 +0200
1910+++ cups-2.3.0/scheduler/printers.c 2019-10-07 12:29:17.956658129 +0200
1911@@ -8,6 +8,8 @@
1912 * information.
b3b50933
AM
1913 */
1914
1915+/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */
1916+
1917 /*
1918 * Include necessary headers...
1919 */
5565574e 1920@@ -32,6 +34,10 @@
b3b50933
AM
1921 # include <asl.h>
1922 #endif /* __APPLE__ */
1923
1924+#ifdef WITH_LSPP
1925+# include <libaudit.h>
1926+# include <selinux/context.h>
1927+#endif /* WITH_LSPP */
1928
1929 /*
1930 * Local functions...
5565574e 1931@@ -2252,6 +2258,13 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)
b3b50933
AM
1932 ipp_attribute_t *attr; /* Attribute data */
1933 char *name, /* Current user/group name */
1934 *filter; /* Current filter */
1935+#ifdef WITH_LSPP
1936+ char *audit_message; /* Audit message string */
1937+ char *printerfile; /* Path to a local printer dev */
1938+ char *rangestr; /* Printer's range if its available */
1939+ security_context_t devcon; /* Printer SELinux context */
1940+ context_t printercon; /* context_t for the printer */
1941+#endif /* WITH_LSPP */
1942
1943
5565574e
AM
1944 /*
1945@@ -2378,6 +2391,45 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)
b3b50933
AM
1946 attr->values[1].string.text = _cupsStrAlloc(Classification ?
1947 Classification : p->job_sheets[1]);
1948 }
1949+#ifdef WITH_LSPP
1950+ if (AuditLog != -1)
1951+ {
1952+ audit_message = NULL;
1953+ rangestr = NULL;
1954+ printercon = 0;
1955+ printerfile = strstr(p->device_uri, "/dev/");
1956+ if (printerfile == NULL && (strncmp(p->device_uri, "file:/", 6) == 0))
1957+ printerfile = p->device_uri + strlen("file:");
1958+
1959+ if (printerfile != NULL)
1960+ {
1961+ if (getfilecon(printerfile, &devcon) == -1)
1962+ {
1963+ if(is_selinux_enabled())
1964+ cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdSetPrinterAttrs: Unable to get printer context");
1965+ }
1966+ else
1967+ {
1968+ printercon = context_new(devcon);
1969+ freecon(devcon);
1970+ }
1971+ }
1972+
1973+ if (printercon && context_range_get(printercon))
1974+ rangestr = strdup(context_range_get(printercon));
1975+ else
1976+ rangestr = strdup("unknown");
1977+
1978+ cupsdSetStringf(&audit_message, "printer=%s uri=%s banners=%s,%s range=%s",
1979+ p->name, p->sanitized_device_uri, p->job_sheets[0], p->job_sheets[1], rangestr);
1980+ audit_log_user_message(AuditLog, AUDIT_LABEL_LEVEL_CHANGE, audit_message,
1981+ ServerName, NULL, NULL, 1);
1982+ if (printercon)
1983+ context_free(printercon);
1984+ free(rangestr);
1985+ cupsdClearString(&audit_message);
1986+ }
1987+#endif /* WITH_LSPP */
1988 }
1989
1990 p->raw = 0;
This page took 0.406481 seconds and 4 git commands to generate.