]>
Commit | Line | Data |
---|---|---|
5565574e AM |
1 | diff -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 |
16 | diff -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 |
56 | diff -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 |
68 | diff -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 |
239 | diff -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 |
397 | diff -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 |
409 | diff -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 |
631 | diff -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 |
669 | diff -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 |
768 | diff -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 |
795 | diff -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 |
822 | diff -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 |
1438 | diff -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 |
1819 | diff -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 |
1847 | diff -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 |
1908 | diff -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; |