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