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