Home | History | Annotate | Download | only in lpsched
      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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     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
     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 CSTATUS	*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 he/she wants.
    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
    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 sytem 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
    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
    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
   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
   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