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