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 2006 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; 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