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