xref: /illumos-gate/usr/src/cmd/lp/cmd/lpsched/disp1.c (revision e4fb8a5fd5bb5a5d316430c6ac8f6d33704fcf5d)
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 
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)45 s_alloc_files(char *m, MESG *md)	/* funcdef */
46 {
47 	char		*file_prefix;
48 	ushort_t	count;
49 	mode_t		old_msk;
50 
51 
52 	/*
53 	 * Bugid 4140311
54 	 * Set umask to 0 before creating files.
55 	 */
56 	old_msk = umask((mode_t)0);
57 
58 	getmessage(m, S_ALLOC_FILES, &count);
59 	syslog(LOG_DEBUG, "s_alloc_files(%d)", count);
60 
61 	if ((file_prefix = _alloc_files(count, (char *)0, md->uid, md->gid))) {
62 		mputm(md, R_ALLOC_FILES, MOK, file_prefix);
63 		add_flt_act(md, FLT_FILES, file_prefix, count);
64 	} else if (errno == EEXIST)
65 		mputm(md, R_ALLOC_FILES, MERRDEST, "");
66 	else
67 		mputm(md, R_ALLOC_FILES, MNOMEM, "");
68 
69 	(void) umask(old_msk);
70 
71 }
72 
73 /*
74  * s_print_request()
75  */
76 
77 void
s_print_request(char * m,MESG * md)78 s_print_request(char *m, MESG *md)
79 {
80 	extern char		*Local_System;
81 	char			*file;
82 	char			*idno;
83 	char			*path;
84 	char			*req_file;
85 	char			*req_id	= 0;
86 	RSTATUS			*rp;
87 	REQUEST			*r;
88 	SECURE			*s;
89 	struct passwd		*pw;
90 	short			err;
91 	short			status;
92 	off_t			size;
93 	uid_t			org_uid;
94 	gid_t			org_gid;
95 #ifdef LP_USE_PAPI_ATTR
96 	struct stat		tmpBuf;
97 	char 			tmpName[BUFSIZ];
98 #endif
99 
100 
101 	(void) getmessage(m, S_PRINT_REQUEST, &file);
102 	syslog(LOG_DEBUG, "s_print_request(%s)", (file ? file : "NULL"));
103 
104 	/*
105 	 * "NewRequest" points to a request that's not yet in the
106 	 * request list but is to be considered with the rest of the
107 	 * requests (e.g. calculating # of requests awaiting a form).
108 	 */
109 	if ((rp = NewRequest = new_rstatus(NULL, NULL)) == NULL)
110 		status = MNOMEM;
111 
112 	else
113 	{
114 		req_file = reqpath(file, &idno);
115 		path = makepath(Lp_Tmp, req_file, (char *)0);
116 		(void) chownmod(path, Lp_Uid, Lp_Gid, 0644);
117 		Free(path);
118 
119 		if (!(r = Getrequest(req_file)))
120 			status = MNOOPEN;
121 
122 		else
123 		{
124 			rp->req_file = Strdup(req_file);
125 
126 			freerequest(rp->request);
127 			rp->request = r;
128 
129 			rp->request->outcome = 0;
130 			rp->secure->uid = md->uid;
131 			rp->secure->gid = md->gid;
132 			if (md->slabel != NULL)
133 				rp->secure->slabel = Strdup(md->slabel);
134 
135 			pw = getpwuid(md->uid);
136 			endpwent();
137 			if (pw && pw->pw_name && *pw->pw_name)
138 				rp->secure->user = Strdup(pw->pw_name);
139 			else {
140 				rp->secure->user = Strdup(BIGGEST_NUMBER_S);
141 				(void) sprintf(rp->secure->user, "%u",
142 				    md->uid);
143 			}
144 
145 			if ((rp->request->actions & ACT_SPECIAL) == ACT_HOLD)
146 				rp->request->outcome |= RS_HELD;
147 			if ((rp->request->actions & ACT_SPECIAL) == ACT_RESUME)
148 				rp->request->outcome &= ~RS_HELD;
149 			if ((rp->request->actions & ACT_SPECIAL) ==
150 			    ACT_IMMEDIATE) {
151 				if (!md->admin) {
152 					status = MNOPERM;
153 					goto Return;
154 				}
155 				rp->request->outcome |= RS_IMMEDIATE;
156 			}
157 
158 			size = chfiles(rp->request->file_list, Lp_Uid, Lp_Gid);
159 
160 			if (size < 0) {
161 				/*
162 				 * at this point, chfiles() may have
163 				 * failed because the file may live on
164 				 * an NFS mounted filesystem, under
165 				 * a directory of mode 700. such a
166 				 * directory isn't accessible even by
167 				 * root, according to the NFS protocol
168 				 * (i.e. the Stat() in chfiles() failed).
169 				 * this most commonly happens via the
170 				 * automounter, and rlogin. thus we
171 				 * change our euid/egid to that of the
172 				 * user, and try again. if *this* fails,
173 				 * then the file must really be
174 				 * inaccessible.
175 				 */
176 				org_uid = geteuid();
177 				org_gid = getegid();
178 
179 				if (setegid(md->gid) != 0) {
180 					status = MUNKNOWN;
181 					goto Return;
182 				}
183 
184 				if (seteuid(md->uid) != 0) {
185 					setgid(org_gid);
186 					status = MUNKNOWN;
187 					goto Return;
188 				}
189 
190 				size = chfiles(rp->request->file_list,
191 				    Lp_Uid, Lp_Gid);
192 
193 				if (seteuid(org_uid) != 0) {
194 					/* should never happen */
195 					note("s_print_request(): ");
196 					note("seteuid back to uid=%d "
197 					    "failed!!\n", org_uid);
198 					size = -1;
199 				}
200 
201 				if (setegid(org_gid) != 0) {
202 					/* should never happen */
203 					note("s_print_request(): ");
204 					note("setegid back to uid=%d "
205 					    "failed!!\n", org_uid);
206 					size = -1;
207 				}
208 
209 				if (size < 0) {
210 					status = MUNKNOWN;
211 					goto Return;
212 				}
213 			}
214 			if (!(rp->request->outcome & RS_HELD) && size == 0) {
215 				status = MNOPERM;
216 				goto Return;
217 			}
218 			rp->secure->size = size;
219 
220 			(void) time(&rp->secure->date);
221 			rp->secure->req_id = NULL;
222 
223 			if (!rp->request->title) {
224 				if (strlen(*rp->request->file_list) <
225 				    (size_t)24)
226 					rp->request->title =
227 					    Strdup(*rp->request->file_list);
228 				else {
229 					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 
321 Return:
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 
336 void
s_start_change_request(char * m,MESG * md)337 s_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 
442 void
s_end_change_request(char * m,MESG * md)443 s_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 
626 Return:
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 
647 static char *
_cancel(MESG * md,char * dest,char * user,char * req_id)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 
729 void
s_cancel_request(char * m,MESG * md)730 s_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 
749 void
s_cancel(char * m,MESG * md)750 s_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 
792 void
s_inquire_request_rank(char * m,MESG * md)793 s_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 
890 static int
mv_file(RSTATUS * rp,char * dest)891 mv_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 
991 void
s_move_request(char * m,MESG * md)992 s_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 
1036 void
s_move_dest(char * m,MESG * md)1037 s_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 
1090 static char *
reqpath(char * file,char ** idnumber)1091 reqpath(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  */
1154 void
s_pass_peer_connection(char * m,MESG * md)1155 s_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