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