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
47int		pickfilter ( RSTATUS * , CANDIDATE * , FSTATUS * );
48
49unsigned long		chkprinter_result	= 0;
50char *			o_cpi		= 0;
51char *			o_lpi		= 0;
52char *			o_width		= 0;
53char *			o_length	= 0;
54
55static int		wants_nobanner	= 0;
56static int		wants_nolabels	= 0;
57static int		lp_or_root	= 0;
58
59static int		_chkopts ( RSTATUS *, CANDIDATE * , FSTATUS * );
60static void		free_candidate ( CANDIDATE * );
61static int		tsol_check_printer_label_range(char *, const char *);
62static int		tsol_lpauth(char *, char *);
63static int		secpolicy_chkpolicy(char *policyp);
64
65/**
66 ** _validate() - FIND A PRINTER TO HANDLE A REQUEST
67 **/
68
69short
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	 */
655Return:	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
836static int
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
977static void
978free_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
995static int
996tsol_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 */
1032static int
1033tsol_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
1055int
1056secpolicy_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