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