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