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