Home | History | Annotate | Download | only in lpsched
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 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 #include "dispatch.h"
     30 #include <sys/types.h>
     31 #include <sys/stat.h>
     32 #include <syslog.h>
     33 
     34 static char	*reqpath(char *, char **);
     35 static int	mv_file(RSTATUS *, char *);
     36 
     37 
     38 RSTATUS			*NewRequest;
     39 
     40 /*
     41  * s_alloc_files()
     42  */
     43 
     44 void
     45 s_alloc_files(char *m, MESG *md)	/* funcdef */
     46 {
     47 	char		*file_prefix;
     48 	ushort_t	count;
     49 	mode_t		old_msk;
     50 
     51 
     52 	/*
     53 	 * Bugid 4140311
     54 	 * Set umask to 0 before creating files.
     55 	 */
     56 	old_msk = umask((mode_t)0);
     57 
     58 	getmessage(m, S_ALLOC_FILES, &count);
     59 	syslog(LOG_DEBUG, "s_alloc_files(%d)", count);
     60 
     61 	if ((file_prefix = _alloc_files(count, (char *)0, md->uid, md->gid))) {
     62 		mputm(md, R_ALLOC_FILES, MOK, file_prefix);
     63 		add_flt_act(md, FLT_FILES, file_prefix, count);
     64 	} else if (errno == EEXIST)
     65 		mputm(md, R_ALLOC_FILES, MERRDEST, "");
     66 	else
     67 		mputm(md, R_ALLOC_FILES, MNOMEM, "");
     68 
     69 	(void) umask(old_msk);
     70 
     71 }
     72 
     73 /*
     74  * s_print_request()
     75  */
     76 
     77 void
     78 s_print_request(char *m, MESG *md)
     79 {
     80 	extern char		*Local_System;
     81 	char			*file;
     82 	char			*idno;
     83 	char			*path;
     84 	char			*req_file;
     85 	char			*req_id	= 0;
     86 	RSTATUS			*rp;
     87 	REQUEST			*r;
     88 	SECURE			*s;
     89 	struct passwd		*pw;
     90 	short			err;
     91 	short			status;
     92 	off_t			size;
     93 	uid_t			org_uid;
     94 	gid_t			org_gid;
     95 #ifdef LP_USE_PAPI_ATTR
     96 	struct stat		tmpBuf;
     97 	char 			tmpName[BUFSIZ];
     98 #endif
     99 
    100 
    101 	(void) getmessage(m, S_PRINT_REQUEST, &file);
    102 	syslog(LOG_DEBUG, "s_print_request(%s)", (file ? file : "NULL"));
    103 
    104 	/*
    105 	 * "NewRequest" points to a request that's not yet in the
    106 	 * request list but is to be considered with the rest of the
    107 	 * requests (e.g. calculating # of requests awaiting a form).
    108 	 */
    109 	if ((rp = NewRequest = new_rstatus(NULL, NULL)) == NULL)
    110 		status = MNOMEM;
    111 
    112 	else
    113 	{
    114 		req_file = reqpath(file, &idno);
    115 		path = makepath(Lp_Tmp, req_file, (char *)0);
    116 		(void) chownmod(path, Lp_Uid, Lp_Gid, 0644);
    117 		Free(path);
    118 
    119 		if (!(r = Getrequest(req_file)))
    120 			status = MNOOPEN;
    121 
    122 		else
    123 		{
    124 			rp->req_file = Strdup(req_file);
    125 
    126 			freerequest(rp->request);
    127 			rp->request = r;
    128 
    129 			rp->request->outcome = 0;
    130 			rp->secure->uid = md->uid;
    131 			rp->secure->gid = md->gid;
    132 			if (md->slabel != NULL)
    133 				rp->secure->slabel = Strdup(md->slabel);
    134 
    135 			pw = getpwuid(md->uid);
    136 			endpwent();
    137 			if (pw && pw->pw_name && *pw->pw_name)
    138 				rp->secure->user = Strdup(pw->pw_name);
    139 			else {
    140 				rp->secure->user = Strdup(BIGGEST_NUMBER_S);
    141 				(void) sprintf(rp->secure->user, "%u",
    142 				    md->uid);
    143 			}
    144 
    145 			if ((rp->request->actions & ACT_SPECIAL) == ACT_HOLD)
    146 				rp->request->outcome |= RS_HELD;
    147 			if ((rp->request->actions & ACT_SPECIAL) == ACT_RESUME)
    148 				rp->request->outcome &= ~RS_HELD;
    149 			if ((rp->request->actions & ACT_SPECIAL) ==
    150 			    ACT_IMMEDIATE) {
    151 				if (!md->admin) {
    152 					status = MNOPERM;
    153 					goto Return;
    154 				}
    155 				rp->request->outcome |= RS_IMMEDIATE;
    156 			}
    157 
    158 			size = chfiles(rp->request->file_list, Lp_Uid, Lp_Gid);
    159 
    160 			if (size < 0) {
    161 				/*
    162 				 * at this point, chfiles() may have
    163 				 * failed because the file may live on
    164 				 * an NFS mounted filesystem, under
    165 				 * a directory of mode 700. such a
    166 				 * directory isn't accessible even by
    167 				 * root, according to the NFS protocol
    168 				 * (i.e. the Stat() in chfiles() failed).
    169 				 * this most commonly happens via the
    170 				 * automounter, and rlogin. thus we
    171 				 * change our euid/egid to that of the
    172 				 * user, and try again. if *this* fails,
    173 				 * then the file must really be
    174 				 * inaccessible.
    175 				 */
    176 				org_uid = geteuid();
    177 				org_gid = getegid();
    178 
    179 				if (setegid(md->gid) != 0) {
    180 					status = MUNKNOWN;
    181 					goto Return;
    182 				}
    183 
    184 				if (seteuid(md->uid) != 0) {
    185 					setgid(org_gid);
    186 					status = MUNKNOWN;
    187 					goto Return;
    188 				}
    189 
    190 				size = chfiles(rp->request->file_list,
    191 				    Lp_Uid, Lp_Gid);
    192 
    193 				if (seteuid(org_uid) != 0) {
    194 					/* should never happen */
    195 					note("s_print_request(): ");
    196 					note("seteuid back to uid=%d "
    197 					    "failed!!\n", org_uid);
    198 					size = -1;
    199 				}
    200 
    201 				if (setegid(org_gid) != 0) {
    202 					/* should never happen */
    203 					note("s_print_request(): ");
    204 					note("setegid back to uid=%d "
    205 					    "failed!!\n", org_uid);
    206 					size = -1;
    207 				}
    208 
    209 				if (size < 0) {
    210 					status = MUNKNOWN;
    211 					goto Return;
    212 				}
    213 			}
    214 			if (!(rp->request->outcome & RS_HELD) && size == 0) {
    215 				status = MNOPERM;
    216 				goto Return;
    217 			}
    218 			rp->secure->size = size;
    219 
    220 			(void) time(&rp->secure->date);
    221 			rp->secure->req_id = NULL;
    222 
    223 			if (!rp->request->title) {
    224 				if (strlen(*rp->request->file_list) <
    225 				    (size_t)24)
    226 					rp->request->title =
    227 					    Strdup(*rp->request->file_list);
    228 				else {
    229 					/*
    230 					 * In case of standard input
    231 					 * the title page should be
    232 					 * 'standard input'
    233 					 */
    234 					rp->request->title = malloc(25);
    235 					sprintf(rp->request->title,
    236 					    "%-.24s", "standard input");
    237 				}
    238 			}
    239 
    240 			if ((err = validate_request(rp, &req_id, 0)) != MOK)
    241 				status = err;
    242 			else {
    243 				/*
    244 				 * "req_id" will be supplied if this is from a
    245 				 * remote system.
    246 				 */
    247 				if (rp->secure->req_id == NULL) {
    248 					req_id = makestr(req_id, "-",
    249 					    idno, (char *)0);
    250 					rp->secure->req_id = req_id;
    251 				} else
    252 					req_id = rp->secure->req_id;
    253 
    254 #ifdef LP_USE_PAPI_ATTR
    255 				/*
    256 				 * Check if the PAPI job attribute file
    257 				 * exists, if it does change the
    258 				 * permissions and ownership of the file.
    259 				 * This file is created when print jobs
    260 				 * are submitted via the PAPI interface,
    261 				 * the file pathname of this file is
    262 				 * passed to the slow-filters and printer
    263 				 * interface script as an environment
    264 				 * variable when they are executed
    265 				 */
    266 				snprintf(tmpName, sizeof (tmpName),
    267 				    "%s-%s", idno, LP_PAPIATTRNAME);
    268 				path = makepath(Lp_Temp, tmpName, (char *)0);
    269 
    270 				if (stat(path, &tmpBuf) == 0) {
    271 					syslog(LOG_DEBUG,
    272 					    "s_print_request: "\
    273 					    "attribute file ='%s'", path);
    274 
    275 					/*
    276 					 * IPP job attribute file exists
    277 					 * for this job so change
    278 					 * permissions and ownership of
    279 					 * the file
    280 					 */
    281 					(void) chownmod(path, Lp_Uid,
    282 					    Lp_Gid, 0644);
    283 					Free(path);
    284 				}
    285 				else
    286 				{
    287 					syslog(LOG_DEBUG,
    288 					    "s_print_request: "\
    289 					    "no attribute file");
    290 				}
    291 #endif
    292 
    293 				/*
    294 				 * fix for bugid 1103890.
    295 				 * use Putsecure instead.
    296 				 */
    297 				if ((Putsecure(req_file, rp->secure) == -1) ||
    298 				    (putrequest(req_file, rp->request) == -1))
    299 					status = MNOMEM;
    300 				else
    301 				{
    302 					status = MOK;
    303 
    304 					insertr(rp);
    305 					NewRequest = 0;
    306 
    307 					if (rp->slow)
    308 						schedule(EV_SLOWF, rp);
    309 					else
    310 						schedule(EV_INTERF,
    311 						    rp->printer);
    312 
    313 					del_flt_act(md, FLT_FILES);
    314 				}
    315 			}
    316 		}
    317 	}
    318 
    319 Return:
    320 	NewRequest = 0;
    321 	Free(req_file);
    322 	Free(idno);
    323 	if (status != MOK && rp) {
    324 		rmfiles(rp, 0);
    325 		free_rstatus(rp);
    326 	}
    327 	mputm(md, R_PRINT_REQUEST, status, NB(req_id), chkprinter_result);
    328 }
    329 
    330 /*
    331  * s_start_change_request()
    332  */
    333 
    334 void
    335 s_start_change_request(char *m, MESG *md)
    336 {
    337 	char		*req_id;
    338 	char		*req_file	= "";
    339 	short		status;
    340 	RSTATUS		*rp;
    341 	char		*path;
    342 	char		tmpName[BUFSIZ];
    343 	struct stat	tmpBuf;
    344 
    345 	(void) getmessage(m, S_START_CHANGE_REQUEST, &req_id);
    346 	syslog(LOG_DEBUG, "s_start_change_request(%s)",
    347 	    (req_id ? req_id : "NULL"));
    348 
    349 	if (!(rp = request_by_id(req_id)))
    350 		status = MUNKNOWN;
    351 	else if ((md->admin == 0) && (is_system_labeled()) &&
    352 	    (md->slabel != NULL) && (rp->secure->slabel != NULL) &&
    353 	    (!STREQU(md->slabel, rp->secure->slabel)))
    354 		status = MUNKNOWN;
    355 	else if (rp->request->outcome & RS_DONE)
    356 		status = M2LATE;
    357 	else if (!md->admin && md->uid != rp->secure->uid)
    358 		status = MNOPERM;
    359 	else if (rp->request->outcome & RS_CHANGING)
    360 		status = MNOOPEN;
    361 	else if (rp->request->outcome & RS_NOTIFYING)
    362 		status = MBUSY;
    363 	else {
    364 		status = MOK;
    365 
    366 		if (rp->request->outcome & RS_FILTERING &&
    367 		    !(rp->request->outcome & RS_STOPPED)) {
    368 			rp->request->outcome |= (RS_REFILTER|RS_STOPPED);
    369 			terminate(rp->exec);
    370 		}
    371 
    372 		if (rp->request->outcome & RS_PRINTING &&
    373 		    !(rp->request->outcome & RS_STOPPED)) {
    374 			rp->request->outcome |= RS_STOPPED;
    375 			terminate(rp->printer->exec);
    376 		}
    377 
    378 		rp->request->outcome |= RS_CHANGING;
    379 
    380 		/*
    381 		 * Change the ownership of the request file to be "md->uid".
    382 		 * Either this is identical to "rp->secure->uid", or it is
    383 		 * "Lp_Uid" or it is root. The idea is that the
    384 		 * person at the other end needs access, and that may not
    385 		 * be who queued the request.
    386 		 */
    387 
    388 		path = makepath(Lp_Tmp, rp->req_file, (char *)0);
    389 		(void) Chown(path, md->uid, rp->secure->gid);
    390 		Free(path);
    391 
    392 #ifdef LP_USE_PAPI_ATTR
    393 
    394 		/*
    395 		 * Check if the PAPI job attribute file exists, if it does
    396 		 * change the ownership of the file to be "md->uid".
    397 		 * Either this is identical to "rp->secure->uid", or it is
    398 		 * "Lp_Uid" or it is root. The idea is that the
    399 		 * person at the other end needs access, and that may not
    400 		 * be who queued the request.
    401 		 */
    402 
    403 		snprintf(tmpName, sizeof (tmpName),
    404 		    "%s-%s", strtok(strdup(rp->req_file), "-"),
    405 		    LP_PAPIATTRNAME);
    406 
    407 		path = makepath(Lp_Tmp, tmpName, (char *)0);
    408 
    409 		if (stat(path, &tmpBuf) == 0) {
    410 			syslog(LOG_DEBUG,
    411 			    "s_start_change_request: attribute file ='%s'",
    412 			    path);
    413 
    414 			/*
    415 			 * IPP job attribute file exists for this job so
    416 			 * change permissions and ownership of the file
    417 			 */
    418 			(void) Chown(path, md->uid, rp->secure->gid);
    419 			Free(path);
    420 		}
    421 		else
    422 		{
    423 			syslog(LOG_DEBUG,
    424 			    "s_start_change_request: no attribute file");
    425 		}
    426 #endif
    427 
    428 		add_flt_act(md, FLT_CHANGE, rp);
    429 		req_file = rp->req_file;
    430 
    431 	}
    432 
    433 	mputm(md, R_START_CHANGE_REQUEST, status, req_file);
    434 }
    435 
    436 /*
    437  * s_end_change_request()
    438  */
    439 
    440 void
    441 s_end_change_request(char *m, MESG *md)
    442 {
    443 	char		*req_id;
    444 	RSTATUS		*rp;
    445 	off_t		size;
    446 	off_t		osize;
    447 	short		err;
    448 	short		status;
    449 	REQUEST		*r = 0;
    450 	REQUEST		oldr;
    451 	int		call_schedule = 0;
    452 	int		move_ok	= 0;
    453 	char		*path;
    454 	char		tmpName[BUFSIZ];
    455 	struct stat	tmpBuf;
    456 
    457 	(void) getmessage(m, S_END_CHANGE_REQUEST, &req_id);
    458 	syslog(LOG_DEBUG, "s_end_change_request(%s)",
    459 	    (req_id ? req_id : "NULL"));
    460 
    461 	if (!(rp = request_by_id(req_id)))
    462 		status = MUNKNOWN;
    463 	else if ((md->admin == 0) && (is_system_labeled()) &&
    464 	    (md->slabel != NULL) && (rp->secure->slabel != NULL) &&
    465 	    (!STREQU(md->slabel, rp->secure->slabel)))
    466 		status = MUNKNOWN;
    467 	else if (!(rp->request->outcome & RS_CHANGING))
    468 		status = MNOSTART;
    469 	else {
    470 		path = makepath(Lp_Tmp, rp->req_file, (char *)0);
    471 		(void) chownmod(path, Lp_Uid, Lp_Gid, 0644);
    472 		Free(path);
    473 
    474 #ifdef LP_USE_PAPI_ATTR
    475 
    476 		/*
    477 		 * Check if the PAPI job attribute file exists,
    478 		 * if it does change the permission and the ownership
    479 		 * of the file to be "Lp_Uid".
    480 		 */
    481 
    482 		snprintf(tmpName, sizeof (tmpName),
    483 		    "%s-%s", strtok(strdup(rp->req_file), "-"),
    484 		    LP_PAPIATTRNAME);
    485 
    486 		path = makepath(Lp_Tmp, tmpName, (char *)0);
    487 
    488 		if (stat(path, &tmpBuf) == 0) {
    489 			syslog(LOG_DEBUG,
    490 			    "s_end_change_request: attribute file ='%s'",
    491 			    path);
    492 
    493 			/*
    494 			 * IPP job attribute file exists for this job so
    495 			 * change permissions and ownership of the file
    496 			 */
    497 			(void) chownmod(path, Lp_Uid, Lp_Gid, 0644);
    498 			Free(path);
    499 		}
    500 		else
    501 		{
    502 			syslog(LOG_DEBUG,
    503 			    "s_end_change_request: no attribute file");
    504 		}
    505 #endif
    506 		rp->request->outcome &= ~(RS_CHANGING);
    507 		del_flt_act(md, FLT_CHANGE);
    508 		/*
    509 		 * The RS_CHANGING bit may have been the only thing
    510 		 * preventing this request from filtering or printing,
    511 		 * so regardless of what happens below,
    512 		 * we must check to see if the request can proceed.
    513 		 */
    514 		call_schedule = 1;
    515 
    516 		if (!(r = Getrequest(rp->req_file)))
    517 			status = MNOOPEN;
    518 		else {
    519 			oldr = *(rp->request);
    520 			*(rp->request) = *r;
    521 
    522 			move_ok =
    523 			    STREQU(oldr.destination, r->destination);
    524 
    525 			/*
    526 			 * Preserve the current request status!
    527 			 */
    528 			rp->request->outcome = oldr.outcome;
    529 
    530 			/*
    531 			 * Here's an example of the dangers one meets
    532 			 * when public flags are used for private
    533 			 * purposes. ".actions" (indeed, anything in the
    534 			 * REQUEST structure) is set by the person
    535 			 * changing the job. However, lpsched uses
    536 			 * ".actions" as place to indicate that a job
    537 			 * came from a remote system and we must send
    538 			 * back job completion--this is a strictly
    539 			 * private flag that we must preserve.
    540 			 */
    541 			rp->request->actions |=
    542 			    (oldr.actions & ACT_NOTIFY);
    543 
    544 			if ((rp->request->actions & ACT_SPECIAL) ==
    545 			    ACT_HOLD) {
    546 				rp->request->outcome |= RS_HELD;
    547 				/*
    548 				 * To be here means either the user owns
    549 				 * the request or he or she is the
    550 				 * administrator. Since we don't want to
    551 				 * set the RS_ADMINHELD flag if the user
    552 				 * is the administrator, the following
    553 				 * compare will work.
    554 				 */
    555 				if (md->uid != rp->secure->uid)
    556 					rp->request->outcome |=
    557 					    RS_ADMINHELD;
    558 			}
    559 
    560 			if ((rp->request->actions & ACT_SPECIAL) ==
    561 			    ACT_RESUME) {
    562 				if ((rp->request->outcome & RS_ADMINHELD) &&
    563 				    !md->admin) {
    564 					status = MNOPERM;
    565 					goto Return;
    566 				}
    567 				rp->request->outcome &=
    568 				    ~(RS_ADMINHELD|RS_HELD);
    569 			}
    570 
    571 			if ((rp->request->actions & ACT_SPECIAL)
    572 			    == ACT_IMMEDIATE) {
    573 				if (!md->admin) {
    574 					status = MNOPERM;
    575 					goto Return;
    576 				}
    577 				rp->request->outcome |= RS_IMMEDIATE;
    578 			}
    579 
    580 			size = chfiles(rp->request->file_list, Lp_Uid,
    581 			    Lp_Gid);
    582 			if (size < 0) {
    583 				status = MUNKNOWN;
    584 				goto Return;
    585 			}
    586 			if (!(rp->request->outcome & RS_HELD) &&
    587 			    size == 0) {
    588 				status = MNOPERM;
    589 				goto Return;
    590 			}
    591 
    592 			osize = rp->secure->size;
    593 			rp->secure->size = size;
    594 
    595 			if (move_ok == 0) {
    596 				char *dest = strdup(r->destination);
    597 				if ((status = mv_file(rp, dest)) == MOK)
    598 					rp->secure->size = osize;
    599 				free(dest);
    600 			} else if ((err = validate_request(rp, (char **)0,
    601 			    move_ok)) != MOK) {
    602 				status = err;
    603 				rp->secure->size = osize;
    604 			} else {
    605 				status = MOK;
    606 
    607 				if ((rp->request->outcome & RS_IMMEDIATE) ||
    608 				    (rp->request->priority != oldr.priority)) {
    609 					remover(rp);
    610 					insertr(rp);
    611 				}
    612 
    613 				freerequest(&oldr);
    614 				(void) putrequest(rp->req_file, rp->request);
    615 				/*
    616 				 * fix for bugid 1103890.
    617 				 * use Putsecure instead.
    618 				 */
    619 				(void) Putsecure(rp->req_file, rp->secure);
    620 			}
    621 		}
    622 	}
    623 
    624 Return:
    625 	if (status != MOK && rp) {
    626 		if (r) {
    627 			freerequest(r);
    628 			*(rp->request) = oldr;
    629 		}
    630 		if (status != MNOSTART)
    631 			(void) putrequest(rp->req_file, rp->request);
    632 	}
    633 
    634 	if (call_schedule)
    635 		maybe_schedule(rp);
    636 
    637 	mputm(md, R_END_CHANGE_REQUEST, status, chkprinter_result);
    638 }
    639 
    640 /*
    641  * _cancel()
    642  *	user may be (host!user)
    643  */
    644 
    645 static char *
    646 _cancel(MESG *md, char *dest, char *user, char *req_id)
    647 {
    648 	static RSTATUS	*rp;
    649 	static char		*s_dest;
    650 	static char		*s_user;
    651 	static char		*s_req_id;
    652 	static int		current;
    653 	RSTATUS		*crp;
    654 	char		*creq_id;
    655 
    656 	syslog(LOG_DEBUG, "_cancel(%s, %s, %s)", (dest ? dest : "NULL"),
    657 	    (user ? user : "NULL"), (req_id ? req_id : "NULL"));
    658 
    659 	if (dest || user || req_id) {
    660 		s_dest = dest;
    661 		if (STREQU(user, "!"))
    662 			s_user = strdup("all!all");
    663 		else
    664 			s_user = user;
    665 		s_req_id = req_id;
    666 		rp = Request_List;
    667 		current = 0;
    668 		if (STREQU(s_req_id, CURRENT_REQ)) {
    669 			current = 1;
    670 			s_req_id = NULL;
    671 		}
    672 	}
    673 
    674 	while (rp != NULL) {
    675 		crp = rp;
    676 		rp = rp->next;
    677 
    678 		if (*s_dest && !STREQU(s_dest, crp->request->destination))
    679 			continue;
    680 
    681 		if (current && !(crp->request->outcome & RS_PRINTING))
    682 			continue;
    683 
    684 		if (s_req_id && *s_req_id &&
    685 		    !STREQU(s_req_id, crp->secure->req_id))
    686 			continue;
    687 
    688 		if (*s_user && !bangequ(s_user, crp->secure->user))
    689 			continue;
    690 
    691 		if (!md->admin && md->uid != crp->secure->uid) {
    692 			errno = MNOPERM;
    693 			return (Strdup(crp->secure->req_id));
    694 		}
    695 
    696 		/*
    697 		 * For Trusted Extensions, we need to check the
    698 		 * sensitivity label of the
    699 		 * connection and job before we try to cancel it.
    700 		 */
    701 		if ((md->admin == 0) && (is_system_labeled()) &&
    702 		    (md->slabel != NULL) && (crp->secure->slabel != NULL) &&
    703 		    (!STREQU(md->slabel, crp->secure->slabel)))
    704 			continue;
    705 
    706 		crp->reason = MOK;
    707 		creq_id = Strdup(crp->secure->req_id);
    708 
    709 		syslog(LOG_DEBUG, "cancel reqid (%s) uid: %d, secureuid: %d",
    710 		    creq_id, md->uid, crp->secure->uid);
    711 
    712 		if (cancel(crp, (md->uid != crp->secure->uid)))
    713 			errno = MOK;
    714 		else
    715 			errno = M2LATE;
    716 		return (creq_id);
    717 	}
    718 
    719 	errno = MUNKNOWN;
    720 	return (NULL);
    721 }
    722 
    723 /*
    724  * s_cancel_request()
    725  */
    726 
    727 void
    728 s_cancel_request(char *m, MESG *md)
    729 {
    730 	char	*req_id, *rid;
    731 	short	status;
    732 
    733 	(void) getmessage(m, S_CANCEL_REQUEST, &req_id);
    734 	syslog(LOG_DEBUG, "s_cancel_request(%s)", (req_id ? req_id : "NULL"));
    735 
    736 	if ((rid = _cancel(md, "", "", req_id)) != NULL)
    737 		Free(rid);
    738 	status = (short)errno;
    739 
    740 	mputm(md, R_CANCEL_REQUEST, status);
    741 }
    742 
    743 /*
    744  * s_cancel()
    745  */
    746 
    747 void
    748 s_cancel(char *m, MESG *md)
    749 {
    750 	char	*req_id;
    751 	char	*user;
    752 	char	*destination;
    753 	char	*rid;
    754 	char	*nrid;
    755 	int		nerrno;
    756 	int		oerrno;
    757 
    758 	(void) getmessage(m, S_CANCEL, &destination, &user, &req_id);
    759 	syslog(LOG_DEBUG, "s_cancel(%s, %s, %s)",
    760 	    (destination ? destination : "NULL"), (user ? user : "NULL"),
    761 	    (req_id ? req_id : "NULL"));
    762 
    763 	if (STREQU(destination, NAME_ALL))
    764 		destination = "";
    765 	if (STREQU(req_id, NAME_ALL))
    766 		req_id = "";
    767 
    768 	if (rid = _cancel(md, destination, user, req_id)) {
    769 		oerrno = errno;
    770 
    771 		while ((nrid = _cancel(md, NULL, NULL, NULL)) != NULL) {
    772 			nerrno = errno;
    773 			mputm(md, R_CANCEL, MOKMORE, oerrno, rid);
    774 			Free(rid);
    775 			rid = nrid;
    776 			oerrno = nerrno;
    777 		}
    778 		mputm(md, R_CANCEL, MOK, oerrno, rid);
    779 		Free(rid);
    780 		return;
    781 	}
    782 
    783 	mputm(md, R_CANCEL, MOK, MUNKNOWN, "");
    784 }
    785 
    786 /*
    787  * s_inquire_request_rank()
    788  */
    789 
    790 void
    791 s_inquire_request_rank(char *m, MESG *md)
    792 {
    793 	char		*form;
    794 	char		*dest;
    795 	char		*pwheel;
    796 	char		*user;
    797 	char		*req_id;
    798 	RSTATUS		*rp;
    799 	RSTATUS		*found = NULL;
    800 	int		found_rank = 0;
    801 	short		prop;
    802 	char		files[BUFSIZ];
    803 	int 		i;
    804 
    805 	(void) getmessage(m, S_INQUIRE_REQUEST_RANK, &prop, &form, &dest,
    806 	    &req_id, &user, &pwheel);
    807 	syslog(LOG_DEBUG, "s_inquire_request_rank(%d, %s, %s, %s, %s, %s)",
    808 	    prop, (form ? form : "NULL"), (dest ? dest : "NULL"),
    809 	    (req_id ? req_id : "NULL"), (user ? user : "NULL"),
    810 	    (pwheel ? pwheel : "NULL"));
    811 
    812 	for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++)
    813 		PStatus[i]->nrequests = 0;
    814 
    815 	for (rp = Request_List; rp != NULL; rp = rp->next) {
    816 		if (rp->printer && !(rp->request->outcome & RS_DONE))
    817 			rp->printer->nrequests++;
    818 
    819 		if (*form && !SAME(form, rp->request->form))
    820 			continue;
    821 
    822 		if (*dest && !STREQU(dest, rp->request->destination)) {
    823 			if (!rp->printer)
    824 				continue;
    825 			if (!STREQU(dest, rp->printer->printer->name))
    826 				continue;
    827 		}
    828 
    829 		if (*req_id && !STREQU(req_id, rp->secure->req_id))
    830 			continue;
    831 
    832 		if (*user && !bangequ(user, rp->secure->user))
    833 			continue;
    834 
    835 		if (*pwheel && !SAME(pwheel, rp->pwheel_name))
    836 			continue;
    837 		/*
    838 		 * For Trusted Extensions, we need to check the sensitivity
    839 		 * label of the connection and job before we return it to the
    840 		 * client.
    841 		 */
    842 		if ((md->admin <= 0) && (is_system_labeled()) &&
    843 		    (md->slabel != NULL) && (rp->secure->slabel != NULL) &&
    844 		    (!STREQU(md->slabel, rp->secure->slabel)))
    845 			continue;
    846 
    847 		if (found) {
    848 			GetRequestFiles(found->request, files, sizeof (files));
    849 			mputm(md, R_INQUIRE_REQUEST_RANK,
    850 			    MOKMORE,
    851 			    found->secure->req_id,
    852 			    found->request->user,
    853 			    /* bgolden 091996, bug 1257405 */
    854 			    found->secure->slabel,
    855 			    found->secure->size,
    856 			    found->secure->date,
    857 			    found->request->outcome,
    858 			    found->printer->printer->name,
    859 			    (found->form? found->form->form->name : ""),
    860 			    NB(found->pwheel_name),
    861 			    found_rank,
    862 			    files);
    863 		}
    864 		found = rp;
    865 		found_rank = found->printer->nrequests;
    866 	}
    867 
    868 	if (found) {
    869 		GetRequestFiles(found->request, files, sizeof (files));
    870 		mputm(md, R_INQUIRE_REQUEST_RANK,
    871 		    MOK,
    872 		    found->secure->req_id,
    873 		    found->request->user, /* bgolden 091996, bug 1257405 */
    874 		    found->secure->slabel,
    875 		    found->secure->size,
    876 		    found->secure->date,
    877 		    found->request->outcome,
    878 		    found->printer->printer->name,
    879 		    (found->form? found->form->form->name : ""),
    880 		    NB(found->pwheel_name),
    881 		    found_rank,
    882 		    files);
    883 	} else
    884 		mputm(md, R_INQUIRE_REQUEST_RANK, MNOINFO, "", "", "", 0L, 0L,
    885 		    0, "", "", "", 0, "");
    886 }
    887 
    888 static int
    889 mv_file(RSTATUS *rp, char *dest)
    890 {
    891 	int	stat;
    892 	char	*olddest;
    893 	EXEC	*oldexec;
    894 	SECURE * securep;
    895 	RSTATUS * prs;
    896 	char *reqno;
    897 
    898 	oldexec = rp->printer->exec;
    899 	olddest = rp->request->destination;
    900 	rp->request->destination = Strdup(dest);
    901 	if ((stat = validate_request(rp, (char **)0, 1)) == MOK) {
    902 		Free(olddest);
    903 
    904 		if (rp->request->outcome & RS_FILTERED) {
    905 			int cnt = 0;
    906 			char *reqno;
    907 			char **listp;
    908 			char tmp_nam[MAXPATHLEN];
    909 
    910 			reqno = getreqno(rp->secure->req_id);
    911 			for (listp = rp->request->file_list; *listp; listp++) {
    912 				cnt++;
    913 				snprintf(tmp_nam, sizeof (tmp_nam),
    914 				    "%s/F%s-%d", Lp_Temp, reqno, cnt);
    915 				unlink(tmp_nam);
    916 
    917 			}
    918 			rp->request->outcome &= ~RS_FILTERED;
    919 		}
    920 
    921 		/* update /var/spool/lp/tmp/<host>/nnn-0 */
    922 		if (putrequest(rp->req_file, rp->request) < 0) {
    923 			note("putrequest failed\n");
    924 			return (MNOMEM);
    925 		}
    926 
    927 		/* update /var/spool/lp/requests/<host>/nnn-0 */
    928 		if ((securep = Getsecure(rp->req_file))) {
    929 			reqno = strdup(getreqno(securep->req_id));
    930 			(void) free(securep->req_id);
    931 			if ((securep->req_id = calloc(strlen(dest) + 1 +
    932 			    strlen(reqno) +1, sizeof (char))) == NULL)
    933 				return (MNOMEM);
    934 			(void) sprintf(securep->req_id, "%s-%s", dest, reqno);
    935 			/* remove the old request file; save new one */
    936 			(void) rmsecure(rp->secure->req_id);
    937 			if (Putsecure(rp->req_file, securep) < 0) {
    938 				/* Putsecure includes note/errmessage */
    939 				return (MNOMEM);
    940 			}
    941 		} else {
    942 			note("Getsecure failed\n");
    943 			return (MNOMEM);
    944 		}
    945 
    946 		/* update internal jobs list: Request_list */
    947 		if (prs = request_by_id(rp->secure->req_id)) {
    948 			free(prs->secure->req_id);
    949 			prs->secure->req_id = strdup(securep->req_id);
    950 
    951 			/*
    952 			 * We calloc'd securep->reqid earlier, now we free it
    953 			 * here because we no longer call 'freesecure' from
    954 			 * Putsecure() if we use a static structure
    955 			 */
    956 
    957 			free(securep->req_id);
    958 		} else {
    959 			note("request_by_id failed\n");
    960 			return (MUNKNOWN);
    961 		}
    962 
    963 		/*
    964 		 * If the request was being filtered or was printing,
    965 		 * it would have been stopped in "validate_request()",
    966 		 * but only if it has to be refiltered. Thus, the
    967 		 * filtering has been stopped if it has to be stopped,
    968 		 * but the printing may still be going.
    969 		 */
    970 		if (rp->request->outcome & RS_PRINTING &&
    971 		    !(rp->request->outcome & RS_STOPPED)) {
    972 			rp->request->outcome |= RS_STOPPED;
    973 			terminate(oldexec);
    974 		}
    975 
    976 		maybe_schedule(rp);
    977 		return (MOK);
    978 	}
    979 
    980 	Free(rp->request->destination);
    981 	rp->request->destination = olddest;
    982 	return (stat);
    983 }
    984 
    985 /*
    986  * s_move_request()
    987  */
    988 
    989 void
    990 s_move_request(char *m, MESG *md)
    991 {
    992 	RSTATUS	*rp;
    993 	short	err;
    994 	char	*req_id;
    995 	char	*dest;
    996 
    997 	(void) getmessage(m, S_MOVE_REQUEST, &req_id, &dest);
    998 	syslog(LOG_DEBUG, "s_move_request(%s, %s)", (req_id ? req_id : "NULL"),
    999 	    (dest ? dest : "NULL"));
   1000 
   1001 
   1002 	if (!(search_pstatus(dest)) && !(search_cstatus(dest))) {
   1003 		mputm(md, R_MOVE_REQUEST, MNODEST, 0L);
   1004 		return;
   1005 	}
   1006 
   1007 	if ((rp = request_by_id(req_id))) {
   1008 		if (STREQU(rp->request->destination, dest)) {
   1009 			mputm(md, R_MOVE_REQUEST, MOK, 0L);
   1010 			return;
   1011 		}
   1012 		if (rp->request->outcome & (RS_DONE|RS_NOTIFYING)) {
   1013 			mputm(md, R_MOVE_REQUEST, M2LATE, 0L);
   1014 			return;
   1015 		}
   1016 		if (rp->request->outcome & RS_CHANGING)	{
   1017 			mputm(md, R_MOVE_REQUEST, MBUSY, 0L);
   1018 			return;
   1019 		}
   1020 		if ((err = mv_file(rp, dest)) == MOK) {
   1021 			mputm(md, R_MOVE_REQUEST, MOK, 0L);
   1022 			return;
   1023 		}
   1024 		mputm(md, R_MOVE_REQUEST, err, chkprinter_result);
   1025 		return;
   1026 	}
   1027 	mputm(md, R_MOVE_REQUEST, MUNKNOWN, 0L);
   1028 }
   1029 
   1030 /*
   1031  * s_move_dest()
   1032  */
   1033 
   1034 void
   1035 s_move_dest(char *m, MESG *md)
   1036 {
   1037 	char		*dest;
   1038 	char		*fromdest;
   1039 	RSTATUS		*rp;
   1040 	char		*found = (char *)0;
   1041 	short		num_ok = 0;
   1042 
   1043 	(void) getmessage(m, S_MOVE_DEST, &fromdest, &dest);
   1044 	syslog(LOG_DEBUG, "s_move_dest(%s, %s)", (fromdest ? fromdest : "NULL"),
   1045 	    (dest ? dest : "NULL"));
   1046 
   1047 	if (!search_pstatus(fromdest) && !search_cstatus(fromdest)) {
   1048 		mputm(md, R_MOVE_DEST, MNODEST, fromdest, 0);
   1049 		return;
   1050 	}
   1051 
   1052 	if (!(search_pstatus(dest)) && !(search_cstatus(dest))) {
   1053 		mputm(md, R_MOVE_DEST, MNODEST, dest, 0);
   1054 		return;
   1055 	}
   1056 
   1057 	if (STREQU(dest, fromdest)) {
   1058 		mputm(md, R_MOVE_DEST, MOK, "", 0);
   1059 		return;
   1060 	}
   1061 
   1062 	for (rp = Request_List; rp != NULL; rp = rp->next) {
   1063 		if ((STREQU(rp->request->destination, fromdest)) &&
   1064 		    (!(rp->request->outcome &
   1065 		    (RS_DONE|RS_CHANGING|RS_NOTIFYING)))) {
   1066 			if (mv_file(rp, dest) == MOK) {
   1067 				num_ok++;
   1068 				continue;
   1069 			}
   1070 		}
   1071 
   1072 		if (found)
   1073 			mputm(md, R_MOVE_DEST, MMORERR, found, 0);
   1074 
   1075 		found = rp->secure->req_id;
   1076 	}
   1077 
   1078 	if (found)
   1079 		mputm(md, R_MOVE_DEST, MERRDEST, found, num_ok);
   1080 	else
   1081 		mputm(md, R_MOVE_DEST, MOK, "", num_ok);
   1082 }
   1083 
   1084 /*
   1085  * reqpath
   1086  */
   1087 
   1088 static char *
   1089 reqpath(char *file, char **idnumber)
   1090 {
   1091 	char	*path;
   1092 	char	*cp;
   1093 	char	*cp2;
   1094 
   1095 	/*
   1096 	 *	/var/spool/lp/tmp/machine/123-0
   1097 	 *	/var/spool/lp/temp/123-0
   1098 	 *	/usr/spool/lp/temp/123-0
   1099 	 *	/usr/spool/lp/tmp/machine/123-0
   1100 	 *	123-0
   1101 	 *	machine/123-0
   1102 	 *
   1103 	 *	/var/spool/lp/tmp/machine/123-0 + 123
   1104 	 */
   1105 	if (*file == '/') {
   1106 		/*CONSTCOND*/
   1107 		if (STRNEQU(file, Lp_Spooldir, strlen(Lp_Spooldir)))
   1108 			cp = file + strlen(Lp_Spooldir) + 1;
   1109 		else {
   1110 			if (STRNEQU(file, "/usr/spool/lp", 13))
   1111 				cp = file + strlen("/usr/spool/lp") + 1;
   1112 			else {
   1113 				*idnumber = NULL;
   1114 				return (NULL);
   1115 			}
   1116 		}
   1117 
   1118 		if (STRNEQU(cp, "temp", 4)) {
   1119 			cp += 5;
   1120 			path = makepath(Local_System, cp, NULL);
   1121 		}
   1122 		else
   1123 			path = Strdup(cp);
   1124 	}
   1125 	else
   1126 	{
   1127 		if (strchr(file, '/'))
   1128 			path = makepath(file, NULL);
   1129 		else
   1130 			path = makepath(Local_System, file, NULL);
   1131 	}
   1132 
   1133 	cp = strrchr(path, '/');
   1134 	cp++;
   1135 	if ((cp2 = strrchr(cp, '-')) == NULL)
   1136 		*idnumber = Strdup(cp);
   1137 	else
   1138 	{
   1139 		*cp2 = '\0';
   1140 		*idnumber = Strdup(cp);
   1141 		*cp2 = '-';
   1142 	}
   1143 
   1144 	return (path);
   1145 }
   1146 
   1147 /*
   1148  * The client is sending a peer connection to retrieve label information
   1149  * from.  This is used in the event that the client is an intermediary for
   1150  * the actual requestor in a Trusted environment.
   1151  */
   1152 void
   1153 s_pass_peer_connection(char *m, MESG *md)
   1154 {
   1155 	short	status = MTRANSMITERR;
   1156 	char	*dest;
   1157 	struct strrecvfd recv_fd;
   1158 
   1159 	(void) getmessage(m, S_PASS_PEER_CONNECTION);
   1160 	syslog(LOG_DEBUG, "s_pass_peer_connection()");
   1161 
   1162 	memset(&recv_fd, NULL, sizeof (recv_fd));
   1163 	if (ioctl(md->readfd, I_RECVFD, &recv_fd) == 0) {
   1164 		int fd = recv_fd.fd;
   1165 
   1166 		if (get_peer_label(fd, &md->slabel) == 0) {
   1167 			if (md->admin == 1)
   1168 				md->admin = -1; /* turn off query privilege */
   1169 			status = MOK;
   1170 		}
   1171 
   1172 		close(fd);
   1173 	}
   1174 
   1175 	mputm(md, R_PASS_PEER_CONNECTION, status);
   1176 }
   1177