summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/lpr/SMM.doc/0.t18
-rw-r--r--usr.sbin/lpr/SMM.doc/2.t6
-rw-r--r--usr.sbin/lpr/SMM.doc/3.t46
-rw-r--r--usr.sbin/lpr/SMM.doc/4.t17
-rw-r--r--usr.sbin/lpr/SMM.doc/5.t4
-rw-r--r--usr.sbin/lpr/SMM.doc/6.t12
-rw-r--r--usr.sbin/lpr/SMM.doc/7.t8
-rw-r--r--usr.sbin/lpr/SMM.doc/spell.ok2
-rw-r--r--usr.sbin/lpr/common_source/common.c59
-rw-r--r--usr.sbin/lpr/common_source/common_vars.c7
-rw-r--r--usr.sbin/lpr/common_source/displayq.c80
-rw-r--r--usr.sbin/lpr/common_source/lp.h24
-rw-r--r--usr.sbin/lpr/common_source/rmjob.c72
-rw-r--r--usr.sbin/lpr/common_source/startdaemon.c14
-rw-r--r--usr.sbin/lpr/lpc/cmds.c140
-rw-r--r--usr.sbin/lpr/lpc/lpc.84
-rw-r--r--usr.sbin/lpr/lpc/lpc.c16
-rw-r--r--usr.sbin/lpr/lpd/Makefile4
-rw-r--r--usr.sbin/lpr/lpd/lpd.c81
-rw-r--r--usr.sbin/lpr/lpd/printjob.c140
-rw-r--r--usr.sbin/lpr/lpd/recvjob.c24
-rw-r--r--usr.sbin/lpr/lpq/Makefile5
-rw-r--r--usr.sbin/lpr/lpq/lpq.c14
-rw-r--r--usr.sbin/lpr/lpr/Makefile4
-rw-r--r--usr.sbin/lpr/lpr/lpr.c92
-rw-r--r--usr.sbin/lpr/lprm/Makefile5
-rw-r--r--usr.sbin/lpr/lprm/lprm.c15
-rw-r--r--usr.sbin/lpr/pac/pac.c12
28 files changed, 563 insertions, 362 deletions
diff --git a/usr.sbin/lpr/SMM.doc/0.t b/usr.sbin/lpr/SMM.doc/0.t
index fa37273edf2..ef3353c53f3 100644
--- a/usr.sbin/lpr/SMM.doc/0.t
+++ b/usr.sbin/lpr/SMM.doc/0.t
@@ -1,4 +1,4 @@
-.\" $OpenBSD: 0.t,v 1.2 1997/01/17 15:54:15 millert Exp $
+.\" $OpenBSD: 0.t,v 1.3 2002/06/08 01:53:42 millert Exp $
.\"
.\" Copyright (c) 1983, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -35,9 +35,9 @@
.\"
.if n .ND
.TL
-4.3BSD Line Printer Spooler Manual
-.EH 'SMM:7-%''4.3BSD Line Printer Spooler Manual'
-.OH '4.3BSD Line Printer Spooler Manual''SMM:7-%'
+OpenBSD Line Printer Spooler Manual
+.EH 'SMM:7-%''OpenBSD Line Printer Spooler Manual'
+.OH 'OpenBSD Line Printer Spooler Manual''SMM:7-%'
.AU
Ralph Campbell
.AI
@@ -47,20 +47,16 @@ Department of Electrical Engineering and Computer Science
University of California, Berkeley
Berkeley, CA 94720
.AB
-.FS
-* UNIX is a trademark of Bell Laboratories.
-.FE
This document describes the structure and installation procedure
-for the line printer spooling system
-developed for the 4.3BSD version
-of the UNIX* operating system.
+for the line printer spooling system included with the OpenBSD
+operating system.
.de D?
.ie \\n(.$>1 Revised \\$1 \\$2 \\$3
.el DRAFT of \n(mo/\n(dy/\n(yr
..
.sp 2
.LP
-.D? June 8, 1993
+.D? May 31, 2002
.AE
.de IR
\fI\\$1\fP\\$2
diff --git a/usr.sbin/lpr/SMM.doc/2.t b/usr.sbin/lpr/SMM.doc/2.t
index 9006ed037cf..c093bbc2cec 100644
--- a/usr.sbin/lpr/SMM.doc/2.t
+++ b/usr.sbin/lpr/SMM.doc/2.t
@@ -1,4 +1,4 @@
-.\" $OpenBSD: 2.t,v 1.3 2002/05/18 23:03:04 millert Exp $
+.\" $OpenBSD: 2.t,v 1.4 2002/06/08 01:53:43 millert Exp $
.\"
.\" Copyright (c) 1983, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -51,7 +51,7 @@ database restarting any printers that have jobs.
In normal operation
.I lpd
listens for service requests on multiple sockets,
-one in the UNIX domain (named ``/var/run/printer'') for
+one in the LOCAL domain (named ``/var/run/printer'') for
local requests, and one in the Internet domain
(under the ``printer'' service specification)
for requests for printer access from off machine;
@@ -67,7 +67,7 @@ Clients communicate with
using a simple transaction oriented protocol.
Authentication of remote clients is done based
on the ``privilege port'' scheme employed by
-\fIrshd\fP\|(8C) and \fIrcmd\fP\|(3X).
+\fIrshd\fP\|(8) and \fIrcmd\fP\|(3).
The following table shows the requests
understood by
.IR lpd .
diff --git a/usr.sbin/lpr/SMM.doc/3.t b/usr.sbin/lpr/SMM.doc/3.t
index 9fa0c94581f..0b1ea2d5973 100644
--- a/usr.sbin/lpr/SMM.doc/3.t
+++ b/usr.sbin/lpr/SMM.doc/3.t
@@ -1,4 +1,4 @@
-.\" $OpenBSD: 3.t,v 1.2 1997/01/17 15:54:16 millert Exp $
+.\" $OpenBSD: 3.t,v 1.3 2002/06/08 01:53:43 millert Exp $
.\"
.\" Copyright (c) 1983, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -42,34 +42,26 @@ remove files other than their own.
The strategy used to maintain protected
spooling areas is as follows:
.IP \(bu 3
-The spooling area is writable only by a \fIdaemon\fP user
-and \fIdaemon\fP group.
+The spooling area is writable only by \fIroot\fP and
+and the \fIdaemon\fP group.
.IP \(bu 3
-The \fIlpr\fP program runs set-user-id to \fIroot\fP and
-set-group-id to group \fIdaemon\fP. The \fIroot\fP access permits
-reading any file required. Accessibility is verified
-with an \fIaccess\fP\|(2) call. The group ID
-is used in setting up proper ownership of files
-in the spooling area for \fIlprm\fP.
+The \fIlpr\fP program runs set-user-id to user \fIdaemon\fP and
+set-group-id to group \fIdaemon\fP.
.IP \(bu 3
-Control files in a spooling area are made with \fIdaemon\fP
+The utility programs,
+\fIlpc\fP, \fIlpq\fP and \fIlprm\fP run set-group-id to group \fIdaemon\fP
+to access spool files.
+.IP \(bu 3
+Control and data files in a spooling area are made with \fIdaemon\fP
ownership and group ownership \fIdaemon\fP. Their mode is 0660.
-This insures control files are not modified by a user
+This ensures control files are not modified by a user
and that no user can remove files except through \fIlprm\fP.
.IP \(bu 3
-The spooling programs,
-\fIlpd\fP, \fIlpq\fP, and \fIlprm\fP run set-user-id to \fIroot\fP
-and set-group-id to group \fIdaemon\fP to access spool files and printers.
-.IP \(bu 3
-The printer server, \fIlpd\fP,
-uses the same verification procedures as \fIrshd\fP\|(8C)
-in authenticating remote clients. The host on which a client
-resides must be present in the file /etc/hosts.equiv or /etc/hosts.lpd and
-the request message must come from a reserved port number.
-.PP
-In practice, none of \fIlpd\fP, \fIlpq\fP, or
-\fIlprm\fP would have to run as user \fIroot\fP if remote
-spooling were not supported. In previous incarnations of
-the printer system \fIlpd\fP ran set-user-id to \fIdaemon\fP,
-set-group-id to group \fIspooling\fP, and \fIlpq\fP and \fIlprm\fP ran
-set-group-id to group \fIspooling\fP.
+The printer server, \fIlpd\fP, runs as \fIroot\fP but spends most
+of its time with the effective user-id set to \fIdaemon\fP and the
+effective group-id set to \fIdaemon\fP. As a result, spool files
+it creates belong to user and group \fIdaemon\fP. \fILpd\fP uses
+the same verification procedures as \fIrshd\fP\|(8) in authenticating
+remote clients. The host on which a client resides must be present
+in the file /etc/hosts.equiv or /etc/hosts.lpd and the request
+message must come from a reserved port number.
diff --git a/usr.sbin/lpr/SMM.doc/4.t b/usr.sbin/lpr/SMM.doc/4.t
index 61f50513ca2..ac25492a897 100644
--- a/usr.sbin/lpr/SMM.doc/4.t
+++ b/usr.sbin/lpr/SMM.doc/4.t
@@ -1,4 +1,4 @@
-.\" $OpenBSD: 4.t,v 1.3 2002/05/18 23:03:04 millert Exp $
+.\" $OpenBSD: 4.t,v 1.4 2002/06/08 01:53:43 millert Exp $
.\"
.\" Copyright (c) 1983, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -36,10 +36,10 @@
.NH 1
Setting up
.PP
-The 4.3BSD release comes with the necessary programs
+OpenBSD comes with the necessary programs
installed and with the default line printer queue
created. If the system must be modified, the
-makefile in the directory /usr/src/usr.sbin/lpr
+Makefile in the directory /usr/src/usr.sbin/lpr
should be used in recompiling and reinstalling
the necessary programs.
.PP
@@ -65,11 +65,11 @@ Printers on serial lines
When a printer is connected via a serial communication line
it must have the proper baud rate and terminal modes set.
The following example is for a DecWriter III printer connected
-locally via a 1200 baud serial line.
+locally via a 9600 baud serial line.
.DS
.DT
lp|LA-180 DecWriter III:\e
- :lp=/dev/lp:br#1200:fs#06320:\e
+ :lp=/dev/lp:br#9600:ms=onlcr,oxtabs,-parity:\e
:tr=\ef:of=/usr/libexec/lpr/lpf:lf=/var/log/lpd-errs:
.DE
The
@@ -79,8 +79,9 @@ be left out since ``/dev/lp'' is the default.
The
.B br
entry sets the baud rate for the tty line and the
-.B fs
-entry sets CRMOD, no parity, and XTABS (see \fItty\fP\|(4)).
+.B ms
+entry sets NL to CR-NL mapping, expansion of tabs to spaces,
+and disables parity (see \fIstty\fP\|(1)).
The
.B tr
entry indicates that a form-feed should be printed when the queue
@@ -162,7 +163,7 @@ used in printing \fItroff\fP\|(1) output.
This filter is needed to set the device into print mode
for text, and plot mode for printing
.I troff
-files and raster images (see \fIva\fP\|(4V)).
+files and raster images (see \fIva\fP\|(4)).
Note that the page length is set to 58 lines by the
.B pl
entry for 8.5" by 11" fan-fold paper.
diff --git a/usr.sbin/lpr/SMM.doc/5.t b/usr.sbin/lpr/SMM.doc/5.t
index 213eac8d3a5..baa639c0e08 100644
--- a/usr.sbin/lpr/SMM.doc/5.t
+++ b/usr.sbin/lpr/SMM.doc/5.t
@@ -1,4 +1,4 @@
-.\" $OpenBSD: 5.t,v 1.2 1997/01/17 15:54:17 millert Exp $
+.\" $OpenBSD: 5.t,v 1.3 2002/06/08 01:53:43 millert Exp $
.\"
.\" Copyright (c) 1983, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -36,7 +36,7 @@
.NH 1
Output filter specifications
.PP
-The filters supplied with 4.3BSD
+The filters supplied with OpenBSD
handle printing and accounting for most common
line printers, the Benson-Varian, the wide (36") and
narrow (11") Versatec printer/plotters. For other devices or accounting
diff --git a/usr.sbin/lpr/SMM.doc/6.t b/usr.sbin/lpr/SMM.doc/6.t
index 22f24347feb..bac580f19f8 100644
--- a/usr.sbin/lpr/SMM.doc/6.t
+++ b/usr.sbin/lpr/SMM.doc/6.t
@@ -1,4 +1,4 @@
-.\" $OpenBSD: 6.t,v 1.2 1997/01/17 15:54:18 millert Exp $
+.\" $OpenBSD: 6.t,v 1.3 2002/06/08 01:53:43 millert Exp $
.\"
.\" Copyright (c) 1983, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -94,3 +94,13 @@ places jobs at the top of a printer queue. This can be used
to reorder high priority jobs since
.I lpr
only provides first-come-first-serve ordering of jobs.
+.LP
+\fBup\fP and \fBdown\fP
+.IP
+\fIUp\fP and \fIdown\fP combine the functionality of \fIenable\fP
+and \fIstart\fP with \fIstart\fP and \fIstop\fP. \fIUp\fP is
+equivalent to issuing the \fIstart\fP and \fIenable\fP commands,
+whereas \fIdown\fP is equivalent to issuing the \fIstop\fP and
+\fIdisable\fP commands. \fIDown\fP also takes an optional message
+that will be written to the printer's status file. This allows the
+administrator to indicate to users why the printer is out of service.
diff --git a/usr.sbin/lpr/SMM.doc/7.t b/usr.sbin/lpr/SMM.doc/7.t
index f7a85808285..2e83cd5f2e8 100644
--- a/usr.sbin/lpr/SMM.doc/7.t
+++ b/usr.sbin/lpr/SMM.doc/7.t
@@ -1,4 +1,4 @@
-.\" $OpenBSD: 7.t,v 1.3 2002/05/18 23:03:04 millert Exp $
+.\" $OpenBSD: 7.t,v 1.4 2002/06/08 01:53:43 millert Exp $
.\"
.\" Copyright (c) 1983, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -74,7 +74,7 @@ Usually it is enough to get a super-user to type the following to
restart
.IR lpd .
.DS
-% /usr/lib/lpd
+% /usr/sbin/lpd
.DE
You can also check the state of the master printer daemon with the following.
.DS
@@ -83,10 +83,10 @@ You can also check the state of the master printer daemon with the following.
.IP
Another possibility is that the
.I lpr
-program is not set-user-id to \fIroot\fP, set-group-id to group \fIdaemon\fP.
+program is not set-user-id to \fIdaemon\fP, set-group-id to group \fIdaemon\fP.
This can be checked with
.DS
-% ls \-lg /usr/bin/lpr
+% ls \-l /usr/bin/lpr
.DE
.SH
lpr: \fIprinter\fP\|: printer queue is disabled
diff --git a/usr.sbin/lpr/SMM.doc/spell.ok b/usr.sbin/lpr/SMM.doc/spell.ok
index bf31319943d..c7120549b5f 100644
--- a/usr.sbin/lpr/SMM.doc/spell.ok
+++ b/usr.sbin/lpr/SMM.doc/spell.ok
@@ -34,7 +34,7 @@ lpd.lock
lpf
lpf:lf
lprgroup
-makefile
+Makefile
mx
offline
pl
diff --git a/usr.sbin/lpr/common_source/common.c b/usr.sbin/lpr/common_source/common.c
index b27da16cd8d..1772d30b7c9 100644
--- a/usr.sbin/lpr/common_source/common.c
+++ b/usr.sbin/lpr/common_source/common.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: common.c,v 1.17 2002/05/20 23:13:50 millert Exp $ */
+/* $OpenBSD: common.c,v 1.18 2002/06/08 01:53:43 millert Exp $ */
/* $NetBSD: common.c,v 1.21 2000/08/09 14:28:50 itojun Exp $ */
/*
@@ -43,7 +43,7 @@
#if 0
static const char sccsid[] = "@(#)common.c 8.5 (Berkeley) 4/28/95";
#else
-static const char rcsid[] = "$OpenBSD: common.c,v 1.17 2002/05/20 23:13:50 millert Exp $";
+static const char rcsid[] = "$OpenBSD: common.c,v 1.18 2002/06/08 01:53:43 millert Exp $";
#endif
#endif /* not lint */
@@ -58,6 +58,7 @@ static const char rcsid[] = "$OpenBSD: common.c,v 1.17 2002/05/20 23:13:50 mille
#include <dirent.h>
#include <errno.h>
+#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
@@ -163,11 +164,15 @@ retry:
for (r = res; r; r = r->ai_next) {
trial++;
retryport:
- seteuid(euid);
+ PRIV_START;
s = rresvport_af(&lport, r->ai_family);
- seteuid(uid);
- if (s < 0)
- return(-1);
+ PRIV_END;
+ if (s < 0) {
+ /* fall back to non-privileged port */
+ if (errno != EACCES ||
+ (s = socket(r->ai_family, SOCK_STREAM, 0)) < 0)
+ return(-1);
+ }
siginterrupt(SIGINT, 1);
if (connect(s, r->ai_addr, r->ai_addrlen) < 0) {
error = errno;
@@ -246,9 +251,9 @@ getq(namelist)
struct stat stbuf;
DIR *dirp;
- seteuid(euid);
+ PRIV_START;
dirp = opendir(SD);
- seteuid(uid);
+ PRIV_END;
if (dirp == NULL)
return(-1);
if (fstat(dirp->dd_fd, &stbuf) < 0)
@@ -267,12 +272,12 @@ getq(namelist)
while ((d = readdir(dirp)) != NULL) {
if (d->d_name[0] != 'c' || d->d_name[1] != 'f')
continue; /* daemon control files only */
- seteuid(euid);
+ PRIV_START;
if (stat(d->d_name, &stbuf) < 0) {
- seteuid(uid);
+ PRIV_END;
continue; /* Doesn't exist */
}
- seteuid(uid);
+ PRIV_END;
q = (struct queue *)malloc(sizeof(time_t)+strlen(d->d_name)+1);
if (q == NULL)
goto errdone;
@@ -340,9 +345,14 @@ checkremote(void)
remote = 0; /* assume printer is local on failure */
- if (RM == NULL)
+ if (RM == NULL || *RM == '\0')
return NULL;
+ /* XXX */
+ remote = 1;
+ return NULL; /* XXX -- for local testing only! */
+ /* XXX */
+
/* get the local interface addresses */
siginterrupt(SIGINT, 1);
if (getifaddrs(&ifap) < 0) {
@@ -452,3 +462,28 @@ fatal(const char *msg, ...)
(void)putchar('\n');
exit(1);
}
+
+int
+safe_open(const char *path, int flags, mode_t mode)
+{
+ int fd, serrno;
+ struct stat stbuf;
+
+ if ((fd = open(path, flags|O_NONBLOCK, mode)) < 0 ||
+ fstat(fd, &stbuf) < 0) {
+ if (fd >= 0) {
+ serrno = errno;
+ close(fd);
+ errno = serrno;
+ }
+ return (-1);
+ }
+ if (!S_ISREG(stbuf.st_mode)) {
+ close(fd);
+ errno = EACCES;
+ return (-1);
+ }
+ if (mode)
+ (void)fchmod(fd, mode);
+ return (fd);
+}
diff --git a/usr.sbin/lpr/common_source/common_vars.c b/usr.sbin/lpr/common_source/common_vars.c
index 241bfad642e..2b874166af2 100644
--- a/usr.sbin/lpr/common_source/common_vars.c
+++ b/usr.sbin/lpr/common_source/common_vars.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: common_vars.c,v 1.1 2002/05/20 23:13:50 millert Exp $ */
+/* $OpenBSD: common_vars.c,v 1.2 2002/06/08 01:53:43 millert Exp $ */
/* $NetBSD: common.c,v 1.15 1999/09/26 10:32:27 mrg Exp $ */
/*
@@ -40,7 +40,7 @@
*/
#ifndef lint
-static const char rcsid[] = "$OpenBSD: common_vars.c,v 1.1 2002/05/20 23:13:50 millert Exp $";
+static const char rcsid[] = "$OpenBSD: common_vars.c,v 1.2 2002/06/08 01:53:43 millert Exp $";
#endif /* not lint */
#include <sys/param.h>
@@ -53,5 +53,6 @@ char host[MAXHOSTNAMELEN+1]; /* host machine name */
char *from = host; /* client's machine name */
char *printcapdb[2] = { _PATH_PRINTCAP, 0 };
char *bp; /* pointer into printcap buffer. */
-uid_t uid, euid; /* real and effective uids */
u_int wait_time = 300; /* time out after 5 minutes by default */
+uid_t real_uid, effective_uid;
+gid_t real_gid, effective_gid;
diff --git a/usr.sbin/lpr/common_source/displayq.c b/usr.sbin/lpr/common_source/displayq.c
index 67dea6390de..a58abcb56b8 100644
--- a/usr.sbin/lpr/common_source/displayq.c
+++ b/usr.sbin/lpr/common_source/displayq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: displayq.c,v 1.17 2002/05/28 18:16:03 millert Exp $ */
+/* $OpenBSD: displayq.c,v 1.18 2002/06/08 01:53:43 millert Exp $ */
/* $NetBSD: displayq.c,v 1.21 2001/08/30 00:51:50 itojun Exp $ */
/*
@@ -38,23 +38,25 @@
#if 0
static const char sccsid[] = "@(#)displayq.c 8.4 (Berkeley) 4/28/95";
#else
-static const char rcsid[] = "$OpenBSD: displayq.c,v 1.17 2002/05/28 18:16:03 millert Exp $";
+static const char rcsid[] = "$OpenBSD: displayq.c,v 1.18 2002/06/08 01:53:43 millert Exp $";
#endif
#endif /* not lint */
#include <sys/param.h>
-#include <sys/stat.h>
#include <sys/file.h>
-
-#include <signal.h>
-#include <fcntl.h>
#include <sys/ioctl.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <errno.h>
#include <dirent.h>
-#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <ctype.h>
+#include <unistd.h>
+
#include "lp.h"
#include "lp.local.h"
#include "pathnames.h"
@@ -139,25 +141,24 @@ displayq(int format)
* Print out local queue
* Find all the control files in the spooling directory
*/
- seteuid(euid);
+ PRIV_START;
if (chdir(SD) < 0)
fatal("cannot chdir to spooling directory");
- seteuid(uid);
+ PRIV_END;
if ((nitems = getq(&queue)) < 0)
fatal("cannot examine spooling area\n");
- seteuid(euid);
+ PRIV_START;
ret = stat(LO, &statb);
- seteuid(uid);
+ PRIV_END;
if (ret >= 0) {
if (statb.st_mode & 0100) {
if (remote)
printf("%s: ", host);
printf("Warning: %s is down: ", printer);
- seteuid(euid);
- fd = open(ST, O_RDONLY);
- seteuid(uid);
- if (fd >= 0) {
- (void)flock(fd, LOCK_SH);
+ PRIV_START;
+ fd = safe_open(ST, O_RDONLY|O_NOFOLLOW, 0);
+ PRIV_END;
+ if (fd >= 0 && flock(fd, LOCK_SH) == 0) {
while ((i = read(fd, line, sizeof(line))) > 0)
(void)fwrite(line, 1, i, stdout);
(void)close(fd); /* unlocks as well */
@@ -172,12 +173,14 @@ displayq(int format)
}
if (nitems) {
- seteuid(euid);
- fp = fopen(LO, "r");
- seteuid(uid);
- if (fp == NULL)
+ PRIV_START;
+ fd = safe_open(LO, O_RDONLY|O_NOFOLLOW, 0);
+ PRIV_END;
+ if (fd < 0 || (fp = fdopen(fd, "r")) == NULL) {
+ if (fd >= 0)
+ close(fd);
nodaemon();
- else {
+ } else {
/* get daemon pid */
cp = current;
ecp = cp + sizeof(current) - 1;
@@ -190,11 +193,11 @@ displayq(int format)
if (i <= 0) {
ret = -1;
} else {
- seteuid(euid);
+ PRIV_START;
ret = kill(i, 0);
- seteuid(uid);
+ PRIV_END;
}
- if (ret < 0) {
+ if (ret < 0 && errno != EPERM) {
nodaemon();
} else {
/* read current file name */
@@ -210,11 +213,10 @@ displayq(int format)
*/
if (remote)
printf("%s: ", host);
- seteuid(euid);
- fd = open(ST, O_RDONLY);
- seteuid(uid);
- if (fd >= 0) {
- (void)flock(fd, LOCK_SH);
+ PRIV_START;
+ fd = safe_open(ST, O_RDONLY|O_NOFOLLOW, 0);
+ PRIV_END;
+ if (fd >= 0 && flock(fd, LOCK_SH) == 0) {
while ((i = read(fd, line, sizeof(line))) > 0)
(void)fwrite(line, 1, i, stdout);
(void)close(fd); /* unlocks as well */
@@ -331,17 +333,21 @@ header(void)
void
inform(char *cf)
{
- int j;
- FILE *cfp;
+ int fd, j;
+ FILE *cfp = NULL;
/*
* There's a chance the control file has gone away
* in the meantime; if this is the case just keep going
*/
- seteuid(euid);
- if ((cfp = fopen(cf, "r")) == NULL)
+ PRIV_START;
+ fd = safe_open(cf, O_RDONLY|O_NOFOLLOW, 0);
+ PRIV_END;
+ if (fd < 0 || (cfp = fdopen(fd, "r")) == NULL) {
+ if (fd >= 0)
+ close(fd);
return;
- seteuid(uid);
+ }
if (rank < 0)
rank = 0;
@@ -465,10 +471,10 @@ dump(char *nfile, char *file, int copies)
printf("%s", nfile);
col += n+fill;
}
- seteuid(euid);
+ PRIV_START;
if (*file && !stat(file, &lbuf))
totsize += copies * lbuf.st_size;
- seteuid(uid);
+ PRIV_END;
}
/*
diff --git a/usr.sbin/lpr/common_source/lp.h b/usr.sbin/lpr/common_source/lp.h
index 9a3cedb372a..2734028e37d 100644
--- a/usr.sbin/lpr/common_source/lp.h
+++ b/usr.sbin/lpr/common_source/lp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: lp.h,v 1.9 2002/05/20 23:13:50 millert Exp $ */
+/* $OpenBSD: lp.h,v 1.10 2002/06/08 01:53:43 millert Exp $ */
/* $NetBSD: lp.h,v 1.14 2000/04/16 14:43:58 mrg Exp $ */
/*
@@ -92,7 +92,8 @@ extern int remote; /* true if sending files to a remote host */
extern char *printcapdb[]; /* printcap database array */
extern u_int wait_time; /* time to wait for remote responses */
-extern uid_t uid, euid; /* real and effective user id's */
+extern uid_t real_uid, effective_uid;
+extern gid_t real_gid, effective_gid;
extern volatile sig_atomic_t gotintr;
@@ -104,6 +105,23 @@ struct queue {
char q_name[MAXNAMLEN+1]; /* control file name */
};
+/*
+ * Macros to raise/lower permissions.
+ */
+#define PRIV_START do { \
+ int save_errno = errno; \
+ (void)seteuid(effective_uid); \
+ (void)setegid(effective_gid); \
+ errno = save_errno; \
+} while (0)
+
+#define PRIV_END do { \
+ int save_errno = errno; \
+ (void)setegid(real_gid); \
+ (void)seteuid(real_uid); \
+ errno = save_errno; \
+} while (0)
+
#include <sys/cdefs.h>
__BEGIN_DECLS
@@ -125,7 +143,6 @@ int inlist(char *, char *);
int iscf(struct dirent *);
int isowner(char *, char *);
void ldump(char *, char *, int);
-int lockchk(char *);
void prank(int);
void process(char *);
void rmjob(void);
@@ -134,4 +151,5 @@ void show(char *, char *, int);
int startdaemon(char *);
void nodaemon(void);
void delay(int);
+int safe_open(const char *, int, mode_t);
__END_DECLS
diff --git a/usr.sbin/lpr/common_source/rmjob.c b/usr.sbin/lpr/common_source/rmjob.c
index c3712e246a8..1e7f13dbd56 100644
--- a/usr.sbin/lpr/common_source/rmjob.c
+++ b/usr.sbin/lpr/common_source/rmjob.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rmjob.c,v 1.13 2002/05/20 23:13:50 millert Exp $ */
+/* $OpenBSD: rmjob.c,v 1.14 2002/06/08 01:53:43 millert Exp $ */
/* $NetBSD: rmjob.c,v 1.16 2000/04/16 14:43:58 mrg Exp $ */
/*
@@ -38,7 +38,7 @@
#if 0
static const char sccsid[] = "@(#)rmjob.c 8.2 (Berkeley) 4/28/95";
#else
-static const char rcsid[] = "$OpenBSD: rmjob.c,v 1.13 2002/05/20 23:13:50 millert Exp $";
+static const char rcsid[] = "$OpenBSD: rmjob.c,v 1.14 2002/06/08 01:53:43 millert Exp $";
#endif
#endif /* not lint */
@@ -46,6 +46,7 @@ static const char rcsid[] = "$OpenBSD: rmjob.c,v 1.13 2002/05/20 23:13:50 miller
#include <signal.h>
#include <errno.h>
+#include <fcntl.h>
#include <dirent.h>
#include <unistd.h>
#include <stdlib.h>
@@ -76,6 +77,7 @@ static char current[NAME_MAX]; /* active control file name */
static void do_unlink(char *);
static void alarmer(int);
+static int lockchk(char *);
void
rmjob(void)
@@ -122,23 +124,24 @@ rmjob(void)
person = root;
}
- seteuid(euid);
+ PRIV_START;
if (chdir(SD) < 0)
fatal("cannot chdir to spool directory");
if ((nitems = scandir(".", &files, iscf, NULL)) < 0)
fatal("cannot access spool directory");
- seteuid(uid);
+ PRIV_END;
if (nitems) {
/*
- * Check for an active printer daemon (in which case we
- * kill it if it is reading our file) then remove stuff
- * (after which we have to restart the daemon).
+ * Check for an active printer daemon. If one is running
+ * and it is reading our file, kill it, then remove stuff.
+ * Lastly, restart the daemon if it is not (or no longer)
+ * running.
*/
if (lockchk(LO) && chk(current)) {
- seteuid(euid);
+ PRIV_START;
assasinated = kill(cur_daemon, SIGINT) == 0;
- seteuid(uid);
+ PRIV_END;
if (!assasinated)
fatal("cannot kill printer daemon");
}
@@ -159,23 +162,27 @@ rmjob(void)
/*
* Process a lock file: collect the pid of the active
- * daemon and the file name of the active spool entry.
+ * daemon and the file name of the active spool entry.
* Return boolean indicating existence of a lock file.
*/
-int
+static int
lockchk(char *s)
{
- FILE *fp;
- int i, n;
-
- seteuid(euid);
- if ((fp = fopen(s, "r")) == NULL) {
+ FILE *fp = NULL;
+ int fd, i, n;
+
+ /* NOTE: lock file is owned by root, not the user. */
+ PRIV_START;
+ fd = safe_open(s, O_RDONLY|O_NOFOLLOW, 0);
+ PRIV_END;
+ if (fd < 0 || (fp = fdopen(fd, "r")) == NULL) {
+ if (fd >= 0)
+ close(fd);
if (errno == EACCES)
fatal("can't access lock file");
else
return(0);
}
- seteuid(uid);
if (!getline(fp)) {
(void)fclose(fp);
return(0); /* no daemon present */
@@ -203,14 +210,19 @@ lockchk(char *s)
void
process(char *file)
{
- FILE *cfp;
+ FILE *cfp = NULL;
+ int fd;
if (!chk(file))
return;
- seteuid(euid);
- if ((cfp = fopen(file, "r")) == NULL)
+ PRIV_START;
+ fd = safe_open(file, O_RDONLY|O_NOFOLLOW, 0);
+ PRIV_END;
+ if (fd < 0 || (cfp = fdopen(fd, "r")) == NULL) {
+ if (fd >= 0)
+ close(fd);
fatal("cannot open %s", file);
- seteuid(uid);
+ }
while (getline(cfp)) {
switch (line[0]) {
case 'U': /* unlink associated files */
@@ -230,9 +242,9 @@ do_unlink(char *file)
if (from != host)
printf("%s: ", host);
- seteuid(euid);
+ PRIV_START;
ret = unlink(file);
- seteuid(uid);
+ PRIV_END;
printf(ret ? "cannot dequeue %s\n" : "%s dequeued\n", file);
}
@@ -242,9 +254,9 @@ do_unlink(char *file)
int
chk(char *file)
{
- int *r, n;
+ int *r, n, fd;
char **u, *cp;
- FILE *cfp;
+ FILE *cfp = NULL;
/*
* Check for valid cf file name (mostly checking current).
@@ -258,10 +270,14 @@ chk(char *file)
/*
* get the owner's name from the control file.
*/
- seteuid(euid);
- if ((cfp = fopen(file, "r")) == NULL)
+ PRIV_START;
+ fd = safe_open(file, O_RDONLY|O_NOFOLLOW, 0);
+ PRIV_END;
+ if (fd < 0 || (cfp = fdopen(fd, "r")) == NULL) {
+ if (fd >= 0)
+ close(fd);
return(0);
- seteuid(uid);
+ }
while (getline(cfp)) {
if (line[0] == 'P')
break;
diff --git a/usr.sbin/lpr/common_source/startdaemon.c b/usr.sbin/lpr/common_source/startdaemon.c
index 8a25bfdcbd0..cf4e868cf17 100644
--- a/usr.sbin/lpr/common_source/startdaemon.c
+++ b/usr.sbin/lpr/common_source/startdaemon.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: startdaemon.c,v 1.7 2002/05/20 23:13:50 millert Exp $ */
+/* $OpenBSD: startdaemon.c,v 1.8 2002/06/08 01:53:43 millert Exp $ */
/* $NetBSD: startdaemon.c,v 1.10 1998/07/18 05:04:39 lukem Exp $ */
/*
@@ -38,7 +38,7 @@
#if 0
static const char sccsid[] = "@(#)startdaemon.c 8.2 (Berkeley) 4/17/94";
#else
-static const char rcsid[] = "$OpenBSD: startdaemon.c,v 1.7 2002/05/20 23:13:50 millert Exp $";
+static const char rcsid[] = "$OpenBSD: startdaemon.c,v 1.8 2002/06/08 01:53:43 millert Exp $";
#endif
#endif /* not lint */
@@ -53,13 +53,13 @@ static const char rcsid[] = "$OpenBSD: startdaemon.c,v 1.7 2002/05/20 23:13:50 m
#include <unistd.h>
#include <string.h>
#include <signal.h>
+
#include "lp.h"
#include "pathnames.h"
/*
* Tell the printer daemon that there are new files in the spool directory.
*/
-
int
startdaemon(char *printer)
{
@@ -79,23 +79,23 @@ startdaemon(char *printer)
#ifndef SUN_LEN
#define SUN_LEN(unp) (strlen((unp)->sun_path) + 2)
#endif
- seteuid(euid);
siginterrupt(SIGINT, 1);
+ PRIV_START;
if (connect(s, (struct sockaddr *)&un, SUN_LEN(&un)) < 0) {
if (errno == EINTR && gotintr) {
+ PRIV_END;
siginterrupt(SIGINT, 0);
- seteuid(uid);
close(s);
return(0);
}
+ PRIV_END;
siginterrupt(SIGINT, 0);
- seteuid(uid);
perror("connect");
(void)close(s);
return(0);
}
+ PRIV_END;
siginterrupt(SIGINT, 0);
- seteuid(uid);
n = snprintf(buf, sizeof(buf), "\1%s\n", printer);
if (n >= sizeof(buf) || n == -1) {
close(s);
diff --git a/usr.sbin/lpr/lpc/cmds.c b/usr.sbin/lpr/lpc/cmds.c
index 86608fe3bda..005fa0caeb0 100644
--- a/usr.sbin/lpr/lpc/cmds.c
+++ b/usr.sbin/lpr/lpc/cmds.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmds.c,v 1.16 2002/05/20 23:13:50 millert Exp $ */
+/* $OpenBSD: cmds.c,v 1.17 2002/06/08 01:53:43 millert Exp $ */
/* $NetBSD: cmds.c,v 1.12 1997/10/05 15:12:06 mrg Exp $ */
/*
@@ -45,7 +45,7 @@ static const char copyright[] =
#if 0
static const char sccsid[] = "@(#)cmds.c 8.2 (Berkeley) 4/28/95";
#else
-static const char rcsid[] = "$OpenBSD: cmds.c,v 1.16 2002/05/20 23:13:50 millert Exp $";
+static const char rcsid[] = "$OpenBSD: cmds.c,v 1.17 2002/06/08 01:53:43 millert Exp $";
#endif
#endif /* not lint */
@@ -73,8 +73,6 @@ static const char rcsid[] = "$OpenBSD: cmds.c,v 1.16 2002/05/20 23:13:50 millert
#include "extern.h"
#include "pathnames.h"
-extern uid_t uid, euid;
-
static void abortpr(int);
static void cleanpr(void);
static void disablepr(void);
@@ -145,22 +143,25 @@ abortpr(int dis)
(void)snprintf(line, sizeof(line), "%s/%s", SD, LO);
printf("%s:\n", printer);
+ PRIV_START;
/*
* Turn on the owner execute bit of the lock file to disable printing.
*/
if (dis) {
- seteuid(euid);
if (stat(line, &stbuf) >= 0) {
- if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0)
+ stbuf.st_mode |= S_IXUSR;
+ if (chmod(line, stbuf.st_mode & 0777) < 0)
printf("\tcannot disable printing\n");
else {
upstat("printing disabled\n");
printf("\tprinting disabled\n");
}
} else if (errno == ENOENT) {
- if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0)
+ if ((fd = safe_open(line, O_WRONLY|O_CREAT|O_NOFOLLOW,
+ 0760)) < 0)
printf("\tcannot create lock file\n");
else {
+ (void)fchown(fd, DEFUID, -1);
(void)close(fd);
upstat("printing disabled\n");
printf("\tprinting disabled\n");
@@ -175,7 +176,10 @@ abortpr(int dis)
/*
* Kill the current daemon to stop printing now.
*/
- if ((fp = fopen(line, "r")) == NULL) {
+ fd = safe_open(line, O_RDONLY|O_NOFOLLOW, 0);
+ if (fd < 0 || (fp = fdopen(fd, "r")) == NULL) {
+ if (fd >= 0)
+ close(fd);
printf("\tcannot open lock file\n");
goto out;
}
@@ -193,11 +197,11 @@ abortpr(int dis)
} else
printf("\tdaemon (pid %d) killed\n", pid);
out:
- seteuid(uid);
+ PRIV_END;
}
/*
- * Write a message into the status file.
+ * Write a message into the status file (assumes PRIV_START already called)
*/
static void
upstat(char *msg)
@@ -208,12 +212,12 @@ upstat(char *msg)
if (cgetstr(bp, "st", &ST) == -1)
ST = DEFSTAT;
(void)snprintf(statfile, sizeof(statfile), "%s/%s", SD, ST);
- umask(0);
- fd = open(statfile, O_WRONLY|O_CREAT, 0664);
+ fd = safe_open(statfile, O_WRONLY|O_CREAT|O_NOFOLLOW, 0660);
if (fd < 0 || flock(fd, LOCK_EX) < 0) {
printf("\tcannot create status file\n");
return;
}
+ (void)fchown(fd, DEFUID, -1);
(void)ftruncate(fd, 0);
if (msg == (char *)NULL)
(void)write(fd, "\n", 1);
@@ -324,9 +328,9 @@ cleanpr(void)
return;
}
- seteuid(euid);
+ PRIV_START;
nitems = scandir(SD, &queue, doselect, sortq);
- seteuid(uid);
+ PRIV_END;
if (nitems < 0) {
printf("\tcannot examine spool directory\n");
return;
@@ -370,12 +374,12 @@ cleanpr(void)
static void
unlinkf(char *name)
{
- seteuid(euid);
+ PRIV_START;
if (unlink(name) < 0)
printf("\tcannot remove %s\n", name);
else
printf("\tremoved %s\n", name);
- seteuid(uid);
+ PRIV_END;
}
/*
@@ -435,14 +439,15 @@ enablepr(void)
/*
* Turn off the group execute bit of the lock file to enable queuing.
*/
- seteuid(euid);
+ PRIV_START;
if (stat(line, &stbuf) >= 0) {
- if (chmod(line, stbuf.st_mode & 0767) < 0)
+ stbuf.st_mode &= ~S_IXGRP;
+ if (chmod(line, stbuf.st_mode & 0777) < 0)
printf("\tcannot enable queuing\n");
else
printf("\tqueuing enabled\n");
}
- seteuid(uid);
+ PRIV_END;
}
/*
@@ -502,22 +507,24 @@ disablepr(void)
/*
* Turn on the group execute bit of the lock file to disable queuing.
*/
- seteuid(euid);
+ PRIV_START;
if (stat(line, &stbuf) >= 0) {
- if (chmod(line, (stbuf.st_mode & 0777) | 010) < 0)
+ stbuf.st_mode |= S_IXGRP;
+ if (chmod(line, stbuf.st_mode & 0777) < 0)
printf("\tcannot disable queuing\n");
else
printf("\tqueuing disabled\n");
} else if (errno == ENOENT) {
- if ((fd = open(line, O_WRONLY|O_CREAT, 0670)) < 0)
+ if ((fd = safe_open(line, O_WRONLY|O_CREAT|O_NOFOLLOW, 0670)) < 0)
printf("\tcannot create lock file\n");
else {
+ (void)fchown(fd, DEFUID, -1);
(void)close(fd);
printf("\tqueuing disabled\n");
}
} else
printf("\tcannot stat lock file\n");
- seteuid(uid);
+ PRIV_END;
}
/*
@@ -581,20 +588,22 @@ putmsg(int argc, char **argv)
* turn on the owner execute bit of the lock file to disable printing.
*/
(void)snprintf(line, sizeof(line), "%s/%s", SD, LO);
- seteuid(euid);
+ PRIV_START;
if (stat(line, &stbuf) >= 0) {
- if (chmod(line, (stbuf.st_mode & 0777) | 0110) < 0)
+ stbuf.st_mode |= (S_IXGRP|S_IXUSR);
+ if (chmod(line, stbuf.st_mode & 0777) < 0)
printf("\tcannot disable queuing\n");
else
printf("\tprinter and queuing disabled\n");
} else if (errno == ENOENT) {
- if ((fd = open(line, O_WRONLY|O_CREAT, 0770)) < 0)
+ if ((fd = safe_open(line, O_WRONLY|O_CREAT|O_NOFOLLOW, 0770)) < 0)
printf("\tcannot create lock file\n");
else {
+ (void)fchown(fd, DEFUID, -1);
(void)close(fd);
printf("\tprinter and queuing disabled\n");
}
- seteuid(uid);
+ PRIV_END;
return;
} else
printf("\tcannot stat lock file\n");
@@ -602,13 +611,14 @@ putmsg(int argc, char **argv)
* Write the message into the status file.
*/
(void)snprintf(line, sizeof(line), "%s/%s", SD, ST);
- fd = open(line, O_WRONLY|O_CREAT, 0664);
+ fd = safe_open(line, O_WRONLY|O_CREAT|O_NOFOLLOW, 0660);
if (fd < 0 || flock(fd, LOCK_EX) < 0) {
printf("\tcannot create status file\n");
- seteuid(uid);
+ PRIV_END;
return;
}
- seteuid(uid);
+ PRIV_END;
+ (void)fchown(fd, DEFUID, -1);
(void)ftruncate(fd, 0);
if (argc <= 0) {
(void)write(fd, "\n", 1);
@@ -737,19 +747,24 @@ startpr(int enable)
/*
* Turn off the owner execute bit of the lock file to enable printing.
+ * If we are marking the printer "up" also turn off group execute bit.
*/
- seteuid(euid);
+ PRIV_START;
if (enable && stat(line, &stbuf) >= 0) {
- if (chmod(line, stbuf.st_mode & (enable==2 ? 0666 : 0677)) < 0)
+ if (enable == 2)
+ stbuf.st_mode &= ~(S_IXUSR|S_IXGRP);
+ else
+ stbuf.st_mode &= ~S_IXUSR;
+ if (chmod(line, stbuf.st_mode & 0777) < 0)
printf("\tcannot enable printing\n");
else
printf("\tprinting enabled\n");
}
+ PRIV_END;
if (!startdaemon(printer))
printf("\tcouldn't start daemon\n");
else
printf("\tdaemon started\n");
- seteuid(uid);
}
/*
@@ -809,7 +824,10 @@ prstat(void)
ST = DEFSTAT;
printf("%s:\n", printer);
(void)snprintf(line, sizeof(line), "%s/%s", SD, LO);
- if (stat(line, &stbuf) >= 0) {
+ PRIV_START;
+ i = stat(line, &stbuf);
+ PRIV_END;
+ if (i >= 0) {
printf("\tqueuing is %s\n",
(stbuf.st_mode & 010) ? "disabled" : "enabled");
printf("\tprinting is %s\n",
@@ -818,7 +836,10 @@ prstat(void)
printf("\tqueuing is enabled\n");
printf("\tprinting is enabled\n");
}
- if ((dirp = opendir(SD)) == NULL) {
+ PRIV_START;
+ dirp = opendir(SD);
+ PRIV_END;
+ if (dirp == NULL) {
printf("\tcannot examine spool directory\n");
return;
}
@@ -834,7 +855,9 @@ prstat(void)
printf("\t1 entry in spool area\n");
else
printf("\t%d entries in spool area\n", i);
- fd = open(line, O_RDONLY);
+ PRIV_START;
+ fd = safe_open(line, O_RDONLY|O_NOFOLLOW, 0);
+ PRIV_END;
if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) {
(void)close(fd); /* unlocks as well */
printf("\tprinter idle\n");
@@ -842,7 +865,9 @@ prstat(void)
}
(void)close(fd);
(void)snprintf(line, sizeof(line), "%s/%s", SD, ST);
- fd = open(line, O_RDONLY);
+ PRIV_START;
+ fd = safe_open(line, O_RDONLY|O_NOFOLLOW, 0);
+ PRIV_END;
if (fd >= 0) {
(void)flock(fd, LOCK_SH);
if (fstat(fd, &stbuf) == 0 && stbuf.st_size > 0) {
@@ -913,25 +938,27 @@ stoppr(void)
/*
* Turn on the owner execute bit of the lock file to disable printing.
*/
- seteuid(euid);
+ PRIV_START;
if (stat(line, &stbuf) >= 0) {
- if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0)
+ stbuf.st_mode |= S_IXUSR;
+ if (chmod(line, stbuf.st_mode & 0777) < 0)
printf("\tcannot disable printing\n");
else {
upstat("printing disabled\n");
printf("\tprinting disabled\n");
}
} else if (errno == ENOENT) {
- if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0)
+ if ((fd = safe_open(line, O_WRONLY|O_CREAT|O_NOFOLLOW, 0760)) < 0)
printf("\tcannot create lock file\n");
else {
+ (void)fchown(fd, DEFUID, -1);
(void)close(fd);
upstat("printing disabled\n");
printf("\tprinting disabled\n");
}
} else
printf("\tcannot stat lock file\n");
- seteuid(uid);
+ PRIV_END;
}
struct queue **queue;
@@ -971,12 +998,12 @@ topq(int argc, char **argv)
LO = DEFLOCK;
printf("%s:\n", printer);
- seteuid(euid);
+ PRIV_START;
if (chdir(SD) < 0) {
printf("\tcannot chdir to %s\n", SD);
goto out;
}
- seteuid(uid);
+ PRIV_END;
nitems = getq(&queue);
if (nitems == 0)
return;
@@ -1000,12 +1027,14 @@ topq(int argc, char **argv)
* Turn on the public execute bit of the lock file to
* get lpd to rebuild the queue after the current job.
*/
- seteuid(euid);
- if (changed && stat(LO, &stbuf) >= 0)
- (void)chmod(LO, (stbuf.st_mode & 0777) | 01);
+ PRIV_START;
+ if (changed && stat(LO, &stbuf) >= 0) {
+ stbuf.st_mode |= S_IXOTH;
+ (void)chmod(LO, stbuf.st_mode & 0777);
+ }
out:
- seteuid(uid);
+ PRIV_END;
}
/*
@@ -1020,9 +1049,9 @@ touch(struct queue *q)
tvp[0].tv_sec = tvp[1].tv_sec = --mtime;
tvp[0].tv_usec = tvp[1].tv_usec = 0;
- seteuid(euid);
+ PRIV_START;
ret = utimes(q->q_name, tvp);
- seteuid(uid);
+ PRIV_END;
return (ret);
}
@@ -1034,7 +1063,7 @@ int
doarg(char *job)
{
struct queue **qq;
- int jobnum, n;
+ int jobnum, fd, n;
char *cp, *machine;
int cnt = 0;
FILE *fp;
@@ -1079,11 +1108,14 @@ doarg(char *job)
* Process item consisting of owner's name (example: henry).
*/
for (qq = queue + nitems; --qq >= queue; ) {
- seteuid(euid);
- fp = fopen((*qq)->q_name, "r");
- seteuid(uid);
- if (fp == NULL)
+ PRIV_START;
+ fd = safe_open((*qq)->q_name, O_RDONLY|O_NOFOLLOW, 0);
+ PRIV_END;
+ if (fd < 0 || (fp = fdopen(fd, "r")) == NULL) {
+ if (fd >= 0)
+ close(fd);
continue;
+ }
while (getline(fp) > 0)
if (line[0] == 'P')
break;
diff --git a/usr.sbin/lpr/lpc/lpc.8 b/usr.sbin/lpr/lpc/lpc.8
index b4781c1847a..c663e0b5daf 100644
--- a/usr.sbin/lpr/lpc/lpc.8
+++ b/usr.sbin/lpr/lpc/lpc.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: lpc.8,v 1.10 2002/05/20 23:13:50 millert Exp $
+.\" $OpenBSD: lpc.8,v 1.11 2002/06/08 01:53:43 millert Exp $
.\" $NetBSD: lpc.8,v 1.14 2002/01/19 03:22:19 wiz Exp $
.\"
.\" Copyright (c) 1983, 1991, 1993
@@ -112,7 +112,7 @@ in the printer status file.
The message doesn't need to be quoted, the
remaining arguments are treated like
.Xr echo 1 .
-This is normally used to take a printer down and let others know why
+This is normally used to take a printer down and let users know why.
.Xr lpq 1
will indicate the printer is down and print the status message.
.Pp
diff --git a/usr.sbin/lpr/lpc/lpc.c b/usr.sbin/lpr/lpc/lpc.c
index adaf078440e..bbd41c4833c 100644
--- a/usr.sbin/lpr/lpc/lpc.c
+++ b/usr.sbin/lpr/lpc/lpc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lpc.c,v 1.13 2002/05/20 23:13:50 millert Exp $ */
+/* $OpenBSD: lpc.c,v 1.14 2002/06/08 01:53:43 millert Exp $ */
/* $NetBSD: lpc.c,v 1.11 2001/11/14 03:01:15 enami Exp $ */
/*
@@ -45,7 +45,7 @@ static const char copyright[] =
#if 0
static const char sccsid[] = "@(#)lpc.c 8.3 (Berkeley) 4/28/95";
#else
-static const char rcsid[] = "$OpenBSD: lpc.c,v 1.13 2002/05/20 23:13:50 millert Exp $";
+static const char rcsid[] = "$OpenBSD: lpc.c,v 1.14 2002/06/08 01:53:43 millert Exp $";
#endif
#endif /* not lint */
@@ -94,11 +94,13 @@ main(int argc, char **argv)
{
struct cmd *c;
- euid = geteuid();
- uid = getuid();
- seteuid(uid);
- openlog("lpc", 0, LOG_LPR);
+ effective_uid = geteuid();
+ real_uid = getuid();
+ effective_gid = getegid();
+ real_gid = getgid();
+ PRIV_END; /* be safe */
+ openlog("lpc", 0, LOG_LPR);
if (--argc > 0) {
c = getcmd(*++argv);
if (c == (struct cmd *)-1) {
@@ -109,7 +111,7 @@ main(int argc, char **argv)
printf("?Invalid command\n");
exit(1);
}
- if (c->c_priv && getuid() && ingroup(LPR_OPER) == 0) {
+ if (c->c_priv && real_uid && ingroup(LPR_OPER) == 0) {
printf("?Privileged command\n");
exit(1);
}
diff --git a/usr.sbin/lpr/lpd/Makefile b/usr.sbin/lpr/lpd/Makefile
index 5698aed8d73..5d64e87885e 100644
--- a/usr.sbin/lpr/lpd/Makefile
+++ b/usr.sbin/lpr/lpd/Makefile
@@ -1,11 +1,13 @@
# from: @(#)Makefile 8.1 (Berkeley) 6/6/93
-# $OpenBSD: Makefile,v 1.3 2002/05/20 23:13:50 millert Exp $
+# $OpenBSD: Makefile,v 1.4 2002/06/08 01:53:43 millert Exp $
PROG= lpd
CFLAGS+=-I${.CURDIR}/../common_source
MAN= lpd.8
SRCS= lpd.c printjob.c recvjob.c displayq.c rmjob.c startdaemon.c \
lpdchar.c common.c key.c modes.c ttcompat.c common_vars.c
+BINGRP= daemon
+BINMODE=2550
.PATH: ${.CURDIR}/../common_source
.include "../../Makefile.inc"
diff --git a/usr.sbin/lpr/lpd/lpd.c b/usr.sbin/lpr/lpd/lpd.c
index fe6034e3113..e731fda086b 100644
--- a/usr.sbin/lpr/lpd/lpd.c
+++ b/usr.sbin/lpr/lpd/lpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lpd.c,v 1.32 2002/05/28 18:17:22 millert Exp $ */
+/* $OpenBSD: lpd.c,v 1.33 2002/06/08 01:53:43 millert Exp $ */
/* $NetBSD: lpd.c,v 1.33 2002/01/21 14:42:29 wiz Exp $ */
/*
@@ -45,7 +45,7 @@ static const char copyright[] =
#if 0
static const char sccsid[] = "@(#)lpd.c 8.7 (Berkeley) 5/10/95";
#else
-static const char rcsid[] = "$OpenBSD: lpd.c,v 1.32 2002/05/28 18:17:22 millert Exp $";
+static const char rcsid[] = "$OpenBSD: lpd.c,v 1.33 2002/06/08 01:53:43 millert Exp $";
#endif
#endif /* not lint */
@@ -66,16 +66,18 @@ static const char rcsid[] = "$OpenBSD: lpd.c,v 1.32 2002/05/28 18:17:22 millert
* remove jobs from the queue.
*
* Strategy to maintain protected spooling area:
- * 1. Spooling area is writable only by daemon and spooling group
- * 2. lpr runs setuid root and setgrp spooling group; it uses
- * root to access any file it wants (verifying things before
- * with an access call) and group id to know how it should
- * set up ownership of files in the spooling area.
- * 3. Files in spooling area are owned by root, group spooling
- * group, with mode 660.
- * 4. lpd, lpq and lprm run setuid daemon and setgrp spooling group to
- * access files and printer. Users can't get to anything
- * w/o help of lpq and lprm programs.
+ * 1. Spooling area is writable only by root and the group daemon.
+ * 2. Files in spooling area are owned by user daemon, group daemon,
+ * and are mode 660.
+ * 3. lpd runs as root but spends most of its time with its effective
+ * uid and gid set to the uid/gid specified in the passwd entry for
+ * DEFUID (1, aka daemon).
+ * 4. lpr runs setuid daemon and setgrp daemon; it opens
+ * files to be printed with its real uid/gid and writes to
+ * the spool dir with its effective uid/gid (i.e. daemon).
+ * 5. lpc, lpr and lprm run setgrp daemon.
+ *
+ * Users can't touch the spool w/o the help of one of the lp* programs.
*/
#include <sys/param.h>
@@ -94,6 +96,7 @@ static const char rcsid[] = "$OpenBSD: lpd.c,v 1.32 2002/05/28 18:17:22 millert
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
+#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -137,6 +140,7 @@ int
main(int argc, char **argv)
{
fd_set defreadfds;
+ struct passwd *pw;
struct sockaddr_un un, fromunix;
struct sockaddr_storage frominet;
sigset_t mask, omask;
@@ -148,14 +152,24 @@ main(int argc, char **argv)
const char *port = "printer";
char *cp;
- euid = geteuid(); /* these shouldn't be different */
- uid = getuid();
- options = check_options = 0;
- gethostname(host, sizeof(host));
-
- if (euid != 0)
+ if (geteuid() != 0)
errx(1, "must run as root");
+ /*
+ * We want to run with euid of daemon most of the time.
+ */
+ if ((pw = getpwuid(DEFUID)) == NULL)
+ errx(1, "daemon uid (%d) not in password file", DEFUID);
+ real_uid = pw->pw_uid;
+ real_gid = pw->pw_gid;
+ effective_uid = 0;
+ effective_gid = getegid();
+ PRIV_END; /* run as daemon for most things */
+
+ check_options = LPD_NOPORTCHK; /* XXX - lp* not setuid root */
+ options = 0;
+ gethostname(host, sizeof(host));
+
while ((i = getopt(argc, argv, "b:cdln:rsw:W")) != -1) {
switch (i) {
case 'b':
@@ -240,7 +254,9 @@ main(int argc, char **argv)
openlog("lpd", LOG_PID, LOG_LPR);
syslog(LOG_INFO, "restarted");
(void)umask(0);
+ PRIV_START;
lfd = open(_PATH_MASTERLOCK, O_WRONLY|O_CREAT|O_EXLOCK|O_NONBLOCK, 0644);
+ PRIV_END;
if (lfd < 0) {
if (errno == EWOULDBLOCK) /* active daemon present */
exit(0);
@@ -262,7 +278,9 @@ main(int argc, char **argv)
* Restart all the printers.
*/
startup();
+ PRIV_START;
(void)unlink(_PATH_SOCKETNAME);
+ PRIV_END;
funix = socket(AF_LOCAL, SOCK_STREAM, 0);
if (funix < 0) {
syslog(LOG_ERR, "socket: %m");
@@ -287,10 +305,12 @@ main(int argc, char **argv)
#ifndef SUN_LEN
#define SUN_LEN(unp) (strlen((unp)->sun_path) + 2)
#endif
+ PRIV_START;
if (bind(funix, (struct sockaddr *)&un, SUN_LEN(&un)) < 0) {
syslog(LOG_ERR, "ubind: %m");
exit(1);
}
+ PRIV_END;
(void)umask(0);
sigprocmask(SIG_SETMASK, &omask, NULL);
FD_ZERO(&defreadfds);
@@ -438,6 +458,7 @@ mcleanup(int signo)
if (lflag)
syslog_r(LOG_INFO, &sdata, "exiting");
+ PRIV_START;
unlink(_PATH_SOCKETNAME);
unlink(_PATH_MASTERLOCK);
_exit(0);
@@ -584,8 +605,7 @@ doit(void)
static void
startup(void)
{
- char *buf;
- char *cp;
+ char *buf, *cp;
/*
* Restart the daemons.
@@ -622,6 +642,7 @@ startup(void)
/*
* Make sure there's some work to do before forking off a child
+ * XXX - could be common w/ lpq
*/
static int
ckqueue(char *cap)
@@ -632,13 +653,14 @@ ckqueue(char *cap)
if (cgetstr(cap, "sd", &spooldir) == -1)
spooldir = _PATH_DEFSPOOL;
- if ((dirp = opendir(spooldir)) == NULL)
+ dirp = opendir(spooldir);
+ if (dirp == NULL)
return (-1);
while ((d = readdir(dirp)) != NULL) {
- if (d->d_name[0] != 'c' || d->d_name[1] != 'f')
- continue; /* daemon control files only */
- closedir(dirp);
- return (1); /* found something */
+ if (d->d_name[0] == 'c' && d->d_name[1] == 'f') {
+ closedir(dirp);
+ return (1); /* found a cf file */
+ }
}
closedir(dirp);
return (0);
@@ -710,7 +732,9 @@ chkhost(struct sockaddr *f, int check_opts)
if (good == 0)
fatal("address for your hostname (%s) not matched", host);
setproctitle("serving %s", from);
+ PRIV_START;
hostf = fopen(_PATH_HOSTSEQUIV, "r");
+ PRIV_END;
again:
if (hostf) {
if (__ivaliduser_sa(hostf, f, f->sa_len, DUMMY, DUMMY) == 0) {
@@ -721,7 +745,9 @@ again:
}
if (first == 1) {
first = 0;
+ PRIV_START;
hostf = fopen(_PATH_HOSTSLPD, "r");
+ PRIV_END;
goto again;
}
fatal("Your host does not have line printer access");
@@ -796,7 +822,10 @@ socksetup(int af, int options, const char *port)
close (*s);
continue;
}
- if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) {
+ PRIV_START;
+ error = bind(*s, r->ai_addr, r->ai_addrlen);
+ PRIV_END;
+ if (error < 0) {
syslog(LOG_DEBUG, "bind(): %m");
close (*s);
continue;
diff --git a/usr.sbin/lpr/lpd/printjob.c b/usr.sbin/lpr/lpd/printjob.c
index a1578c9e43a..8e0bce7da8e 100644
--- a/usr.sbin/lpr/lpd/printjob.c
+++ b/usr.sbin/lpr/lpd/printjob.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: printjob.c,v 1.32 2002/05/20 23:13:50 millert Exp $ */
+/* $OpenBSD: printjob.c,v 1.33 2002/06/08 01:53:43 millert Exp $ */
/* $NetBSD: printjob.c,v 1.31 2002/01/21 14:42:30 wiz Exp $ */
/*
@@ -72,6 +72,7 @@ static const char sccsid[] = "@(#)printjob.c 8.7 (Berkeley) 5/10/95";
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
+
#include "lp.h"
#include "lp.local.h"
#include "pathnames.h"
@@ -94,13 +95,13 @@ static const char sccsid[] = "@(#)printjob.c 8.7 (Berkeley) 5/10/95";
static dev_t fdev; /* device of file pointed to by symlink */
static ino_t fino; /* inode of file pointed to by symlink */
static FILE *cfp; /* control file */
-static int child; /* id of any filters */
+static pid_t child; /* pid of any filters */
static int lfd; /* lock file descriptor */
static int ofd; /* output filter file descriptor */
-static int ofilter; /* id of output filter, if any */
+static pid_t ofilter; /* pid of output filter, if any */
static int pfd; /* prstatic inter file descriptor */
-static int pid; /* pid of lpd process */
-static int prchild; /* id of pr process */
+static pid_t pid; /* pid of lpd process */
+static pid_t prchild; /* pid of pr process */
static char title[80]; /* ``pr'' title */
static int tof; /* true if at top of form */
@@ -118,7 +119,7 @@ static char width[10] = "-w"; /* page width in static characters */
static void abortpr(int);
static void banner(char *, char *);
-static int dofork(int);
+static pid_t dofork(int);
static int dropit(int);
static void init(void);
static void openpr(void);
@@ -144,18 +145,27 @@ printjob(void)
struct stat stb;
struct queue *q, **qp;
struct queue **queue;
- int i, nitems;
+ int i, fd, nitems;
off_t pidoff;
int errcnt, count = 0;
init(); /* set up capabilities */
(void)write(STDOUT_FILENO, "", 1); /* ack that daemon is started */
- (void)close(STDERR_FILENO); /* set up log file */
- if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {
+ PRIV_START;
+ fd = open(LF, O_WRONLY|O_APPEND, 0664); /* set up log file */
+ PRIV_END;
+ if (fd < 0) {
syslog(LOG_ERR, "%s: %m", LF);
- (void)open(_PATH_DEVNULL, O_WRONLY);
+ if ((fd = open(_PATH_DEVNULL, O_WRONLY)) < 0)
+ exit(1);
+ }
+ if (fd != STDERR_FILENO) {
+ if (dup2(fd, STDERR_FILENO) < 0) {
+ syslog(LOG_ERR, "dup2: %m");
+ exit(1);
+ }
+ close(fd);
}
- setgid(getegid());
pid = getpid(); /* for use with lprm */
setpgrp(0, pid);
signal(SIGHUP, abortpr);
@@ -163,28 +173,23 @@ printjob(void)
signal(SIGQUIT, abortpr);
signal(SIGTERM, abortpr);
- (void)mktemp(tempfile); /* safe */
-
- /*
- * uses short form file names
- */
+ /* so we can use short form file names */
if (chdir(SD) < 0) {
syslog(LOG_ERR, "%s: %m", SD);
exit(1);
}
- if (stat(LO, &stb) == 0 && (stb.st_mode & S_IXUSR))
- exit(0); /* printing disabled */
- lfd = open(LO, O_WRONLY|O_CREAT, 0644);
+
+ (void)mktemp(tempfile); /* safe */
+
+ lfd = safe_open(LO, O_WRONLY|O_CREAT|O_NOFOLLOW|O_EXLOCK, 0640);
if (lfd < 0) {
- syslog(LOG_ERR, "%s: %s: %m", printer, LO);
- exit(1);
- }
- if (flock(lfd, LOCK_EX|LOCK_NB) < 0) {
if (errno == EWOULDBLOCK) /* active daemon present */
exit(0);
syslog(LOG_ERR, "%s: %s: %m", printer, LO);
exit(1);
}
+ if (fstat(lfd, &stb) == 0 && (stb.st_mode & S_IXUSR))
+ exit(0); /* printing disabled */
ftruncate(lfd, 0);
/*
* write process id for others to know
@@ -208,10 +213,14 @@ printjob(void)
if (nitems == 0) /* no work to do */
exit(0);
if (stb.st_mode & S_IXOTH) { /* reset queue flag */
- if (fchmod(lfd, stb.st_mode & 0776) < 0)
+ stb.st_mode &= ~S_IXOTH;
+ if (fchmod(lfd, stb.st_mode & 0777) < 0)
syslog(LOG_ERR, "%s: %s: %m", printer, LO);
}
+ PRIV_START;
openpr(); /* open printer or remote */
+ PRIV_END;
+
again:
/*
* we found something to do now do it --
@@ -246,7 +255,8 @@ again:
if (stb.st_mode & S_IXOTH) {
for (free((char *) q); nitems--; free((char *) q))
q = *qp++;
- if (fchmod(lfd, stb.st_mode & 0776) < 0)
+ stb.st_mode &= ~S_IXOTH;
+ if (fchmod(lfd, stb.st_mode & 0777) < 0)
syslog(LOG_WARNING, "%s: %s: %m",
printer, LO);
break;
@@ -267,16 +277,20 @@ again:
(void)close(pfd); /* close printer */
if (ftruncate(lfd, pidoff) < 0)
syslog(LOG_WARNING, "%s: %s: %m", printer, LO);
+ PRIV_START;
openpr(); /* try to reopen printer */
+ PRIV_END;
goto restart;
} else {
syslog(LOG_WARNING, "%s: job could not be %s (%s)", printer,
remote ? "sent to remote host" : "printed", q->q_name);
if (i == REPRINT) {
/* ensure we don't attempt this job again */
+ PRIV_START;
(void)unlink(q->q_name);
q->q_name[0] = 'd';
(void)unlink(q->q_name);
+ PRIV_END;
if (logname[0])
sendmail(logname, FATALERR);
}
@@ -323,15 +337,18 @@ char ifonts[4][40] = {
static int
printit(char *file)
{
- int i;
+ int i, fd;
char *cp;
int bombed = OK;
/*
* open control file; ignore if no longer there.
*/
- if ((cfp = fopen(file, "r")) == NULL) {
+ fd = safe_open(file, O_RDONLY|O_NOFOLLOW, 0);
+ if (fd < 0 || (cfp = fdopen(fd, "r")) == NULL) {
syslog(LOG_INFO, "%s: %s: %m", printer, file);
+ if (fd >= 0)
+ close(fd);
return(OK);
}
/*
@@ -521,14 +538,19 @@ pass2:
static int
print(int format, char *file)
{
- FILE *fp;
- int status, serrno;
+ ssize_t nread;
struct stat stb;
+ pid_t pid;
char *prog, *av[15], buf[BUFSIZ];
- int n, fi, fo, pid, p[2], stopped = 0, nofile;
+ int fd, status, serrno;
+ int n, fi, fo, p[2], stopped = 0, nofile;
- if (lstat(file, &stb) < 0 || (fi = open(file, O_RDONLY)) < 0)
+ PRIV_START;
+ if (lstat(file, &stb) < 0 || (fi = safe_open(file, O_RDONLY, 0)) < 0) {
+ PRIV_END;
return(ERROR);
+ }
+ PRIV_END;
/*
* Check to see if data file is a symbolic link. If so, it should
* still point to the same file or someone is trying to print
@@ -590,7 +612,7 @@ print(int format, char *file)
* For now, treat this as a plain-text file, and assume
* the standard LPF_INPUT filter will recognize that it
* is postscript and know what to do with it. These
- * 'o'-file requests could come from MacOS 10.1 systems.
+ * 'o'-file requests could come from MacOS X systems.
*/
/* FALLTHROUGH */
case 'f': /* print plain text file */
@@ -618,7 +640,7 @@ print(int format, char *file)
case 'n': /* print ditroff output */
case 'd': /* print tex output */
(void)unlink(".railmag");
- if ((fo = creat(".railmag", FILMOD)) < 0) {
+ if ((fo = open(".railmag", O_CREAT|O_WRONLY|O_EXCL, FILMOD)) < 0) {
syslog(LOG_ERR, "%s: cannot create .railmag", printer);
(void)unlink(".railmag");
} else {
@@ -697,7 +719,7 @@ start:
dup2(fi, 0);
dup2(fo, 1);
unlink(tempfile);
- n = open(tempfile, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0664);
+ n = open(tempfile, O_WRONLY|O_CREAT|O_EXCL, 0664);
if (n >= 0)
dup2(n, 2);
closelog();
@@ -729,10 +751,11 @@ start:
tof = 0;
/* Copy filter output to "lf" logfile */
- if ((fp = fopen(tempfile, "r")) != NULL) {
- while (fgets(buf, sizeof(buf), fp))
- fputs(buf, stderr);
- fclose(fp);
+ fd = safe_open(tempfile, O_RDONLY|O_NOFOLLOW, 0);
+ if (fd >= 0) {
+ while ((nread = read(fd, buf, sizeof(buf))) > 0)
+ (void)write(STDERR_FILENO, buf, nread);
+ close(fd);
}
if (!WIFEXITED(status)) {
@@ -750,7 +773,7 @@ start:
return(ERROR);
default:
syslog(LOG_WARNING, "%s: filter '%c' exited (retcode=%d)",
- printer, format, WEXITSTATUS(status));
+ printer, format, WEXITSTATUS(status));
return(FILTERERR);
}
}
@@ -763,13 +786,12 @@ start:
static int
sendit(char *file)
{
- int i, err = OK;
+ int fd, i, err = OK;
char *cp, last[BUFSIZ];
- /*
- * open control file
- */
- if ((cfp = fopen(file, "r")) == NULL)
+ /* open control file */
+ fd = safe_open(file, O_RDONLY|O_NOFOLLOW, 0);
+ if (fd < 0 || (cfp = fdopen(fd, "r")) == NULL)
return(OK);
/*
* read the control file for work to do
@@ -853,8 +875,12 @@ sendfile(int type, char *file)
char buf[BUFSIZ];
int sizerr, resp;
- if (lstat(file, &stb) < 0 || (f = open(file, O_RDONLY)) < 0)
+ PRIV_START;
+ if (lstat(file, &stb) < 0 || (f = safe_open(file, O_RDONLY, 0)) < 0) {
+ PRIV_END;
return(ERROR);
+ }
+ PRIV_END;
/*
* Check to see if data file is a symbolic link. If so, it should
* still point to the same file or someone is trying to print something
@@ -1140,11 +1166,12 @@ sendmail(char *user, int bombed)
/*
* dofork - fork with retries on failure
*/
-static int
+static pid_t
dofork(int action)
{
- int i, pid;
struct passwd *pw;
+ pid_t pid;
+ int i;
for (i = 0; i < 20; i++) {
if ((pid = fork()) < 0) {
@@ -1155,6 +1182,7 @@ dofork(int action)
* Child should run as daemon instead of root
*/
if (pid == 0) {
+ PRIV_START;
pw = getpwuid(DU);
if (pw == 0) {
syslog(LOG_ERR, "uid %ld not in password file",
@@ -1279,6 +1307,7 @@ init(void)
/*
* Acquire line printer or remote connection.
+ * XXX - should push down privs in here
*/
static void
openpr(void)
@@ -1477,7 +1506,7 @@ static void
setty(void)
{
struct info i;
- char **argv, **ap, *p, *val;
+ char **argv, **ap, **ep, *p, *val;
i.fd = pfd;
i.set = i.wset = 0;
@@ -1514,19 +1543,26 @@ setty(void)
syslog(LOG_INFO, "%s: ioctl(TIOCGWINSZ): %m",
printer);
- argv = (char **)calloc(256, sizeof(char *));
+ argv = (char **)malloc(256 * sizeof(char *));
if (argv == NULL) {
- syslog(LOG_ERR, "%s: calloc: %m", printer);
+ syslog(LOG_ERR, "%s: malloc: %m", printer);
exit(1);
}
p = strdup(MS);
ap = argv;
+ ep = argv + 255;
while ((val = strsep(&p, " \t,")) != NULL) {
if ((*ap++ = strdup(val)) == NULL) {
syslog(LOG_ERR, "%s: strdup: %m", printer);
exit(1);
}
+ if (ap == ep) {
+ syslog(LOG_ERR, "%s: too many \"ms\" entries",
+ printer);
+ exit(1);
+ }
}
+ *ap = NULL;
for (; *argv; ++argv) {
if (ksearch(&argv, &i))
@@ -1573,8 +1609,8 @@ pstatus(const char *msg, ...)
va_start(ap, msg);
umask(0);
- fd = open(ST, O_WRONLY|O_CREAT, 0664);
- if (fd < 0 || flock(fd, LOCK_EX) < 0) {
+ fd = open(ST, O_WRONLY|O_CREAT|O_NOFOLLOW|O_EXLOCK, 0660);
+ if (fd < 0) {
syslog(LOG_ERR, "%s: %s: %m", printer, ST);
exit(1);
}
diff --git a/usr.sbin/lpr/lpd/recvjob.c b/usr.sbin/lpr/lpd/recvjob.c
index 2d2d9b0c0cc..4962d4175ec 100644
--- a/usr.sbin/lpr/lpd/recvjob.c
+++ b/usr.sbin/lpr/lpd/recvjob.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: recvjob.c,v 1.20 2002/05/20 23:13:50 millert Exp $ */
+/* $OpenBSD: recvjob.c,v 1.21 2002/06/08 01:53:43 millert Exp $ */
/* $NetBSD: recvjob.c,v 1.14 2001/12/04 22:52:44 christos Exp $ */
/*
@@ -45,7 +45,7 @@ static const char copyright[] =
#if 0
static const char sccsid[] = "@(#)recvjob.c 8.2 (Berkeley) 4/27/95";
#else
-static const char rcsid[] = "$OpenBSD: recvjob.c,v 1.20 2002/05/20 23:13:50 millert Exp $";
+static const char rcsid[] = "$OpenBSD: recvjob.c,v 1.21 2002/06/08 01:53:43 millert Exp $";
#endif
#endif /* not lint */
@@ -113,10 +113,12 @@ recvjob(void)
LO = DEFLOCK;
(void)close(2); /* set up log file */
+ PRIV_START;
if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {
syslog(LOG_ERR, "%s: %m", LF);
(void)open(_PATH_DEVNULL, O_WRONLY);
}
+ PRIV_END;
if (chdir(SD) < 0)
frecverr("%s: %s: %m", printer, SD);
@@ -128,6 +130,7 @@ recvjob(void)
}
} else if (stat(SD, &stb) < 0)
frecverr("%s: %s: %m", printer, SD);
+
minfree = 2 * read_number("minfree"); /* scale KB to 512 blocks */
signal(SIGTERM, rcleanup);
signal(SIGPIPE, rcleanup);
@@ -191,12 +194,22 @@ readjob(void)
(void)write(STDOUT_FILENO, "\2", 1);
continue;
}
+ /*
+ * XXX
+ * We blindly believe what the remote host puts
+ * for the path to the df file. In general this
+ * is OK since we don't allow paths with '/' in
+ * them. Still, it would be better to sanity
+ * check the cf file sent to us and make the
+ * df name match the cf name we used. That way
+ * we avoid any possible collisions.
+ */
if (!readfile(tfname, size)) {
rcleanup(0);
continue;
}
if (link(tfname, cp) < 0)
- frecverr("%s: %m", tfname);
+ frecverr("link %s %s: %m", tfname, cp);
(void)unlink(tfname);
tfname[0] = '\0';
nfiles++;
@@ -233,8 +246,7 @@ readfile(char *file, int size)
int i, j, amt;
int fd, err;
- fd = open(file, O_CREAT|O_EXCL|O_WRONLY, FILMOD);
- if (fd < 0)
+ if ((fd = open(file, O_CREAT|O_EXCL|O_WRONLY, FILMOD)) < 0)
frecverr("readfile: %s: illegal path name: %m", file);
ack();
err = 0;
@@ -311,7 +323,7 @@ read_number(char *fn)
if ((fp = fopen(fn, "r")) == NULL)
return (0);
- if (fgets(lin, 80, fp) == NULL) {
+ if (fgets(lin, sizeof(lin), fp) == NULL) {
fclose(fp);
return (0);
}
diff --git a/usr.sbin/lpr/lpq/Makefile b/usr.sbin/lpr/lpq/Makefile
index 79e229243dd..dcf9ec818a7 100644
--- a/usr.sbin/lpr/lpq/Makefile
+++ b/usr.sbin/lpr/lpq/Makefile
@@ -1,12 +1,11 @@
# from: @(#)Makefile 8.1 (Berkeley) 6/6/93
-# $OpenBSD: Makefile,v 1.3 2002/05/20 23:13:50 millert Exp $
+# $OpenBSD: Makefile,v 1.4 2002/06/08 01:53:43 millert Exp $
PROG= lpq
CFLAGS+=-I${.CURDIR}/../common_source
SRCS= lpq.c displayq.c common.c common_vars.c
-BINOWN= root
BINGRP= daemon
-BINMODE=6555
+BINMODE=2555
BINDIR= /usr/bin
.PATH: ${.CURDIR}/../common_source
diff --git a/usr.sbin/lpr/lpq/lpq.c b/usr.sbin/lpr/lpq/lpq.c
index bc90790276d..1ca80fdd1cb 100644
--- a/usr.sbin/lpr/lpq/lpq.c
+++ b/usr.sbin/lpr/lpq/lpq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lpq.c,v 1.12 2002/05/20 23:13:50 millert Exp $ */
+/* $OpenBSD: lpq.c,v 1.13 2002/06/08 01:53:43 millert Exp $ */
/* $NetBSD: lpq.c,v 1.9 1999/12/07 14:54:47 mrg Exp $ */
/*
@@ -45,7 +45,7 @@ static const char copyright[] =
#if 0
static const char sccsid[] = "@(#)lpq.c 8.3 (Berkeley) 5/10/95";
#else
-static const char rcsid[] = "$OpenBSD: lpq.c,v 1.12 2002/05/20 23:13:50 millert Exp $";
+static const char rcsid[] = "$OpenBSD: lpq.c,v 1.13 2002/06/08 01:53:43 millert Exp $";
#endif
#endif /* not lint */
@@ -64,6 +64,7 @@ static const char rcsid[] = "$OpenBSD: lpq.c,v 1.12 2002/05/20 23:13:50 millert
#include <ctype.h>
#include <dirent.h>
#include <err.h>
+#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
@@ -90,9 +91,11 @@ main(int argc, char **argv)
char *buf, *cp;
long l;
- euid = geteuid();
- uid = getuid();
- seteuid(uid);
+ effective_uid = geteuid();
+ real_uid = getuid();
+ effective_gid = getegid();
+ real_gid = getgid();
+ PRIV_END; /* be safe */
if (gethostname(host, sizeof(host)) != 0)
err(1, "gethostname");
@@ -162,6 +165,7 @@ main(int argc, char **argv)
exit(0);
}
+/* XXX - could be common w/ lpd */
static int
ckqueue(char *cap)
{
diff --git a/usr.sbin/lpr/lpr/Makefile b/usr.sbin/lpr/lpr/Makefile
index c53d3fcfed2..4bc5e2b9b89 100644
--- a/usr.sbin/lpr/lpr/Makefile
+++ b/usr.sbin/lpr/lpr/Makefile
@@ -1,10 +1,10 @@
# from: @(#)Makefile 8.1 (Berkeley) 6/6/93
-# $OpenBSD: Makefile,v 1.3 2002/05/20 23:13:50 millert Exp $
+# $OpenBSD: Makefile,v 1.4 2002/06/08 01:53:43 millert Exp $
PROG= lpr
CFLAGS+=-I${.CURDIR}/../common_source
SRCS= lpr.c startdaemon.c common.c common_vars.c
-BINOWN= root
+BINOWN= daemon
BINGRP= daemon
BINMODE=6555
BINDIR= /usr/bin
diff --git a/usr.sbin/lpr/lpr/lpr.c b/usr.sbin/lpr/lpr/lpr.c
index 348a38b94d9..fbcd36e70fb 100644
--- a/usr.sbin/lpr/lpr/lpr.c
+++ b/usr.sbin/lpr/lpr/lpr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lpr.c,v 1.25 2002/05/20 23:13:50 millert Exp $ */
+/* $OpenBSD: lpr.c,v 1.26 2002/06/08 01:53:43 millert Exp $ */
/* $NetBSD: lpr.c,v 1.19 2000/10/11 20:23:52 is Exp $ */
/*
@@ -50,7 +50,7 @@ static const char copyright[] =
#if 0
static const char sccsid[] = "@(#)lpr.c 8.4 (Berkeley) 4/28/95";
#else
-static const char rcsid[] = "$OpenBSD: lpr.c,v 1.25 2002/05/20 23:13:50 millert Exp $";
+static const char rcsid[] = "$OpenBSD: lpr.c,v 1.26 2002/06/08 01:53:43 millert Exp $";
#endif
#endif /* not lint */
@@ -66,6 +66,7 @@ static const char rcsid[] = "$OpenBSD: lpr.c,v 1.25 2002/05/20 23:13:50 millert
#include <sys/file.h>
#include <dirent.h>
+#include <errno.h>
#include <fcntl.h>
#include <a.out.h>
#include <signal.h>
@@ -103,7 +104,6 @@ static int sflag; /* symbolic link flag */
static int tfd; /* control file descriptor */
static char *tfname; /* tmp copy of cf before linking */
static char *title; /* pr'ing title */
-static int userid; /* user id */
static char *width; /* width for versatec printing */
static struct stat statb;
@@ -132,9 +132,11 @@ main(int argc, char **argv)
int i, f, ch;
struct stat stb;
- euid = geteuid();
- uid = getuid();
- seteuid(uid);
+ effective_uid = geteuid();
+ real_uid = getuid();
+ effective_gid = getegid();
+ real_gid = getgid();
+ PRIV_END; /* be safe */
if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
signal(SIGHUP, cleanup);
@@ -260,16 +262,16 @@ main(int argc, char **argv)
* Get the identity of the person doing the lpr using the same
* algorithm as lprm.
*/
- userid = getuid();
- if (userid != DU || person == 0) {
- if ((pw = getpwuid(userid)) == NULL)
+ if (real_uid != DU || person == NULL) {
+ if ((pw = getpwuid(real_uid)) == NULL)
errx(1, "Who are you?");
- person = pw->pw_name;
+ if ((person = strdup(pw->pw_name)) == NULL)
+ err(1, NULL);
}
/*
* Check for restricted group access.
*/
- if (RG != NULL && userid != DU) {
+ if (RG != NULL && real_uid != DU) {
if ((gptr = getgrnam(RG)) == NULL)
errx(1, "Restricted group specified incorrectly");
if (gptr->gr_gid != getgid()) {
@@ -283,19 +285,16 @@ main(int argc, char **argv)
}
}
/*
- * Check to make sure queuing is enabled if userid is not root.
+ * Check to make sure queuing is enabled if real_uid is not root.
*/
(void)snprintf(buf, sizeof(buf), "%s/%s", SD, LO);
- if (userid && stat(buf, &stb) == 0 && (stb.st_mode & 010))
+ if (real_uid && stat(buf, &stb) == 0 && (stb.st_mode & 010))
errx(1, "Printer queue is disabled");
/*
* Initialize the control file.
*/
mktemps();
tfd = nfile(tfname);
- seteuid(euid);
- (void)fchown(tfd, DU, -1); /* owned by daemon for protection */
- seteuid(uid);
card('H', host);
card('P', person);
if (hdr) {
@@ -354,7 +353,7 @@ main(int argc, char **argv)
}
if (sflag)
warnx("%s: not linked, copying instead", arg);
- if ((i = open(arg, O_RDONLY)) < 0)
+ if ((i = safe_open(arg, O_RDONLY, 0)) < 0)
warn("%s", arg);
else {
copy(i, arg);
@@ -370,8 +369,8 @@ main(int argc, char **argv)
/*
* Touch the control file to fix position in the queue.
*/
- seteuid(euid);
- if ((tfd = open(tfname, O_RDWR)) >= 0) {
+ PRIV_START;
+ if ((tfd = safe_open(tfname, O_RDWR|O_NOFOLLOW, 0)) >= 0) {
char c;
if (read(tfd, &c, 1) == 1 &&
@@ -389,7 +388,7 @@ main(int argc, char **argv)
cleanup(0);
}
unlink(tfname);
- seteuid(uid);
+ PRIV_END;
if (qflag) /* just q things up */
exit(0);
if (!startdaemon(printer))
@@ -478,9 +477,9 @@ linked(file)
return(NULL);
file = buf;
}
- seteuid(euid);
+ PRIV_START;
ret = symlink(file, dfname);
- seteuid(uid);
+ PRIV_END;
return(ret ? NULL : file);
}
@@ -519,18 +518,14 @@ nfile(n)
int f;
int oldumask = umask(0); /* should block signals */
- seteuid(euid);
- f = open(n, O_WRONLY | O_EXCL | O_CREAT, FILMOD);
+ PRIV_START;
+ f = open(n, O_WRONLY|O_EXCL|O_CREAT, FILMOD);
(void)umask(oldumask);
if (f < 0) {
warn("%s", n);
cleanup(0);
}
- if (fchown(f, userid, -1) < 0) {
- warn("cannot chown %s", n);
- cleanup(0); /* cleanup does exit */
- }
- seteuid(uid);
+ PRIV_END;
if (++n[inchar] > 'z') {
if (++n[inchar-2] == 't') {
warnx("too many files - break up the job");
@@ -556,7 +551,7 @@ cleanup(signo)
signal(SIGQUIT, SIG_IGN);
signal(SIGTERM, SIG_IGN);
i = inchar;
- seteuid(euid);
+ PRIV_START;
if (tfname)
do
unlink(tfname);
@@ -588,20 +583,24 @@ test(file)
int fd;
char *cp;
- if ((fd = open(file, O_RDONLY)) < 0) {
- warn("cannot open %s\n", file);
+ if ((fd = open(file, O_RDONLY|O_NONBLOCK)) < 0) {
+ warn("cannot open %s", file);
goto bad;
}
if (fstat(fd, &statb) < 0) {
- warn("cannot stat %s\n", file);
+ warn("cannot stat %s", file);
goto bad;
}
if (S_ISDIR(statb.st_mode)) {
- warnx("%s is a directory\n", file);
+ warnx("%s is a directory", file);
+ goto bad;
+ }
+ if (!S_ISREG(statb.st_mode)) {
+ warnx("%s is not a regular file", file);
goto bad;
}
if (statb.st_size == 0) {
- warnx("%s is an empty file\n", file);
+ warnx("%s is an empty file", file);
goto bad;
}
if (read(fd, &execb, sizeof(execb)) == sizeof(execb) &&
@@ -687,14 +686,16 @@ mktemps()
int len, fd, n;
char *cp;
char buf[BUFSIZ];
+ struct stat stb;
- (void)snprintf(buf, sizeof(buf), "%s/.seq", SD);
- seteuid(euid);
- if ((fd = open(buf, O_RDWR|O_CREAT, 0661)) < 0)
- err(1, "cannot create %s", buf);
+ if (snprintf(buf, sizeof(buf), "%s/.seq", SD) >= sizeof(buf))
+ errx(1, "%s/.seq: %s", SD, strerror(ENAMETOOLONG));
+ PRIV_START;
+ if ((fd = safe_open(buf, O_RDWR|O_CREAT|O_NOFOLLOW, 0661)) < 0)
+ err(1, "cannot open %s", buf);
if (flock(fd, LOCK_EX))
err(1, "cannot lock %s", buf);
- seteuid(uid);
+ PRIV_END;
n = 0;
if ((len = read(fd, buf, sizeof(buf))) > 0) {
for (cp = buf; len--; ) {
@@ -704,11 +705,14 @@ mktemps()
}
}
len = strlen(SD) + strlen(host) + 8;
- tfname = lmktemp("tf", n, len);
- cfname = lmktemp("cf", n, len);
- dfname = lmktemp("df", n, len);
+ do {
+ tfname = lmktemp("tf", n, len);
+ cfname = lmktemp("cf", n, len);
+ dfname = lmktemp("df", n, len);
+ n = (n + 1) % 1000;
+ } while (stat(tfname, &stb) == 0 || stat(cfname, &stb) == 0 ||
+ stat(dfname, &stb) == 0);
inchar = strlen(SD) + 3;
- n = (n + 1) % 1000;
(void)lseek(fd, (off_t)0, 0);
snprintf(buf, sizeof(buf), "%03d\n", n);
(void)write(fd, buf, strlen(buf));
diff --git a/usr.sbin/lpr/lprm/Makefile b/usr.sbin/lpr/lprm/Makefile
index 968e100e65d..d132b8151b5 100644
--- a/usr.sbin/lpr/lprm/Makefile
+++ b/usr.sbin/lpr/lprm/Makefile
@@ -1,12 +1,11 @@
# @(#)Makefile 8.1 (Berkeley) 6/6/93
-# $OpenBSD: Makefile,v 1.3 2002/05/20 23:13:50 millert Exp $
+# $OpenBSD: Makefile,v 1.4 2002/06/08 01:53:43 millert Exp $
PROG= lprm
CFLAGS+=-I${.CURDIR}/../common_source
SRCS= lprm.c rmjob.c startdaemon.c common.c common_vars.c
-BINOWN= root
BINGRP= daemon
-BINMODE=6555
+BINMODE=2555
BINDIR= /usr/bin
.PATH: ${.CURDIR}/../common_source
diff --git a/usr.sbin/lpr/lprm/lprm.c b/usr.sbin/lpr/lprm/lprm.c
index 4c7c0d949a9..0189767a996 100644
--- a/usr.sbin/lpr/lprm/lprm.c
+++ b/usr.sbin/lpr/lprm/lprm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lprm.c,v 1.11 2002/05/20 23:13:50 millert Exp $ */
+/* $OpenBSD: lprm.c,v 1.12 2002/06/08 01:53:43 millert Exp $ */
/* $$NetBSD: lprm.c,v 1.9 1999/08/16 03:12:32 simonb Exp $ */
/*
@@ -45,7 +45,7 @@ static const char copyright[] =
#if 0
static const char sccsid[] = "@(#)lprm.c 8.1 (Berkeley) 6/6/93";
#else
-static const char rcsid[] = "$OpenBSD: lprm.c,v 1.11 2002/05/20 23:13:50 millert Exp $";
+static const char rcsid[] = "$OpenBSD: lprm.c,v 1.12 2002/06/08 01:53:43 millert Exp $";
#endif
#endif /* not lint */
@@ -65,6 +65,7 @@ static const char rcsid[] = "$OpenBSD: lprm.c,v 1.11 2002/05/20 23:13:50 millert
#include <ctype.h>
#include <dirent.h>
#include <err.h>
+#include <errno.h>
#include <pwd.h>
#include <stdlib.h>
#include <stdio.h>
@@ -96,13 +97,15 @@ main(int argc, char **argv)
long l;
int ch;
- uid = getuid();
- euid = geteuid();
- seteuid(uid); /* be safe */
+ effective_uid = geteuid();
+ real_uid = getuid();
+ effective_gid = getegid();
+ real_gid = getgid();
+ PRIV_END; /* be safe */
gethostname(host, sizeof(host));
openlog("lprm", 0, LOG_LPR);
- if ((p = getpwuid(getuid())) == NULL)
+ if ((p = getpwuid(real_uid)) == NULL)
fatal("Who are you?");
if (strlen(p->pw_name) >= sizeof(luser))
fatal("Your name is too long");
diff --git a/usr.sbin/lpr/pac/pac.c b/usr.sbin/lpr/pac/pac.c
index 3da340f36cd..bb8efb45782 100644
--- a/usr.sbin/lpr/pac/pac.c
+++ b/usr.sbin/lpr/pac/pac.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pac.c,v 1.13 2002/05/20 23:13:50 millert Exp $ */
+/* $OpenBSD: pac.c,v 1.14 2002/06/08 01:53:43 millert Exp $ */
/* $NetBSD: pac.c,v 1.14 2000/04/27 13:40:18 msaitoh Exp $ */
/*
@@ -45,7 +45,7 @@ static const char copyright[] =
#if 0
static const char sccsid[] = "@(#)pac.c 8.1 (Berkeley) 6/6/93";
#else
-static const char rcsid[] = "$OpenBSD: pac.c,v 1.13 2002/05/20 23:13:50 millert Exp $";
+static const char rcsid[] = "$OpenBSD: pac.c,v 1.14 2002/06/08 01:53:43 millert Exp $";
#endif
#endif /* not lint */
@@ -119,8 +119,12 @@ main(int argc, char **argv)
FILE *acct;
int ch;
- euid = geteuid(); /* these aren't used in pac(1) */
- uid = getuid();
+ /* these aren't actually used in pac(1) */
+ effective_uid = geteuid();
+ real_uid = getuid();
+ effective_gid = getegid();
+ real_gid = getgid();
+
while ((ch = getopt(argc, argv, "P:p:scmr")) != -1) {
switch (ch) {
case 'P':