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