/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#include "dispatch.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>
static char *reqpath(char *, char **);
static int mv_file(RSTATUS *, char *);
RSTATUS *NewRequest;
/*
* s_alloc_files()
*/
void
s_alloc_files(char *m, MESG *md) /* funcdef */
{
char *file_prefix;
ushort_t count;
mode_t old_msk;
/*
* Bugid 4140311
* Set umask to 0 before creating files.
*/
old_msk = umask((mode_t)0);
getmessage(m, S_ALLOC_FILES, &count);
syslog(LOG_DEBUG, "s_alloc_files(%d)", count);
if ((file_prefix = _alloc_files(count, (char *)0, md->uid, md->gid))) {
mputm(md, R_ALLOC_FILES, MOK, file_prefix);
add_flt_act(md, FLT_FILES, file_prefix, count);
} else if (errno == EEXIST)
mputm(md, R_ALLOC_FILES, MERRDEST, "");
else
mputm(md, R_ALLOC_FILES, MNOMEM, "");
(void) umask(old_msk);
}
/*
* s_print_request()
*/
void
s_print_request(char *m, MESG *md)
{
extern char *Local_System;
char *file;
char *idno;
char *path;
char *req_file;
char *req_id = 0;
RSTATUS *rp;
REQUEST *r;
SECURE *s;
struct passwd *pw;
short err;
short status;
off_t size;
uid_t org_uid;
gid_t org_gid;
#ifdef LP_USE_PAPI_ATTR
struct stat tmpBuf;
char tmpName[BUFSIZ];
#endif
(void) getmessage(m, S_PRINT_REQUEST, &file);
syslog(LOG_DEBUG, "s_print_request(%s)", (file ? file : "NULL"));
/*
* "NewRequest" points to a request that's not yet in the
* request list but is to be considered with the rest of the
* requests (e.g. calculating # of requests awaiting a form).
*/
if ((rp = NewRequest = new_rstatus(NULL, NULL)) == NULL)
status = MNOMEM;
else
{
req_file = reqpath(file, &idno);
path = makepath(Lp_Tmp, req_file, (char *)0);
(void) chownmod(path, Lp_Uid, Lp_Gid, 0644);
Free(path);
if (!(r = Getrequest(req_file)))
status = MNOOPEN;
else
{
rp->req_file = Strdup(req_file);
freerequest(rp->request);
rp->request = r;
rp->request->outcome = 0;
rp->secure->uid = md->uid;
rp->secure->gid = md->gid;
if (md->slabel != NULL)
rp->secure->slabel = Strdup(md->slabel);
pw = getpwuid(md->uid);
endpwent();
if (pw && pw->pw_name && *pw->pw_name)
rp->secure->user = Strdup(pw->pw_name);
else {
rp->secure->user = Strdup(BIGGEST_NUMBER_S);
(void) sprintf(rp->secure->user, "%u",
md->uid);
}
if ((rp->request->actions & ACT_SPECIAL) == ACT_HOLD)
rp->request->outcome |= RS_HELD;
if ((rp->request->actions & ACT_SPECIAL) == ACT_RESUME)
rp->request->outcome &= ~RS_HELD;
if ((rp->request->actions & ACT_SPECIAL) ==
ACT_IMMEDIATE) {
if (!md->admin) {
status = MNOPERM;
goto Return;
}
rp->request->outcome |= RS_IMMEDIATE;
}
size = chfiles(rp->request->file_list, Lp_Uid, Lp_Gid);
if (size < 0) {
/*
* at this point, chfiles() may have
* failed because the file may live on
* an NFS mounted filesystem, under
* a directory of mode 700. such a
* directory isn't accessible even by
* root, according to the NFS protocol
* (i.e. the Stat() in chfiles() failed).
* this most commonly happens via the
* automounter, and rlogin. thus we
* change our euid/egid to that of the
* user, and try again. if *this* fails,
* then the file must really be
* inaccessible.
*/
org_uid = geteuid();
org_gid = getegid();
if (setegid(md->gid) != 0) {
status = MUNKNOWN;
goto Return;
}
if (seteuid(md->uid) != 0) {
setgid(org_gid);
status = MUNKNOWN;
goto Return;
}
size = chfiles(rp->request->file_list,
Lp_Uid, Lp_Gid);
if (seteuid(org_uid) != 0) {
/* should never happen */
note("s_print_request(): ");
note("seteuid back to uid=%d "
"failed!!\n", org_uid);
size = -1;
}
if (setegid(org_gid) != 0) {
/* should never happen */
note("s_print_request(): ");
note("setegid back to uid=%d "
"failed!!\n", org_uid);
size = -1;
}
if (size < 0) {
status = MUNKNOWN;
goto Return;
}
}
if (!(rp->request->outcome & RS_HELD) && size == 0) {
status = MNOPERM;
goto Return;
}
rp->secure->size = size;
(void) time(&rp->secure->date);
rp->secure->req_id = NULL;
if (!rp->request->title) {
if (strlen(*rp->request->file_list) <
(size_t)24)
rp->request->title =
Strdup(*rp->request->file_list);
else {
char *r;
if (r = strrchr(
*rp->request->file_list, '/'))
r++;
else
r = *rp->request->file_list;
rp->request->title = malloc(25);
sprintf(rp->request->title,
"%-.24s", r);
}
}
if ((err = validate_request(rp, &req_id, 0)) != MOK)
status = err;
else {
/*
* "req_id" will be supplied if this is from a
* remote system.
*/
if (rp->secure->req_id == NULL) {
req_id = makestr(req_id, "-",
idno, (char *)0);
rp->secure->req_id = req_id;
} else
req_id = rp->secure->req_id;
#ifdef LP_USE_PAPI_ATTR
/*
* Check if the PAPI job attribute file
* exists, if it does change the
* permissions and ownership of the file.
* This file is created when print jobs
* are submitted via the PAPI interface,
* the file pathname of this file is
* passed to the slow-filters and printer
* interface script as an environment
* variable when they are executed
*/
snprintf(tmpName, sizeof (tmpName),
"%s-%s", idno, LP_PAPIATTRNAME);
path = makepath(Lp_Temp, tmpName, (char *)0);
if (stat(path, &tmpBuf) == 0) {
syslog(LOG_DEBUG,
"s_print_request: "\
"attribute file ='%s'", path);
/*
* IPP job attribute file exists
* for this job so change
* permissions and ownership of
* the file
*/
(void) chownmod(path, Lp_Uid,
Lp_Gid, 0644);
Free(path);
}
else
{
syslog(LOG_DEBUG,
"s_print_request: "\
"no attribute file");
}
#endif
/*
* fix for bugid 1103890.
* use Putsecure instead.
*/
if ((Putsecure(req_file, rp->secure) == -1) ||
(putrequest(req_file, rp->request) == -1))
status = MNOMEM;
else
{
status = MOK;
insertr(rp);
NewRequest = 0;
if (rp->slow)
schedule(EV_SLOWF, rp);
else
schedule(EV_INTERF,
rp->printer);
del_flt_act(md, FLT_FILES);
}
}
}
}
Return:
NewRequest = 0;
Free(req_file);
Free(idno);
if (status != MOK && rp) {
rmfiles(rp, 0);
free_rstatus(rp);
}
mputm(md, R_PRINT_REQUEST, status, NB(req_id), chkprinter_result);
}
/*
* s_start_change_request()
*/
void
s_start_change_request(char *m, MESG *md)
{
char *req_id;
char *req_file = "";
short status;
RSTATUS *rp;
char *path;
char tmpName[BUFSIZ];
struct stat tmpBuf;
(void) getmessage(m, S_START_CHANGE_REQUEST, &req_id);
syslog(LOG_DEBUG, "s_start_change_request(%s)",
(req_id ? req_id : "NULL"));
if (!(rp = request_by_id(req_id)))
status = MUNKNOWN;
else if ((md->admin == 0) && (is_system_labeled()) &&
(md->slabel != NULL) && (rp->secure->slabel != NULL) &&
(!STREQU(md->slabel, rp->secure->slabel)))
status = MUNKNOWN;
else if (rp->request->outcome & RS_DONE)
status = M2LATE;
else if (!md->admin && md->uid != rp->secure->uid)
status = MNOPERM;
else if (rp->request->outcome & RS_CHANGING)
status = MNOOPEN;
else if (rp->request->outcome & RS_NOTIFYING)
status = MBUSY;
else {
status = MOK;
if (rp->request->outcome & RS_FILTERING &&
!(rp->request->outcome & RS_STOPPED)) {
rp->request->outcome |= (RS_REFILTER|RS_STOPPED);
terminate(rp->exec);
}
if (rp->request->outcome & RS_PRINTING &&
!(rp->request->outcome & RS_STOPPED)) {
rp->request->outcome |= RS_STOPPED;
terminate(rp->printer->exec);
}
rp->request->outcome |= RS_CHANGING;
/*
* Change the ownership of the request file to be "md->uid".
* Either this is identical to "rp->secure->uid", or it is
* "Lp_Uid" or it is root. The idea is that the
* person at the other end needs access, and that may not
* be who queued the request.
*/
path = makepath(Lp_Tmp, rp->req_file, (char *)0);
(void) Chown(path, md->uid, rp->secure->gid);
Free(path);
#ifdef LP_USE_PAPI_ATTR
/*
* Check if the PAPI job attribute file exists, if it does
* change the ownership of the file to be "md->uid".
* Either this is identical to "rp->secure->uid", or it is
* "Lp_Uid" or it is root. The idea is that the
* person at the other end needs access, and that may not
* be who queued the request.
*/
snprintf(tmpName, sizeof (tmpName),
"%s-%s", strtok(strdup(rp->req_file), "-"),
LP_PAPIATTRNAME);
path = makepath(Lp_Tmp, tmpName, (char *)0);
if (stat(path, &tmpBuf) == 0) {
syslog(LOG_DEBUG,
"s_start_change_request: attribute file ='%s'",
path);
/*
* IPP job attribute file exists for this job so
* change permissions and ownership of the file
*/
(void) Chown(path, md->uid, rp->secure->gid);
Free(path);
}
else
{
syslog(LOG_DEBUG,
"s_start_change_request: no attribute file");
}
#endif
add_flt_act(md, FLT_CHANGE, rp);
req_file = rp->req_file;
}
mputm(md, R_START_CHANGE_REQUEST, status, req_file);
}
/*
* s_end_change_request()
*/
void
s_end_change_request(char *m, MESG *md)
{
char *req_id;
RSTATUS *rp;
off_t size;
off_t osize;
short err;
short status;
REQUEST *r = 0;
REQUEST oldr;
int call_schedule = 0;
int move_ok = 0;
char *path;
char tmpName[BUFSIZ];
struct stat tmpBuf;
(void) getmessage(m, S_END_CHANGE_REQUEST, &req_id);
syslog(LOG_DEBUG, "s_end_change_request(%s)",
(req_id ? req_id : "NULL"));
if (!(rp = request_by_id(req_id)))
status = MUNKNOWN;
else if ((md->admin == 0) && (is_system_labeled()) &&
(md->slabel != NULL) && (rp->secure->slabel != NULL) &&
(!STREQU(md->slabel, rp->secure->slabel)))
status = MUNKNOWN;
else if (!(rp->request->outcome & RS_CHANGING))
status = MNOSTART;
else {
path = makepath(Lp_Tmp, rp->req_file, (char *)0);
(void) chownmod(path, Lp_Uid, Lp_Gid, 0644);
Free(path);
#ifdef LP_USE_PAPI_ATTR
/*
* Check if the PAPI job attribute file exists,
* if it does change the permission and the ownership
* of the file to be "Lp_Uid".
*/
snprintf(tmpName, sizeof (tmpName),
"%s-%s", strtok(strdup(rp->req_file), "-"),
LP_PAPIATTRNAME);
path = makepath(Lp_Tmp, tmpName, (char *)0);
if (stat(path, &tmpBuf) == 0) {
syslog(LOG_DEBUG,
"s_end_change_request: attribute file ='%s'",
path);
/*
* IPP job attribute file exists for this job so
* change permissions and ownership of the file
*/
(void) chownmod(path, Lp_Uid, Lp_Gid, 0644);
Free(path);
}
else
{
syslog(LOG_DEBUG,
"s_end_change_request: no attribute file");
}
#endif
rp->request->outcome &= ~(RS_CHANGING);
del_flt_act(md, FLT_CHANGE);
/*
* The RS_CHANGING bit may have been the only thing
* preventing this request from filtering or printing,
* so regardless of what happens below,
* we must check to see if the request can proceed.
*/
call_schedule = 1;
if (!(r = Getrequest(rp->req_file)))
status = MNOOPEN;
else {
oldr = *(rp->request);
*(rp->request) = *r;
move_ok =
STREQU(oldr.destination, r->destination);
/*
* Preserve the current request status!
*/
rp->request->outcome = oldr.outcome;
/*
* Here's an example of the dangers one meets
* when public flags are used for private
* purposes. ".actions" (indeed, anything in the
* REQUEST structure) is set by the person
* changing the job. However, lpsched uses
* ".actions" as place to indicate that a job
* came from a remote system and we must send
* back job completion--this is a strictly
* private flag that we must preserve.
*/
rp->request->actions |=
(oldr.actions & ACT_NOTIFY);
if ((rp->request->actions & ACT_SPECIAL) ==
ACT_HOLD) {
rp->request->outcome |= RS_HELD;
/*
* To be here means either the user owns
* the request or he or she is the
* administrator. Since we don't want to
* set the RS_ADMINHELD flag if the user
* is the administrator, the following
* compare will work.
*/
if (md->uid != rp->secure->uid)
rp->request->outcome |=
RS_ADMINHELD;
}
if ((rp->request->actions & ACT_SPECIAL) ==
ACT_RESUME) {
if ((rp->request->outcome & RS_ADMINHELD) &&
!md->admin) {
status = MNOPERM;
goto Return;
}
rp->request->outcome &=
~(RS_ADMINHELD|RS_HELD);
}
if ((rp->request->actions & ACT_SPECIAL)
== ACT_IMMEDIATE) {
if (!md->admin) {
status = MNOPERM;
goto Return;
}
rp->request->outcome |= RS_IMMEDIATE;
}
size = chfiles(rp->request->file_list, Lp_Uid,
Lp_Gid);
if (size < 0) {
status = MUNKNOWN;
goto Return;
}
if (!(rp->request->outcome & RS_HELD) &&
size == 0) {
status = MNOPERM;
goto Return;
}
osize = rp->secure->size;
rp->secure->size = size;
if (move_ok == 0) {
char *dest = strdup(r->destination);
if ((status = mv_file(rp, dest)) == MOK)
rp->secure->size = osize;
free(dest);
} else if ((err = validate_request(rp, (char **)0,
move_ok)) != MOK) {
status = err;
rp->secure->size = osize;
} else {
status = MOK;
if ((rp->request->outcome & RS_IMMEDIATE) ||
(rp->request->priority != oldr.priority)) {
remover(rp);
insertr(rp);
}
freerequest(&oldr);
(void) putrequest(rp->req_file, rp->request);
/*
* fix for bugid 1103890.
* use Putsecure instead.
*/
(void) Putsecure(rp->req_file, rp->secure);
}
}
}
Return:
if (status != MOK && rp) {
if (r) {
freerequest(r);
*(rp->request) = oldr;
}
if (status != MNOSTART)
(void) putrequest(rp->req_file, rp->request);
}
if (call_schedule)
maybe_schedule(rp);
mputm(md, R_END_CHANGE_REQUEST, status, chkprinter_result);
}
/*
* _cancel()
* user may be (host!user)
*/
static char *
_cancel(MESG *md, char *dest, char *user, char *req_id)
{
static RSTATUS *rp;
static char *s_dest;
static char *s_user;
static char *s_req_id;
static int current;
RSTATUS *crp;
char *creq_id;
syslog(LOG_DEBUG, "_cancel(%s, %s, %s)", (dest ? dest : "NULL"),
(user ? user : "NULL"), (req_id ? req_id : "NULL"));
if (dest || user || req_id) {
s_dest = dest;
if (STREQU(user, "!"))
s_user = strdup("all!all");
else
s_user = user;
s_req_id = req_id;
rp = Request_List;
current = 0;
if (STREQU(s_req_id, CURRENT_REQ)) {
current = 1;
s_req_id = NULL;
}
}
while (rp != NULL) {
crp = rp;
rp = rp->next;
if (*s_dest && !STREQU(s_dest, crp->request->destination))
continue;
if (current && !(crp->request->outcome & RS_PRINTING))
continue;
if (s_req_id && *s_req_id &&
!STREQU(s_req_id, crp->secure->req_id))
continue;
if (*s_user && !bangequ(s_user, crp->secure->user))
continue;
if (!md->admin && md->uid != crp->secure->uid) {
errno = MNOPERM;
return (Strdup(crp->secure->req_id));
}
/*
* For Trusted Extensions, we need to check the
* sensitivity label of the
* connection and job before we try to cancel it.
*/
if ((md->admin == 0) && (is_system_labeled()) &&
(md->slabel != NULL) && (crp->secure->slabel != NULL) &&
(!STREQU(md->slabel, crp->secure->slabel)))
continue;
crp->reason = MOK;
creq_id = Strdup(crp->secure->req_id);
syslog(LOG_DEBUG, "cancel reqid (%s) uid: %d, secureuid: %d",
creq_id, md->uid, crp->secure->uid);
if (cancel(crp, (md->uid != crp->secure->uid)))
errno = MOK;
else
errno = M2LATE;
return (creq_id);
}
errno = MUNKNOWN;
return (NULL);
}
/*
* s_cancel_request()
*/
void
s_cancel_request(char *m, MESG *md)
{
char *req_id, *rid;
short status;
(void) getmessage(m, S_CANCEL_REQUEST, &req_id);
syslog(LOG_DEBUG, "s_cancel_request(%s)", (req_id ? req_id : "NULL"));
if ((rid = _cancel(md, "", "", req_id)) != NULL)
Free(rid);
status = (short)errno;
mputm(md, R_CANCEL_REQUEST, status);
}
/*
* s_cancel()
*/
void
s_cancel(char *m, MESG *md)
{
char *req_id;
char *user;
char *destination;
char *rid;
char *nrid;
int nerrno;
int oerrno;
(void) getmessage(m, S_CANCEL, &destination, &user, &req_id);
syslog(LOG_DEBUG, "s_cancel(%s, %s, %s)",
(destination ? destination : "NULL"), (user ? user : "NULL"),
(req_id ? req_id : "NULL"));
if (STREQU(destination, NAME_ALL))
destination = "";
if (STREQU(req_id, NAME_ALL))
req_id = "";
if (rid = _cancel(md, destination, user, req_id)) {
oerrno = errno;
while ((nrid = _cancel(md, NULL, NULL, NULL)) != NULL) {
nerrno = errno;
mputm(md, R_CANCEL, MOKMORE, oerrno, rid);
Free(rid);
rid = nrid;
oerrno = nerrno;
}
mputm(md, R_CANCEL, MOK, oerrno, rid);
Free(rid);
return;
}
mputm(md, R_CANCEL, MOK, MUNKNOWN, "");
}
/*
* s_inquire_request_rank()
*/
void
s_inquire_request_rank(char *m, MESG *md)
{
char *form;
char *dest;
char *pwheel;
char *user;
char *req_id;
RSTATUS *rp;
RSTATUS *found = NULL;
int found_rank = 0;
short prop;
char files[BUFSIZ];
int i;
(void) getmessage(m, S_INQUIRE_REQUEST_RANK, &prop, &form, &dest,
&req_id, &user, &pwheel);
syslog(LOG_DEBUG, "s_inquire_request_rank(%d, %s, %s, %s, %s, %s)",
prop, (form ? form : "NULL"), (dest ? dest : "NULL"),
(req_id ? req_id : "NULL"), (user ? user : "NULL"),
(pwheel ? pwheel : "NULL"));
for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++)
PStatus[i]->nrequests = 0;
for (rp = Request_List; rp != NULL; rp = rp->next) {
if (rp->printer && !(rp->request->outcome & RS_DONE))
rp->printer->nrequests++;
if (*form && !SAME(form, rp->request->form))
continue;
if (*dest && !STREQU(dest, rp->request->destination)) {
if (!rp->printer)
continue;
if (!STREQU(dest, rp->printer->printer->name))
continue;
}
if (*req_id && !STREQU(req_id, rp->secure->req_id))
continue;
if (*user && !bangequ(user, rp->secure->user))
continue;
if (*pwheel && !SAME(pwheel, rp->pwheel_name))
continue;
/*
* For Trusted Extensions, we need to check the sensitivity
* label of the connection and job before we return it to the
* client.
*/
if ((md->admin <= 0) && (is_system_labeled()) &&
(md->slabel != NULL) && (rp->secure->slabel != NULL) &&
(!STREQU(md->slabel, rp->secure->slabel)))
continue;
if (found) {
GetRequestFiles(found->request, files, sizeof (files));
mputm(md, R_INQUIRE_REQUEST_RANK,
MOKMORE,
found->secure->req_id,
found->request->user,
/* bgolden 091996, bug 1257405 */
found->secure->slabel,
found->secure->size,
found->secure->date,
found->request->outcome,
found->printer->printer->name,
(found->form? found->form->form->name : ""),
NB(found->pwheel_name),
found_rank,
files);
}
found = rp;
found_rank = found->printer->nrequests;
}
if (found) {
GetRequestFiles(found->request, files, sizeof (files));
mputm(md, R_INQUIRE_REQUEST_RANK,
MOK,
found->secure->req_id,
found->request->user, /* bgolden 091996, bug 1257405 */
found->secure->slabel,
found->secure->size,
found->secure->date,
found->request->outcome,
found->printer->printer->name,
(found->form? found->form->form->name : ""),
NB(found->pwheel_name),
found_rank,
files);
} else
mputm(md, R_INQUIRE_REQUEST_RANK, MNOINFO, "", "", "", 0L, 0L,
0, "", "", "", 0, "");
}
static int
mv_file(RSTATUS *rp, char *dest)
{
int stat;
char *olddest;
EXEC *oldexec;
SECURE * securep;
RSTATUS * prs;
char *reqno;
oldexec = rp->printer->exec;
olddest = rp->request->destination;
rp->request->destination = Strdup(dest);
if ((stat = validate_request(rp, (char **)0, 1)) == MOK) {
Free(olddest);
if (rp->request->outcome & RS_FILTERED) {
int cnt = 0;
char *reqno;
char **listp;
char tmp_nam[MAXPATHLEN];
reqno = getreqno(rp->secure->req_id);
for (listp = rp->request->file_list; *listp; listp++) {
cnt++;
snprintf(tmp_nam, sizeof (tmp_nam),
"%s/F%s-%d", Lp_Temp, reqno, cnt);
unlink(tmp_nam);
}
rp->request->outcome &= ~RS_FILTERED;
}
/* update /var/spool/lp/tmp/<host>/nnn-0 */
if (putrequest(rp->req_file, rp->request) < 0) {
note("putrequest failed\n");
return (MNOMEM);
}
/* update /var/spool/lp/requests/<host>/nnn-0 */
if ((securep = Getsecure(rp->req_file))) {
reqno = strdup(getreqno(securep->req_id));
(void) free(securep->req_id);
if ((securep->req_id = calloc(strlen(dest) + 1 +
strlen(reqno) +1, sizeof (char))) == NULL)
return (MNOMEM);
(void) sprintf(securep->req_id, "%s-%s", dest, reqno);
/* remove the old request file; save new one */
(void) rmsecure(rp->secure->req_id);
if (Putsecure(rp->req_file, securep) < 0) {
/* Putsecure includes note/errmessage */
return (MNOMEM);
}
} else {
note("Getsecure failed\n");
return (MNOMEM);
}
/* update internal jobs list: Request_list */
if (prs = request_by_id(rp->secure->req_id)) {
free(prs->secure->req_id);
prs->secure->req_id = strdup(securep->req_id);
/*
* We calloc'd securep->reqid earlier, now we free it
* here because we no longer call 'freesecure' from
* Putsecure() if we use a static structure
*/
free(securep->req_id);
} else {
note("request_by_id failed\n");
return (MUNKNOWN);
}
/*
* If the request was being filtered or was printing,
* it would have been stopped in "validate_request()",
* but only if it has to be refiltered. Thus, the
* filtering has been stopped if it has to be stopped,
* but the printing may still be going.
*/
if (rp->request->outcome & RS_PRINTING &&
!(rp->request->outcome & RS_STOPPED)) {
rp->request->outcome |= RS_STOPPED;
terminate(oldexec);
}
maybe_schedule(rp);
return (MOK);
}
Free(rp->request->destination);
rp->request->destination = olddest;
return (stat);
}
/*
* s_move_request()
*/
void
s_move_request(char *m, MESG *md)
{
RSTATUS *rp;
short err;
char *req_id;
char *dest;
(void) getmessage(m, S_MOVE_REQUEST, &req_id, &dest);
syslog(LOG_DEBUG, "s_move_request(%s, %s)", (req_id ? req_id : "NULL"),
(dest ? dest : "NULL"));
if (!(search_pstatus(dest)) && !(search_cstatus(dest))) {
mputm(md, R_MOVE_REQUEST, MNODEST, 0L);
return;
}
if ((rp = request_by_id(req_id))) {
if (STREQU(rp->request->destination, dest)) {
mputm(md, R_MOVE_REQUEST, MOK, 0L);
return;
}
if (rp->request->outcome & (RS_DONE|RS_NOTIFYING)) {
mputm(md, R_MOVE_REQUEST, M2LATE, 0L);
return;
}
if (rp->request->outcome & RS_CHANGING) {
mputm(md, R_MOVE_REQUEST, MBUSY, 0L);
return;
}
if ((err = mv_file(rp, dest)) == MOK) {
mputm(md, R_MOVE_REQUEST, MOK, 0L);
return;
}
mputm(md, R_MOVE_REQUEST, err, chkprinter_result);
return;
}
mputm(md, R_MOVE_REQUEST, MUNKNOWN, 0L);
}
/*
* s_move_dest()
*/
void
s_move_dest(char *m, MESG *md)
{
char *dest;
char *fromdest;
RSTATUS *rp;
char *found = (char *)0;
short num_ok = 0;
(void) getmessage(m, S_MOVE_DEST, &fromdest, &dest);
syslog(LOG_DEBUG, "s_move_dest(%s, %s)", (fromdest ? fromdest : "NULL"),
(dest ? dest : "NULL"));
if (!search_pstatus(fromdest) && !search_cstatus(fromdest)) {
mputm(md, R_MOVE_DEST, MNODEST, fromdest, 0);
return;
}
if (!(search_pstatus(dest)) && !(search_cstatus(dest))) {
mputm(md, R_MOVE_DEST, MNODEST, dest, 0);
return;
}
if (STREQU(dest, fromdest)) {
mputm(md, R_MOVE_DEST, MOK, "", 0);
return;
}
for (rp = Request_List; rp != NULL; rp = rp->next) {
if ((STREQU(rp->request->destination, fromdest)) &&
(!(rp->request->outcome &
(RS_DONE|RS_CHANGING|RS_NOTIFYING)))) {
if (mv_file(rp, dest) == MOK) {
num_ok++;
continue;
}
}
if (found)
mputm(md, R_MOVE_DEST, MMORERR, found, 0);
found = rp->secure->req_id;
}
if (found)
mputm(md, R_MOVE_DEST, MERRDEST, found, num_ok);
else
mputm(md, R_MOVE_DEST, MOK, "", num_ok);
}
/*
* reqpath
*/
static char *
reqpath(char *file, char **idnumber)
{
char *path;
char *cp;
char *cp2;
/*
* /var/spool/lp/tmp/machine/123-0
* /var/spool/lp/temp/123-0
* /usr/spool/lp/temp/123-0
* /usr/spool/lp/tmp/machine/123-0
* 123-0
* machine/123-0
*
* /var/spool/lp/tmp/machine/123-0 + 123
*/
if (*file == '/') {
/*CONSTCOND*/
if (STRNEQU(file, Lp_Spooldir, strlen(Lp_Spooldir)))
cp = file + strlen(Lp_Spooldir) + 1;
else {
if (STRNEQU(file, "/usr/spool/lp", 13))
cp = file + strlen("/usr/spool/lp") + 1;
else {
*idnumber = NULL;
return (NULL);
}
}
if (STRNEQU(cp, "temp", 4)) {
cp += 5;
path = makepath(Local_System, cp, NULL);
}
else
path = Strdup(cp);
}
else
{
if (strchr(file, '/'))
path = makepath(file, NULL);
else
path = makepath(Local_System, file, NULL);
}
cp = strrchr(path, '/');
cp++;
if ((cp2 = strrchr(cp, '-')) == NULL)
*idnumber = Strdup(cp);
else
{
*cp2 = '\0';
*idnumber = Strdup(cp);
*cp2 = '-';
}
return (path);
}
/*
* The client is sending a peer connection to retrieve label information
* from. This is used in the event that the client is an intermediary for
* the actual requestor in a Trusted environment.
*/
void
s_pass_peer_connection(char *m, MESG *md)
{
short status = MTRANSMITERR;
char *dest;
struct strrecvfd recv_fd;
(void) getmessage(m, S_PASS_PEER_CONNECTION);
syslog(LOG_DEBUG, "s_pass_peer_connection()");
memset(&recv_fd, NULL, sizeof (recv_fd));
if (ioctl(md->readfd, I_RECVFD, &recv_fd) == 0) {
int fd = recv_fd.fd;
if (get_peer_label(fd, &md->slabel) == 0) {
if (md->admin == 1)
md->admin = -1; /* turn off query privilege */
status = MOK;
}
close(fd);
}
mputm(md, R_PASS_PEER_CONNECTION, status);
}