summaryrefslogtreecommitdiffstats
path: root/usr.sbin/lpr/lpc
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>1997-07-23 00:49:46 +0000
committerimp <imp@FreeBSD.org>1997-07-23 00:49:46 +0000
commitf080009db57e6a7b246a2ab15d8a73e4563931b4 (patch)
tree3f6c130b47ee18671302ddcfcae8cef66be97455 /usr.sbin/lpr/lpc
parent5d2b7fa5ede6cefc6d4c6f7df3987bea7b9149b8 (diff)
downloadFreeBSD-src-f080009db57e6a7b246a2ab15d8a73e4563931b4.zip
FreeBSD-src-f080009db57e6a7b246a2ab15d8a73e4563931b4.tar.gz
Use setuid/seteuid around dangerous operations. Also a few buffer
overflow patches that were "near" to where these operations are taking place. The buffer overflows are from OpenBSD. The setuid/seteuid patches are from NetBSD by way of OpenBSD (they changed them a little), at least from my read of the tree. This is the first of a series of OpenBSD lpr/et al merges. It (and them) should be merged back into 2.2 and/or 2.1 (if requested) branches when they have been shaken out in -current. Obtained from: OpenBSD
Diffstat (limited to 'usr.sbin/lpr/lpc')
-rw-r--r--usr.sbin/lpr/lpc/cmds.c81
-rw-r--r--usr.sbin/lpr/lpc/lpc.c16
2 files changed, 71 insertions, 26 deletions
diff --git a/usr.sbin/lpr/lpc/cmds.c b/usr.sbin/lpr/lpc/cmds.c
index 95e46ba..36a2dd2 100644
--- a/usr.sbin/lpr/lpc/cmds.c
+++ b/usr.sbin/lpr/lpc/cmds.c
@@ -66,6 +66,8 @@ static char sccsid[] = "@(#)cmds.c 8.2 (Berkeley) 4/28/95";
#include "extern.h"
#include "pathnames.h"
+extern uid_t uid, euid;
+
static void abortpr __P((int));
static void cleanpr __P((void));
static void disablepr __P((void));
@@ -102,7 +104,8 @@ doabort(argc, argv)
while (cgetnext(&bp, printcapdb) > 0) {
cp1 = prbuf;
cp2 = bp;
- while ((c = *cp2++) && c != '|' && c != ':')
+ while ((c = *cp2++) && c != '|' && c != ':' &&
+ (cp1 - prbuf) < sizeof(prbuf))
*cp1++ = c;
*cp1 = '\0';
abortpr(1);
@@ -135,13 +138,14 @@ abortpr(dis)
SD = _PATH_DEFSPOOL;
if (cgetstr(bp, "lo", &LO) == -1)
LO = DEFLOCK;
- (void) sprintf(line, "%s/%s", SD, LO);
+ (void) snprintf(line, sizeof(line), "%s/%s", SD, LO);
printf("%s:\n", printer);
/*
* 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)
printf("\tcannot disable printing\n");
@@ -158,10 +162,10 @@ abortpr(dis)
printf("\tprinting disabled\n");
printf("\tno daemon to abort\n");
}
- return;
+ goto out;
} else {
printf("\tcannot stat lock file\n");
- return;
+ goto out;
}
}
/*
@@ -169,18 +173,23 @@ abortpr(dis)
*/
if ((fp = fopen(line, "r")) == NULL) {
printf("\tcannot open lock file\n");
- return;
+ goto out;
}
if (!getline(fp) || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) {
(void) fclose(fp); /* unlocks as well */
printf("\tno daemon to abort\n");
- return;
+ goto out;
}
(void) fclose(fp);
- if (kill(pid = atoi(line), SIGTERM) < 0)
- printf("\tWarning: daemon (pid %d) not killed\n", pid);
- else
+ if (kill(pid = atoi(line), SIGTERM) < 0) {
+ if (errno == ESRCH)
+ printf("\tno daemon to abort\n");
+ else
+ printf("\tWarning: daemon (pid %d) not killed\n", pid);
+ } else
printf("\tdaemon (pid %d) killed\n", pid);
+out:
+ seteuid(uid);
}
/*
@@ -305,11 +314,13 @@ cleanpr()
SD = _PATH_DEFSPOOL;
printf("%s:\n", printer);
- for (lp = line, cp = SD; (*lp++ = *cp++); )
+ for (lp = line, cp = SD; (lp - line) < sizeof(line) && (*lp++ = *cp++);)
;
lp[-1] = '/';
+ seteuid(euid);
nitems = scandir(SD, &queue, doselect, sortq);
+ seteuid(uid);
if (nitems < 0) {
printf("\tcannot examine spool directory\n");
return;
@@ -345,15 +356,17 @@ cleanpr()
}
} while (++i < nitems);
}
-
+
static void
unlinkf(name)
char *name;
{
+ seteuid(euid);
if (unlink(name) < 0)
printf("\tcannot remove %s\n", name);
else
printf("\tremoved %s\n", name);
+ seteuid(uid);
}
/*
@@ -408,18 +421,20 @@ enablepr()
SD = _PATH_DEFSPOOL;
if (cgetstr(bp, "lo", &LO) == -1)
LO = DEFLOCK;
- (void) sprintf(line, "%s/%s", SD, LO);
+ (void) snprintf(line, sizeof(line), "%s/%s", SD, LO);
printf("%s:\n", printer);
/*
* Turn off the group execute bit of the lock file to enable queuing.
*/
+ seteuid(euid);
if (stat(line, &stbuf) >= 0) {
if (chmod(line, stbuf.st_mode & 0767) < 0)
printf("\tcannot enable queuing\n");
else
printf("\tqueuing enabled\n");
}
+ seteuid(uid);
}
/*
@@ -475,11 +490,12 @@ disablepr()
SD = _PATH_DEFSPOOL;
if (cgetstr(bp, "lo", &LO) == -1)
LO = DEFLOCK;
- (void) sprintf(line, "%s/%s", SD, LO);
+ (void) snprintf(line, sizeof(line), "%s/%s", SD, LO);
printf("%s:\n", printer);
/*
* Turn on the group execute bit of the lock file to disable queuing.
*/
+ seteuid(euid);
if (stat(line, &stbuf) >= 0) {
if (chmod(line, (stbuf.st_mode & 0777) | 010) < 0)
printf("\tcannot disable queuing\n");
@@ -492,9 +508,9 @@ disablepr()
(void) close(fd);
printf("\tqueuing disabled\n");
}
- return;
} else
printf("\tcannot stat lock file\n");
+ seteuid(uid);
}
/*
@@ -560,7 +576,8 @@ putmsg(argc, argv)
* Turn on the group execute bit of the lock file to disable queuing and
* turn on the owner execute bit of the lock file to disable printing.
*/
- (void) sprintf(line, "%s/%s", SD, LO);
+ (void) snprintf(line, sizeof(line), "%s/%s", SD, LO);
+ seteuid(euid);
if (stat(line, &stbuf) >= 0) {
if (chmod(line, (stbuf.st_mode & 0777) | 0110) < 0)
printf("\tcannot disable queuing\n");
@@ -573,18 +590,21 @@ putmsg(argc, argv)
(void) close(fd);
printf("\tprinter and queuing disabled\n");
}
+ seteuid(uid);
return;
} else
printf("\tcannot stat lock file\n");
/*
* Write the message into the status file.
*/
- (void) sprintf(line, "%s/%s", SD, ST);
+ (void) snprintf(line, sizeof(line), "%s/%s", SD, ST);
fd = open(line, O_WRONLY|O_CREAT, 0664);
if (fd < 0 || flock(fd, LOCK_EX) < 0) {
printf("\tcannot create status file\n");
+ seteuid(uid);
return;
}
+ seteuid(uid);
(void) ftruncate(fd, 0);
if (argc <= 0) {
(void) write(fd, "\n", 1);
@@ -713,12 +733,13 @@ startpr(enable)
SD = _PATH_DEFSPOOL;
if (cgetstr(bp, "lo", &LO) == -1)
LO = DEFLOCK;
- (void) sprintf(line, "%s/%s", SD, LO);
+ (void) snprintf(line, sizeof(line), "%s/%s", SD, LO);
printf("%s:\n", printer);
/*
* Turn off the owner execute bit of the lock file to enable printing.
*/
+ seteuid(euid);
if (enable && stat(line, &stbuf) >= 0) {
if (chmod(line, stbuf.st_mode & (enable==2 ? 0666 : 0677)) < 0)
printf("\tcannot enable printing\n");
@@ -729,6 +750,7 @@ startpr(enable)
printf("\tcouldn't start daemon\n");
else
printf("\tdaemon started\n");
+ seteuid(uid);
}
/*
@@ -890,12 +912,13 @@ stoppr()
SD = _PATH_DEFSPOOL;
if (cgetstr(bp, "lo", &LO) == -1)
LO = DEFLOCK;
- (void) sprintf(line, "%s/%s", SD, LO);
+ (void) snprintf(line, sizeof(line), "%s/%s", SD, LO);
printf("%s:\n", printer);
/*
* Turn on the owner execute bit of the lock file to disable printing.
*/
+ seteuid(euid);
if (stat(line, &stbuf) >= 0) {
if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0)
printf("\tcannot disable printing\n");
@@ -913,6 +936,7 @@ stoppr()
}
} else
printf("\tcannot stat lock file\n");
+ seteuid(uid);
}
struct queue **queue;
@@ -954,10 +978,12 @@ topq(argc, argv)
LO = DEFLOCK;
printf("%s:\n", printer);
+ seteuid(euid);
if (chdir(SD) < 0) {
printf("\tcannot chdir to %s\n", SD);
- return;
+ goto out;
}
+ seteuid(uid);
nitems = getq(&queue);
if (nitems == 0)
return;
@@ -981,9 +1007,13 @@ topq(argc, 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);
-}
+
+out:
+ seteuid(uid);
+}
/*
* Reposition the job by changing the modification time of
@@ -994,10 +1024,14 @@ touch(q)
struct queue *q;
{
struct timeval tvp[2];
+ int ret;
tvp[0].tv_sec = tvp[1].tv_sec = --mtime;
tvp[0].tv_usec = tvp[1].tv_usec = 0;
- return(utimes(q->q_name, tvp));
+ seteuid(euid);
+ ret = utimes(q->q_name, tvp);
+ seteuid(uid);
+ return (ret);
}
/*
@@ -1054,7 +1088,10 @@ doarg(job)
* Process item consisting of owner's name (example: henry).
*/
for (qq = queue + nitems; --qq >= queue; ) {
- if ((fp = fopen((*qq)->q_name, "r")) == NULL)
+ seteuid(euid);
+ fp = fopen((*qq)->q_name, "r");
+ seteuid(uid);
+ if (fp == NULL)
continue;
while (getline(fp) > 0)
if (line[0] == 'P')
diff --git a/usr.sbin/lpr/lpc/lpc.c b/usr.sbin/lpr/lpc/lpc.c
index 5135163..353d7cb 100644
--- a/usr.sbin/lpr/lpc/lpc.c
+++ b/usr.sbin/lpr/lpc/lpc.c
@@ -67,12 +67,15 @@ static char sccsid[] = "@(#)lpc.c 8.3 (Berkeley) 4/28/95";
* lpc -- line printer control program
*/
+#define MAX_CMDLINE 200
+#define MAX_MARGV 20
int fromatty;
-char cmdline[200];
+char cmdline[MAX_CMDLINE];
int margc;
-char *margv[20];
+char *margv[MAX_MARGV];
int top;
+uid_t uid, euid;
jmp_buf toplevel;
@@ -89,6 +92,9 @@ main(argc, argv)
{
register struct cmd *c;
+ euid = geteuid();
+ uid = getuid();
+ seteuid(uid);
name = argv[0];
openlog("lpd", 0, LOG_LPR);
@@ -144,7 +150,7 @@ cmdscanner(top)
printf("lpc> ");
fflush(stdout);
}
- if (fgets(cmdline, sizeof(cmdline), stdin) == 0)
+ if (fgets(cmdline, MAX_CMDLINE, stdin) == 0)
quit(0, NULL);
if (cmdline[0] == 0 || cmdline[0] == '\n')
break;
@@ -204,9 +210,11 @@ makeargv()
{
register char *cp;
register char **argp = margv;
+ register int n = 0;
margc = 0;
- for (cp = cmdline; *cp;) {
+ for (cp = cmdline; *cp && (cp - cmdline) < sizeof(cmdline) &&
+ n < MAX_MARGV; n++) {
while (isspace(*cp))
cp++;
if (*cp == '\0')
OpenPOWER on IntegriCloud