1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright (c) 2016 by Delphix. All rights reserved.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30
31 /* SVr4.0 1.11.1.10 */
32 /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */
33
34 #include "lpsched.h"
35
36 #include "validate.h"
37
38 #include <syslog.h>
39 #include <errno.h>
40 #include <deflt.h>
41 #include <tsol/label.h>
42 #include <auth_list.h>
43
44 #define register auto
45
46
47 int pickfilter ( RSTATUS * , CANDIDATE * , FSTATUS * );
48
49 unsigned long chkprinter_result = 0;
50 char * o_cpi = 0;
51 char * o_lpi = 0;
52 char * o_width = 0;
53 char * o_length = 0;
54
55 static int wants_nobanner = 0;
56 static int wants_nolabels = 0;
57 static int lp_or_root = 0;
58
59 static int _chkopts ( RSTATUS *, CANDIDATE * , FSTATUS * );
60 static void free_candidate ( CANDIDATE * );
61 static int tsol_check_printer_label_range(char *, const char *);
62 static int tsol_lpauth(char *, char *);
63 static int secpolicy_chkpolicy(char *policyp);
64
65 /**
66 ** _validate() - FIND A PRINTER TO HANDLE A REQUEST
67 **/
68
69 short
_validate(RSTATUS * prs,PSTATUS * pps,PSTATUS * stop_pps,char ** prefixp,int moving)70 _validate(RSTATUS *prs, PSTATUS *pps, PSTATUS *stop_pps, char **prefixp,
71 int moving)
72 {
73 register CANDIDATE *pc = 0,
74 *pcend,
75 *best_pc = 0;
76
77 register FSTATUS *pfs = 0;
78
79 register CLSTATUS *pcs = 0;
80
81 CANDIDATE *arena = 0,
82 single;
83
84 size_t n;
85 int i;
86
87 short ret;
88
89 chkprinter_result = 0;
90 o_cpi = o_lpi = o_width = o_length = 0;
91 wants_nobanner = 0;
92 memset (&single, 0, sizeof(single));
93
94 wants_nolabels = 0;
95 /*
96 * If the system is labeled, the printing of postscript files
97 * is restricted. All users can print postscript files if the
98 * file /etc/default/print contains "PRINT_POSTSCRIPT=1".
99 * (this is checked by secpolicy_chkpolicy). Otherwise the
100 * user must have PRINT_POSTSCRIPT_AUTH to print postscript files.
101 */
102 if ((is_system_labeled() &&
103 strcmp(prs->request->input_type, "postscript") == 0) &&
104 (secpolicy_chkpolicy("PRINT_POSTSCRIPT=") == 0)) {
105 if (tsol_lpauth(PRINT_POSTSCRIPT_AUTH, prs->secure->user)
106 == 0) {
107 ret = MDENYDEST;
108 goto Return;
109 }
110 }
111 lp_or_root = 0;
112
113 if (bangequ(prs->secure->user, "root") ||
114 bangequ(prs->secure->user, "lp"))
115 lp_or_root = 1;
116
117 if (prefixp)
118 *prefixp = prs->request->destination;
119
120 /*
121 * If a destination other than "any" was given,
122 * see if it exists in our internal tables.
123 */
124 if (!pps && prs->request->destination &&
125 !STREQU(prs->request->destination, NAME_ANY))
126 if (((pps = search_pstatus(prs->request->destination)) != NULL) ||
127 ((pcs = search_cstatus(prs->request->destination)) != NULL) &&
128 pcs->class->members)
129 /*EMPTY*/;
130 else {
131 ret = MNODEST;
132 goto Return;
133 }
134
135 /*
136 * If we are trying to avoid a printer, but the request
137 * was destined for just that printer, we're out.
138 */
139 if (pps && pps == stop_pps) {
140 ret = MERRDEST;
141 goto Return;
142 }
143
144 /*
145 * If a form was given, see if it exists; if so,
146 * see if the user is allowed to use it.
147 * If a remote printer was specified, then don't use any local
148 * form knowledge.
149 */
150 if (prs && prs->request && prs->request->form && (pps || pcs)) {
151 if ((pfs = search_fstatus(prs->request->form))) {
152 if (lp_or_root || allowed(prs->secure->user,
153 pfs->users_allowed, pfs->users_denied))
154 /*EMPTY*/;
155 else {
156 ret = MDENYMEDIA;
157 goto Return;
158 }
159 } else {
160 ret = MNOMEDIA;
161 goto Return;
162 }
163 }
164
165 /*
166 * If the request includes -o options there may be pitch and
167 * size and no-banner requests that have to be checked. One
168 * could argue that this shouldn't be in the Spooler, because
169 * the Spooler's job is SPOOLING, not PRINTING. That's right,
170 * except that the Spooler will be making a choice of printers
171 * so it has to evaluate carefully: E.g. user wants ANY printer,
172 * so we should pick one that can handle what they want.
173 *
174 * Parse out the important stuff here so we have it when we
175 * need it.
176 */
177 {
178 register char **list,
179 **pl;
180
181 if (
182 prs->request->options
183 && (list = dashos(prs->request->options))
184 ) {
185 for (pl = list ; *pl; pl++)
186 if (STRNEQU(*pl, "cpi=", 4))
187 o_cpi = Strdup(*pl + 4);
188 else if (STRNEQU(*pl, "lpi=", 4))
189 o_lpi = Strdup(*pl + 4);
190 else if (STRNEQU(*pl, "width=", 6))
191 o_width = Strdup(*pl + 6);
192 else if (STRNEQU(*pl, "length=", 7))
193 o_length = Strdup(*pl + 7);
194 else if (STREQU(*pl, "nobanner"))
195 wants_nobanner = 1;
196 else if (STREQU(*pl, "nolabels"))
197 wants_nolabels = 1;
198 freelist (list);
199 }
200 }
201
202 /*
203 * This macro checks that a form has a mandatory print wheel
204 * (or character set).
205 */
206 #define CHKMAND(PFS) \
207 ( \
208 (PFS) \
209 && (PFS)->form->chset \
210 && !STREQU((PFS)->form->chset, NAME_ANY) \
211 && (PFS)->form->mandatory \
212 )
213
214 /*
215 * This macro checks that the user is allowed to use the
216 * printer.
217 */
218 #define CHKU(PRS,PPS) \
219 ( \
220 lp_or_root \
221 || allowed( \
222 (PRS)->secure->user, \
223 (PPS)->users_allowed, \
224 (PPS)->users_denied \
225 ) \
226 )
227
228 /*
229 * This macro checks that the form is allowed on the printer,
230 * or is already mounted there.
231 * Note: By doing this check we don't have to check that the
232 * characteristics of the form, such as pitch, size, or
233 * character set, against the printer's capabilities, ASSUMING,
234 * of course, that the allow list is correct. That is, the
235 * allow list lists forms that have already been checked against
236 * the printer!
237 */
238 #define CHKF(PFS,PPS) \
239 ( \
240 isFormMountedOnPrinter(PPS,PFS) \
241 || allowed( \
242 (PFS)->form->name, \
243 (PPS)->forms_allowed, \
244 (PPS)->forms_denied \
245 ) \
246 )
247
248 /*
249 * This macro checks that the print wheel is acceptable
250 * for the printer or is mounted. Note: If the printer doesn't
251 * take print wheels, the check passes. The check for printers
252 * that don't take print wheels is below.
253 */
254 #define CHKPW(PW,PPS) \
255 ( \
256 !(PPS)->printer->daisy \
257 || ( \
258 (PPS)->pwheel_name \
259 && STREQU((PPS)->pwheel_name, (PW)) \
260 ) \
261 || searchlist((PW), (PPS)->printer->char_sets) \
262 )
263
264 /*
265 * This macro checks the pitch, page size, and (if need be)
266 * the character set. The character set isn't checked if the
267 * printer takes print wheels, or if the character set is
268 * listed in the printer's alias list.
269 * The form has to be checked as well; while we're sure that
270 * at least one type for each printer can handle the form's
271 * cpi/lpi/etc. characteristics (lpadmin made sure), we aren't
272 * sure that ALL the types work.
273 */
274 #define CHKOPTS(PRS,PC,PFS) _chkopts((PRS),(PC),(PFS)) /* was a macro */
275
276 /*
277 * This macro checks the acceptance status of a printer.
278 * If the request is already assigned to that printer,
279 * then it's okay. It's ambiguous what should happen if
280 * originally a "-d any" request was accepted, temporarily
281 * assigned one printer, then the administrator (1) rejected
282 * further requests for the printers and (2) made the
283 * temporarily assigned printer unusable for the request.
284 * What will happen, of course, is that the request will
285 * be canceled, even though the other printers would be okay
286 * if not rejecting....but if we were to say, gee it's okay,
287 * the request has already been accepted, we may be allowing
288 * it on printers that were NEVER accepting. Thus we can
289 * continue to accept it only for the printer already assigned.
290 */
291 #define CHKACCEPT(PRS,PPS) \
292 ( \
293 !((PPS)->status & PS_REJECTED) \
294 || (PRS)->printer == (PPS) \
295 || moving \
296 )
297
298 /*
299 * If a print wheel or character set is given, see if it
300 * is allowed on the form.
301 */
302 if (prs->request->charset)
303 if (
304 !CHKMAND(pfs)
305 || STREQU(prs->request->charset, pfs->form->chset)
306 )
307 /*EMPTY*/;
308 else {
309 ret = MDENYMEDIA;
310 chkprinter_result |= PCK_CHARSET;
311 goto Return;
312 }
313
314 /*
315 * If a single printer was named, check the request against it.
316 * Do the accept/reject check late so that we give the most
317 * useful information to the user.
318 */
319 if (pps) {
320 (pc = &single)->pps = pps;
321
322 /* Does the printer allow the user? */
323 if (!CHKU(prs, pps)) {
324 ret = MDENYDEST;
325 goto Return;
326 }
327
328 /* Check printer label range */
329 if (is_system_labeled() && prs->secure->slabel != NULL) {
330 if (tsol_check_printer_label_range(
331 prs->secure->slabel,
332 pps->printer->name) == 0) {
333 ret = MDENYDEST;
334 goto Return;
335 }
336 }
337
338 /* Does the printer allow the form? */
339 if (pfs && !CHKF(pfs, pps)) {
340 ret = MNOMOUNT;
341 goto Return;
342 }
343
344 /* Does the printer allow the pwheel? */
345 if (
346 prs->request->charset
347 && !CHKPW(prs->request->charset, pps)
348 ) {
349 ret = MNOMOUNT;
350 goto Return;
351 }
352
353 /* Can printer handle the pitch/size/charset/nobanner? */
354 if (!CHKOPTS(prs, pc, pfs)) {
355 ret = MDENYDEST;
356 goto Return;
357 }
358
359 /* Is the printer allowing requests? */
360 if (!CHKACCEPT(prs, pps)) {
361 ret = MERRDEST;
362 goto Return;
363 }
364
365 /* Is there a filter which will convert the input? */
366 if (!pickfilter(prs, pc, pfs)) {
367 ret = MNOFILTER;
368 goto Return;
369 }
370
371 best_pc = pc;
372 ret = MOK;
373 goto Return;
374 }
375
376 /*
377 * Do the acceptance check on the class (if we have one)
378 * now so we can proceed with checks on individual printers
379 * in the class. Don't toss out the request if it is already
380 * assigned a printer just because the class is NOW rejecting.
381 */
382 if (
383 pcs
384 && (pcs->status & CS_REJECTED)
385 && !moving
386 && !prs->printer
387 ) {
388 ret = MERRDEST;
389 goto Return;
390 }
391
392 /*
393 * Construct a list of printers based on the destination
394 * given. Cross off those that aren't accepting requests,
395 * that can't take the form, or which the user can't use.
396 * See if the list becomes empty.
397 */
398
399 if (pcs)
400 n = lenlist(pcs->class->members);
401 else {
402 for (n = 0; PStatus != NULL && PStatus[n] != NULL; n++) ;
403 }
404 pcend = arena = (CANDIDATE *)Calloc(n, sizeof(CANDIDATE));
405
406 /*
407 * Start with a list of printers that are accepting requests.
408 * Don't skip a printer if it's rejecting but the request
409 * has already been accepted for it.
410 */
411 if (pcs) {
412 register char **pn;
413
414 for (pn = pcs->class->members; *pn; pn++)
415 if (
416 ((pps = search_pstatus(*pn)) != NULL)
417 && pps != stop_pps
418 )
419 (pcend++)->pps = pps;
420
421
422 } else
423 for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++) {
424 pps = PStatus[i];
425
426 if (CHKACCEPT(prs, pps) && pps != stop_pps)
427 (pcend++)->pps = pps;
428 }
429
430 if (pcend == arena) {
431 ret = MERRDEST;
432 goto Return;
433 }
434
435 /*
436 * Clean out printers that the user can't use. We piggy-back
437 * the pitch/size/banner checks here because the same error return
438 * is given (strange, eh?).
439 */
440 {
441 register CANDIDATE *pcend2;
442
443 for (pcend2 = pc = arena; pc < pcend; pc++) {
444 if (CHKU(prs, pc->pps) && CHKOPTS(prs, pc, pfs))
445 *pcend2++ = *pc;
446 else
447 free_candidate (pc);
448 }
449
450 if (pcend2 == arena) {
451 ret = MDENYDEST;
452 goto Return;
453 }
454 pcend = pcend2;
455
456 }
457
458 /*
459 * Clean out printers that can't mount the form,
460 * EXCEPT for printers that already have it mounted:
461 */
462 if (pfs) {
463 register CANDIDATE *pcend2;
464
465 for (pcend2 = pc = arena; pc < pcend; pc++)
466 if (CHKF(pfs, pc->pps))
467 *pcend2++ = *pc;
468 else
469 free_candidate (pc);
470
471 if (pcend2 == arena) {
472 ret = MNOMOUNT;
473 goto Return;
474 }
475 pcend = pcend2;
476
477 }
478
479 /*
480 * Clean out printers that can't take the print wheel
481 * EXCEPT for printers that already have it mounted
482 * or printers for which it is a selectable character set:
483 */
484 if (prs->request->charset) {
485 register CANDIDATE *pcend2;
486
487 for (pcend2 = pc = arena; pc < pcend; pc++)
488 if (CHKPW(prs->request->charset, pc->pps))
489 *pcend2++ = *pc;
490 else
491 free_candidate (pc);
492
493 if (pcend2 == arena) {
494 ret = MNOMOUNT;
495 goto Return;
496 }
497 pcend = pcend2;
498
499 }
500
501 /*
502 * Clean out printers that can't handle the printing
503 * and for which there's no filter to convert the input.
504 *
505 */
506
507 /*
508 * Is the form mounted, or is none needed?
509 */
510 #define CHKFMNT(PFS,PPS) (isFormUsableOnPrinter(PPS,PFS))
511
512 /*
513 * Is the print-wheel mounted, or is none needed?
514 */
515 #define CHKPWMNT(PRS,PPS) SAME((PPS)->pwheel_name, (PRS)->request->charset)
516
517 /*
518 * Do we NOT need a special character set, or can we select
519 * it on the printer? Note: Getting this far means that IF
520 * the printer has selectable character sets (!daisy) then
521 * it can select the one we want.
522 */
523 #define CHKCHSET(PRS,PPS) \
524 ( \
525 !(PRS)->request->charset \
526 || !(PPS)->printer->daisy \
527 )
528
529 /*
530 * Is the printer able to print now?
531 */
532 #define CHKENB(PPS) (!((PPS)->status & (PS_DISABLED|PS_FAULTED)))
533
534 /*
535 * Is the printer not busy printing another request, or
536 * not awaiting an auto-retry after a fault?
537 */
538 #define CHKFREE(PPS) (!((PPS)->status & (PS_BUSY|PS_LATER)))
539
540 {
541 register CANDIDATE *pcend2;
542
543 for (pcend2 = pc = arena; pc < pcend; pc++)
544 if (pickfilter(prs, pc, pfs)) {
545
546 /*
547 * Compute a ``weight'' for this printer,
548 * based on its status. We'll later pick
549 * the printer with the highest weight.
550 */
551 pc->weight = 0;
552 if (!pc->fast && !pc->slow)
553 pc->weight += WEIGHT_NOFILTER;
554 if (CHKFREE(pc->pps))
555 pc->weight += WEIGHT_FREE;
556 if (CHKENB(pc->pps))
557 pc->weight += WEIGHT_ENABLED;
558 if (CHKFMNT(pfs, pc->pps))
559 pc->weight += WEIGHT_MOUNTED;
560 if (CHKPWMNT(prs, pc->pps))
561 pc->weight += WEIGHT_MOUNTED;
562 if (CHKCHSET(prs, pc->pps))
563 pc->weight += WEIGHT_SELECTS;
564
565 #if defined(FILTER_EARLY_OUT)
566 if (pc->weight == WEIGHT_MAX) {
567 /*
568 * This is the one!
569 */
570 best_pc = pc;
571 ret = MOK;
572 goto Return;
573 }
574 #endif
575 /*
576 * This is a candidate!
577 */
578 *pcend2++ = *pc;
579
580 } else
581 /*
582 * No filter for this one!
583 */
584 free_candidate (pc);
585
586 if (pcend2 == arena) {
587 ret = MNOFILTER;
588 goto Return;
589 }
590 pcend = pcend2;
591
592 }
593
594 if (pcend - arena == 1) {
595 best_pc = arena;
596 ret = MOK;
597 goto Return;
598 }
599 /*
600 * Clean out local printers
601 * where the request is outside the printer label range.
602 */
603 {
604 register CANDIDATE *pcend2 = pcend;
605
606 if (is_system_labeled()) {
607 for (pcend2 = pc = arena; pc < pcend; pc++) {
608 if (tsol_check_printer_label_range(
609 prs->secure->slabel,
610 pps->printer->name) == 1)
611 *pcend2++ = *pc;
612 else
613 free_candidate(pc);
614 }
615 }
616
617 if (pcend2 == arena) {
618 ret = MDENYDEST;
619 goto Return;
620 }
621 pcend = pcend2;
622 }
623
624 #if defined(OTHER_FACTORS)
625 /*
626 * Here you might want to add code that considers
627 * other factors: the size of the file(s) to be
628 * printed ("prs->secure->size") in relation to the
629 * printer (e.g. printer A gets mostly large
630 * files, printer B gets mostly small files); the
631 * number/total-size of requests currently queued
632 * for the printer; etc.
633 *
634 * If your code includes eliminating printers drop them
635 * from the list (as done in several places above).
636 * Otherwise, your code should add weights to the weight
637 * already computed. Change the WEIGHT_MAX, increase the
638 * other WEIGHT_X values to compensate, etc., as appropriate.
639 */
640 ;
641 #endif
642
643 /*
644 * Pick the best printer from a list of eligible candidates.
645 */
646 best_pc = arena;
647 for (pc = arena + 1; pc < pcend; pc++)
648 if (pc->weight > best_pc->weight)
649 best_pc = pc;
650 ret = MOK;
651
652 /*
653 * Branch to here if MOK and/or if things have been allocated.
654 */
655 Return: if (ret == MOK) {
656 register USER *pu = Getuser(prs->secure->user);
657
658 register char *pwheel_name;
659
660 PSTATUS *oldpps = prs->printer;
661
662
663 /*
664 * We are going to accept this print request, having
665 * found a printer for it. This printer will be assigned
666 * to the request, although this assignment may be
667 * temporary if other printers qualify and this printer
668 * is changed to no longer qualify. Qualification in
669 * this context includes being ready to print!
670 */
671 prs->printer = best_pc->pps;
672 load_str (&(prs->printer_type), best_pc->printer_type);
673
674 /*
675 * Assign the form (if any) to the request. Adjust
676 * the number of requests queued for old and new form
677 * accordingly.
678 */
679 if (prs->form != pfs) {
680 unqueue_form (prs);
681 queue_form (prs, pfs);
682 }
683
684 /*
685 * Ditto for the print wheel, except include here the
686 * print wheel needed by the form.
687 * CAUTION: When checking this request later, don't
688 * refuse to service it if the print wheel for the
689 * form isn't mounted but the form is; a mounted form
690 * overrides its other needs. Don't be confused by the
691 * name of the bit, RSS_PWMAND; a printer that prints
692 * this request MUST have the print wheel mounted
693 * (if it takes print wheels) if the user asked for
694 * a particular print wheel.
695 */
696 prs->status &= ~RSS_PWMAND;
697 if (CHKMAND(pfs))
698 pwheel_name = pfs->form->chset;
699 else
700 if ((pwheel_name = prs->request->charset) != NULL)
701 prs->status |= RSS_PWMAND;
702
703 if (!SAME(pwheel_name, prs->pwheel_name)) {
704 unqueue_pwheel (prs);
705 queue_pwheel (prs, pwheel_name);
706 }
707
708 /*
709 * Adjust the priority to lie within the limits allowed
710 * for the user (this is a silent adjustment as required).
711 * CURRENTLY, ONLY NEW REQUESTS WILL GET QUEUED ACCORDING
712 * TO THIS PRIORITY. EXISTING REQUESTS BEING (RE)EVALUATED
713 * WILL NOT BE REQUEUED.
714 * A wild priority is changed to the default, or the
715 * limit, whichever is the lower priority (higher value).
716 */
717 if (prs->request->priority < 0 || 39 < prs->request->priority)
718 prs->request->priority = getdfltpri();
719 if (pu && prs->request->priority < pu->priority_limit)
720 prs->request->priority = pu->priority_limit;
721
722 /*
723 * If a filter is involved, change the number of
724 * copies to 1 (if the filter handles it).
725 */
726 if (
727 (best_pc->fast || best_pc->slow)
728 && (best_pc->flags & FPARM_COPIES)
729 && prs->request->copies > 1
730 )
731 prs->copies = 1;
732 else
733 /*
734 * We use two ".copies" because we don't
735 * want to lose track of the number requested,
736 * but do want to mark the number the interface
737 * program is to handle. Here is the best
738 * place to know this.
739 */
740 prs->copies = prs->request->copies;
741
742 if (best_pc->slow) {
743 /*
744 * If the filter has changed, the request will
745 * have to be refiltered. This may mean stopping
746 * a currently running filter or interface.
747 */
748 if (!SAME(best_pc->slow, prs->slow)) {
749
750 if (prs->request->outcome & RS_FILTERED)
751 prs->request->outcome &= ~RS_FILTERED;
752
753 if (
754 prs->request->outcome & RS_FILTERING
755 && !(prs->request->outcome & RS_STOPPED)
756 ) {
757 prs->request->outcome |= RS_REFILTER;
758 prs->request->outcome |= RS_STOPPED;
759 terminate (prs->exec);
760
761 } else if (
762 prs->request->outcome & RS_PRINTING
763 && !(prs->request->outcome & RS_STOPPED)
764 ) {
765 prs->request->outcome |= RS_STOPPED;
766 terminate (oldpps->exec);
767 }
768
769 }
770
771 load_str (&(prs->slow), best_pc->slow);
772 /* Assumption: if there is a slow filter,
773 * there is an output_type
774 */
775
776 load_str (&(prs->output_type), best_pc->output_type);
777 } else
778 unload_str (&(prs->slow));
779
780 load_str (&(prs->fast), best_pc->fast);
781
782 if (prs->request->actions & ACT_FAST && prs->slow) {
783 if (prs->fast) {
784 prs->fast = makestr(
785 prs->slow,
786 "|",
787 prs->fast,
788 (char *)0
789 );
790 Free (prs->slow);
791 } else
792 prs->fast = prs->slow;
793 prs->slow = 0;
794 }
795
796 }
797
798
799 /*
800 * Free the space allocated for the candidates, INCLUDING
801 * the one chosen. Any allocated space in the chosen candidate
802 * that has to be saved should have been COPIED already.
803 */
804 if (arena) {
805 for (pc = arena; pc < pcend; pc++)
806 free_candidate (pc);
807 Free ((char *)arena);
808 } else if (best_pc)
809 free_candidate (best_pc);
810
811 if (o_length)
812 Free (o_length);
813 if (o_width)
814 Free (o_width);
815 if (o_lpi)
816 Free (o_lpi);
817 if (o_cpi)
818 Free (o_cpi);
819
820
821 /*
822 * The following value is valid ONLY IF the request
823 * is canceled or rejected. Not all requests that
824 * we fail in this routine are tossed out!
825 */
826 prs->reason = ret;
827
828
829 return (ret);
830 }
831
832 /**
833 ** _chkopts() - CHECK -o OPTIONS
834 **/
835
836 static int
_chkopts(RSTATUS * prs,CANDIDATE * pc,FSTATUS * pfs)837 _chkopts(RSTATUS *prs, CANDIDATE *pc, FSTATUS *pfs)
838 {
839 unsigned long ret = 0;
840 unsigned long chk = 0;
841
842 char * charset;
843 char * cpi = 0;
844 char * lpi = 0;
845 char * width = 0;
846 char * length = 0;
847 char * paper = NULL;
848
849 char ** pt;
850 int nobanner_not_allowed = 0;
851
852
853 /*
854 * If we have a form, it overrides whatever print characteristics
855 * the user gave.
856 */
857 if (pfs) {
858 cpi = pfs->cpi;
859 lpi = pfs->lpi;
860 width = pfs->pwid;
861 length = pfs->plen;
862 paper = pfs->form->paper;
863 } else {
864 cpi = o_cpi;
865 lpi = o_lpi;
866 width = o_width;
867 length = o_length;
868 }
869
870 /*
871 * If the printer takes print wheels, or the character set
872 * the user wants is listed in the character set map for this
873 * printer, we needn't check if the printer can handle the
874 * character set. (Note: The check for the print wheel case
875 * is done elsewhere.)
876 */
877
878 if (pc->pps->printer->daisy ||
879 search_cslist(prs->request->charset, pc->pps->printer->char_sets))
880 charset = 0;
881 else
882 charset = prs->request->charset;
883
884 pc->printer_types = 0;
885 for (pt = pc->pps->printer->printer_types; *pt; pt++) {
886 unsigned long this;
887
888 if (paper) {
889 if (allowed(paper,pc->pps->paper_allowed,NULL)) {
890 addlist (&(pc->printer_types), *pt);
891 } else {
892 ret |= PCK_PAPER;
893 }
894 } else {
895 this = chkprinter(*pt, cpi, lpi, length, width,
896 charset);
897 if (this == 0)
898 addlist(&(pc->printer_types), *pt);
899 chk |= this;
900 }
901 }
902 if (!pc->printer_types)
903 ret |= chk;
904
905 /*
906 * If the system is labeled, then user who wants 'nolabels' must
907 * have PRINT_UNLABELED_AUTH authorizations to allow it.
908 */
909 if (is_system_labeled() && (wants_nolabels == 1)) {
910 if (!tsol_lpauth(PRINT_UNLABELED_AUTH, prs->secure->user)) {
911 /* if not authorized, remove "nolabels" from options */
912 register char **list;
913 if (prs->request->options &&
914 (list = dashos(prs->request->options))) {
915 dellist(&list, "nolabels");
916 free(prs->request->options);
917 prs->request->options = sprintlist(list);
918 }
919 }
920 }
921
922
923 if (pc->pps->printer->banner == BAN_ALWAYS) {
924 /* delete "nobanner" */
925 char **list;
926
927 /*
928 * If the system is labeled, users must have
929 * PRINT_NOBANNER_AUTH authorization to print
930 * without a banner.
931 */
932 if (is_system_labeled()) {
933 if (wants_nobanner == 1) {
934 if (tsol_lpauth(PRINT_NOBANNER_AUTH,
935 prs->secure->user) == 0) {
936 nobanner_not_allowed = 1;
937 }
938 }
939
940 }
941 else if ((wants_nobanner == 1) && (lp_or_root != 1)) {
942 nobanner_not_allowed = 1;
943 }
944 if (nobanner_not_allowed == 1) {
945 /* Take out 'nobanner' from request options. */
946 if (prs->request->options &&
947 (list = dashos(prs->request->options))) {
948 dellist(&list, "nobanner");
949 free(prs->request->options);
950 prs->request->options = sprintlist(list);
951 }
952 }
953 } else if (pc->pps->printer->banner == BAN_NEVER) {
954 if (wants_nobanner == 0) {
955 /* add "nobanner" */
956 char **list = NULL;
957
958 if (prs->request->options) {
959 list = dashos(prs->request->options);
960 free(prs->request->options);
961 }
962 appendlist(&list, "nobanner");
963 prs->request->options = sprintlist(list);
964 }
965 } else /* if (pc->pps->printer->banner == BAN_OPTIONAL) */ {
966 /* it is optional, leave it alone */
967 }
968
969 chkprinter_result |= ret;
970 return (ret == 0);
971 }
972
973 /**
974 ** free_candidate()
975 **/
976
977 static void
free_candidate(CANDIDATE * pc)978 free_candidate(CANDIDATE *pc)
979 {
980 if (pc->slow)
981 unload_str (&(pc->slow));
982 if (pc->fast)
983 unload_str (&(pc->fast));
984 if (pc->printer_types) {
985 freelist (pc->printer_types);
986 pc->printer_types = 0;
987 }
988 if (pc->printer_type)
989 unload_str (&(pc->printer_type));
990 if (pc->output_type)
991 unload_str (&(pc->output_type));
992 return;
993 }
994
995 static int
tsol_check_printer_label_range(char * slabel,const char * printer)996 tsol_check_printer_label_range(char *slabel, const char *printer)
997 {
998 int in_range = 0;
999 int err = 0;
1000 m_range_t *range;
1001 m_label_t *sl = NULL;
1002
1003 if (slabel == NULL)
1004 return (0);
1005
1006 if ((err =
1007 (str_to_label(slabel, &sl, USER_CLEAR, L_NO_CORRECTION, &in_range)))
1008 == -1) {
1009 /* stobsl error on printer max label */
1010 return (0);
1011 }
1012 if ((range = getdevicerange(printer)) == NULL) {
1013 m_label_free(sl);
1014 return (0);
1015 }
1016
1017 /* blinrange returns true (1) if in range, false (0) if not */
1018 in_range = blinrange(sl, range);
1019
1020 m_label_free(sl);
1021 m_label_free(range->lower_bound);
1022 m_label_free(range->upper_bound);
1023 free(range);
1024
1025 return (in_range);
1026 }
1027
1028 /*
1029 * Given a character string with a "username" or "system!username"
1030 * this function returns a pointer to "username"
1031 */
1032 static int
tsol_lpauth(char * auth,char * in_name)1033 tsol_lpauth(char *auth, char *in_name)
1034 {
1035 char *cp;
1036 int res;
1037
1038 if ((cp = strchr(in_name, '@')) != NULL) {
1039 /* user@system */
1040 *cp = '\0';
1041 res = chkauthattr(auth, in_name);
1042 *cp = '@';
1043 } else if ((cp = strchr(in_name, '!')) != NULL)
1044 /* system!user */
1045 res = chkauthattr(auth, cp+1);
1046 else
1047 /* user */
1048 res = chkauthattr(auth, in_name);
1049
1050 return (res);
1051 }
1052
1053 #define POLICY_FILE "/etc/default/print"
1054
1055 int
secpolicy_chkpolicy(char * policyp)1056 secpolicy_chkpolicy(char *policyp)
1057 {
1058 char *option;
1059 int opt_val;
1060
1061 if (policyp == NULL)
1062 return (0);
1063 opt_val = 0;
1064 if (defopen(POLICY_FILE) == 0) {
1065
1066 defcntl(DC_SETFLAGS, DC_STD & ~DC_CASE); /* ignore case */
1067
1068 if ((option = defread(policyp)) != NULL)
1069 opt_val = atoi(option);
1070 }
1071 (void) defopen((char *)NULL);
1072 syslog(LOG_DEBUG, "--- Policy %s, opt_val==%d",
1073 policyp ? policyp : "NULL", opt_val);
1074 return (opt_val);
1075 }
1076