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