diff options
author | imp <imp@FreeBSD.org> | 1997-07-23 00:49:46 +0000 |
---|---|---|
committer | imp <imp@FreeBSD.org> | 1997-07-23 00:49:46 +0000 |
commit | f080009db57e6a7b246a2ab15d8a73e4563931b4 (patch) | |
tree | 3f6c130b47ee18671302ddcfcae8cef66be97455 /usr.sbin | |
parent | 5d2b7fa5ede6cefc6d4c6f7df3987bea7b9149b8 (diff) | |
download | FreeBSD-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')
-rw-r--r-- | usr.sbin/lpr/common_source/common.c | 10 | ||||
-rw-r--r-- | usr.sbin/lpr/common_source/displayq.c | 34 | ||||
-rw-r--r-- | usr.sbin/lpr/common_source/rmjob.c | 36 | ||||
-rw-r--r-- | usr.sbin/lpr/common_source/startdaemon.c | 10 | ||||
-rw-r--r-- | usr.sbin/lpr/lpc/cmds.c | 81 | ||||
-rw-r--r-- | usr.sbin/lpr/lpc/lpc.c | 16 | ||||
-rw-r--r-- | usr.sbin/lpr/lpd/lpd.c | 17 | ||||
-rw-r--r-- | usr.sbin/lpr/lpq/lpq.c | 5 | ||||
-rw-r--r-- | usr.sbin/lpr/lpr/lpr.c | 32 | ||||
-rw-r--r-- | usr.sbin/lpr/lprm/lprm.c | 4 | ||||
-rw-r--r-- | usr.sbin/lpr/pac/pac.c | 4 |
11 files changed, 199 insertions, 50 deletions
diff --git a/usr.sbin/lpr/common_source/common.c b/usr.sbin/lpr/common_source/common.c index 9f1ee41..8c77774 100644 --- a/usr.sbin/lpr/common_source/common.c +++ b/usr.sbin/lpr/common_source/common.c @@ -109,6 +109,8 @@ char *from = host; /* client's machine name */ int remote; /* true if sending files to a remote host */ char *printcapdb[2] = { _PATH_PRINTCAP, 0 }; +extern uid_t uid, euid; + static int compar __P((const void *, const void *)); /* @@ -155,7 +157,9 @@ getport(rhost, rport) * Try connecting to the server. */ retry: + seteuid(euid); s = rresvport(&lport); + seteuid(uid); if (s < 0) return(-1); if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { @@ -222,14 +226,16 @@ getq(namelist) DIR *dirp; int arraysz; + seteuid(euid); if ((dirp = opendir(SD)) == NULL) return(-1); if (fstat(dirp->dd_fd, &stbuf) < 0) goto errdone; + seteuid(uid); /* * Estimate the array size by taking the size of the directory file - * and dividing it by a multiple of the minimum size entry. + * and dividing it by a multiple of the minimum size entry. */ arraysz = (stbuf.st_size / 24); queue = (struct queue **)malloc(arraysz * sizeof(struct queue *)); @@ -240,8 +246,10 @@ 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); if (stat(d->d_name, &stbuf) < 0) continue; /* Doesn't exist */ + seteuid(uid); q = (struct queue *)malloc(sizeof(time_t)+strlen(d->d_name)+1); if (q == NULL) goto errdone; diff --git a/usr.sbin/lpr/common_source/displayq.c b/usr.sbin/lpr/common_source/displayq.c index a5b8b26..eafaf0c 100644 --- a/usr.sbin/lpr/common_source/displayq.c +++ b/usr.sbin/lpr/common_source/displayq.c @@ -61,6 +61,8 @@ static char sccsid[] = "@(#)displayq.c 8.4 (Berkeley) 4/28/95"; /* * Stuff for handling job specifications */ +extern uid_t uid, euid; + static int col; /* column on screen */ static char current[40]; /* current file being printed */ static char file[132]; /* print file name */ @@ -83,7 +85,7 @@ displayq(format) int format; { register struct queue *q; - register int i, nitems, fd; + register int i, nitems, fd, ret; register char *cp; struct queue **queue; struct stat statb; @@ -110,23 +112,30 @@ displayq(format) if (cgetstr(bp, "st", &ST) < 0) ST = DEFSTAT; cgetstr(bp, "rm", &RM); - if (cp = checkremote()) + if ((cp = checkremote())) printf("Warning: %s\n", cp); /* * Print out local queue * Find all the control files in the spooling directory */ + seteuid(euid); if (chdir(SD) < 0) fatal("cannot chdir to spooling directory"); + seteuid(uid); if ((nitems = getq(&queue)) < 0) fatal("cannot examine spooling area\n"); - if (stat(LO, &statb) >= 0) { + seteuid(euid); + ret = stat(LO, &statb); + seteuid(uid); + 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); while ((i = read(fd, line, sizeof(line))) > 0) @@ -143,7 +152,9 @@ displayq(format) } if (nitems) { + seteuid(euid); fp = fopen(LO, "r"); + seteuid(uid); if (fp == NULL) warn(); else { @@ -153,9 +164,16 @@ displayq(format) *cp++ = i; *cp = '\0'; i = atoi(current); - if (i <= 0 || kill(i, 0) < 0) + if (i <= 0) { + ret = -1; + } else { + seteuid(euid); + ret = kill(i, 0); + seteuid(uid); + } + if (ret < 0) { warn(); - else { + } else { /* read current file name */ cp = current; while ((i = getc(fp)) != EOF && i != '\n') @@ -166,7 +184,9 @@ displayq(format) */ if (remote) printf("%s: ", host); + seteuid(euid); fd = open(ST, O_RDONLY); + seteuid(uid); if (fd >= 0) { (void) flock(fd, LOCK_SH); while ((i = read(fd, line, sizeof(line))) > 0) @@ -269,8 +289,10 @@ inform(cf) * 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) return; + seteuid(uid); if (rank < 0) rank = 0; @@ -401,8 +423,10 @@ dump(nfile, file, copies) printf("%s", nfile); col += n+fill; } + seteuid(euid); if (*file && !stat(file, &lbuf)) totsize += copies * lbuf.st_size; + seteuid(uid); } /* diff --git a/usr.sbin/lpr/common_source/rmjob.c b/usr.sbin/lpr/common_source/rmjob.c index e4f068b..a04b483 100644 --- a/usr.sbin/lpr/common_source/rmjob.c +++ b/usr.sbin/lpr/common_source/rmjob.c @@ -61,6 +61,10 @@ static int all = 0; /* eliminate all files (root only) */ static int cur_daemon; /* daemon's pid */ static char current[40]; /* active control file name */ +extern uid_t uid, euid; /* real and effective user id's */ + +static void do_unlink __P((char *)); + void rmjob() { @@ -106,10 +110,12 @@ rmjob() person = root; } + seteuid(euid); if (chdir(SD) < 0) fatal("cannot chdir to spool directory"); if ((nitems = scandir(".", &files, iscf, NULL)) < 0) fatal("cannot access spool directory"); + seteuid(uid); if (nitems) { /* @@ -118,7 +124,9 @@ rmjob() * (after which we have to restart the daemon). */ if (lockchk(LO) && chk(current)) { + seteuid(euid); assasinated = kill(cur_daemon, SIGINT) == 0; + seteuid(uid); if (!assasinated) fatal("cannot kill printer daemon"); } @@ -149,17 +157,20 @@ lockchk(s) register FILE *fp; register int i, n; - if ((fp = fopen(s, "r")) == NULL) + seteuid(euid); + if ((fp = fopen(s, "r")) == NULL) { 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 */ } cur_daemon = atoi(line); - if (kill(cur_daemon, 0) < 0) { + if (kill(cur_daemon, 0) < 0 && errno != EPERM) { (void) fclose(fp); return(0); /* no daemon present */ } @@ -186,8 +197,10 @@ process(file) if (!chk(file)) return; + seteuid(euid); if ((cfp = fopen(file, "r")) == NULL) fatal("cannot open %s", file); + seteuid(uid); while (getline(cfp)) { switch (line[0]) { case 'U': /* unlink associated files */ @@ -195,14 +208,25 @@ process(file) break; if (from != host) printf("%s: ", host); - printf(unlink(line+1) ? "cannot dequeue %s\n" : - "%s dequeued\n", line+1); + do_unlink(line+1); } } (void) fclose(cfp); + do_unlink(file); +} + +static void +do_unlink(file) + char *file; +{ + int ret; + if (from != host) printf("%s: ", host); - printf(unlink(file) ? "cannot dequeue %s\n" : "%s dequeued\n", file); + seteuid(euid); + ret = unlink(file); + seteuid(uid); + printf(ret ? "cannot dequeue %s\n" : "%s dequeued\n", file); } /* @@ -228,8 +252,10 @@ chk(file) /* * get the owner's name from the control file. */ + seteuid(euid); if ((cfp = fopen(file, "r")) == NULL) 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 807a976..a876c1e 100644 --- a/usr.sbin/lpr/common_source/startdaemon.c +++ b/usr.sbin/lpr/common_source/startdaemon.c @@ -48,6 +48,8 @@ static char sccsid[] = "@(#)startdaemon.c 8.2 (Berkeley) 4/17/94"; #include "lp.h" #include "pathnames.h" +extern uid_t uid, euid; + static void perr __P((char *)); /* @@ -73,12 +75,18 @@ startdaemon(printer) #ifndef SUN_LEN #define SUN_LEN(unp) (strlen((unp)->sun_path) + 2) #endif + seteuid(euid); if (connect(s, (struct sockaddr *)&un, SUN_LEN(&un)) < 0) { + seteuid(uid); perr("connect"); (void) close(s); return(0); } - (void) sprintf(buf, "\1%s\n", printer); + seteuid(uid); + if (snprintf(buf, sizeof buf, "\1%s\n", printer) > sizeof buf-1) { + close(s); + return (0); + } n = strlen(buf); if (write(s, buf, n) != n) { perr("write"); 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') diff --git a/usr.sbin/lpr/lpd/lpd.c b/usr.sbin/lpr/lpd/lpd.c index 65c8891..1a7448a 100644 --- a/usr.sbin/lpr/lpd/lpd.c +++ b/usr.sbin/lpr/lpd/lpd.c @@ -107,6 +107,8 @@ static void startup __P((void)); static void chkhost __P((struct sockaddr_in *)); static int ckqueue __P((char *)); +uid_t uid, euid; + int main(argc, argv) int argc; @@ -118,9 +120,17 @@ main(argc, argv) struct sockaddr_in sin, frominet; int omask, lfd; + euid = geteuid(); /* these shouldn't be different */ + uid = getuid(); options = 0; gethostname(host, sizeof(host)); - name = argv[0]; + + name = "lpd"; + + if (euid != 0) { + fprintf(stderr,"lpd: must run as root\n"); + exit(1); + } while (--argc > 0) { argv++; @@ -532,11 +542,6 @@ chkhost(f) int first = 1; int good = 0; - f->sin_port = ntohs(f->sin_port); - if (f->sin_family != AF_INET || f->sin_port >= IPPORT_RESERVED || - f->sin_port == htons(20)) - fatal("Malformed from address"); - /* Need real hostname for temporary filenames */ hp = gethostbyaddr((char *)&f->sin_addr, sizeof(struct in_addr), f->sin_family); diff --git a/usr.sbin/lpr/lpq/lpq.c b/usr.sbin/lpr/lpq/lpq.c index 0e3ec33..56705bc 100644 --- a/usr.sbin/lpr/lpq/lpq.c +++ b/usr.sbin/lpr/lpq/lpq.c @@ -69,6 +69,8 @@ int requests; /* # of spool requests */ char *user[MAXUSERS]; /* users to process */ int users; /* # of users in user array */ +uid_t uid, euid; + static int ckqueue __P((char *)); void usage __P((void)); @@ -82,6 +84,9 @@ main(argc, argv) int ch, aflag, lflag; char *buf, *cp; + euid = geteuid(); + uid = getuid(); + seteuid(uid); name = *argv; if (gethostname(host, sizeof(host))) { perror("lpq: gethostname"); diff --git a/usr.sbin/lpr/lpr/lpr.c b/usr.sbin/lpr/lpr/lpr.c index e362f03..4b66acc0e 100644 --- a/usr.sbin/lpr/lpr/lpr.c +++ b/usr.sbin/lpr/lpr/lpr.c @@ -45,7 +45,7 @@ static char copyright[] = #ifndef lint static char sccsid[] = "From: @(#)lpr.c 8.4 (Berkeley) 4/28/95" - "\n$Id: lpr.c,v 1.15 1997/05/13 20:46:45 brian Exp $\n"; + "\n$Id: lpr.c,v 1.16 1997/07/08 21:03:16 dima Exp $\n"; #endif /* not lint */ /* @@ -113,6 +113,8 @@ static int nfile __P((char *)); static int test __P((char *)); static void usage __P((void)); +uid_t uid, euid; + int main(argc, argv) int argc; @@ -125,6 +127,9 @@ main(argc, argv) int c, i, f, errs; struct stat stb; + euid = geteuid(); + uid = getuid(); + seteuid(uid); if (signal(SIGHUP, SIG_IGN) != SIG_IGN) signal(SIGHUP, cleanup); if (signal(SIGINT, SIG_IGN) != SIG_IGN) @@ -281,7 +286,9 @@ main(argc, argv) */ 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) { @@ -355,6 +362,7 @@ main(argc, argv) /* * Touch the control file to fix position in the queue. */ + seteuid(euid); if ((tfd = open(tfname, O_RDWR)) >= 0) { char c; @@ -373,6 +381,7 @@ main(argc, argv) cleanup(0); } unlink(tfname); + seteuid(uid); if (qflag) /* just q things up */ exit(0); if (!startdaemon(printer)) @@ -380,6 +389,7 @@ main(argc, argv) exit(0); } cleanup(0); + return (1); /* NOTREACHED */ } @@ -434,6 +444,7 @@ linked(file) { register char *cp; static char buf[MAXPATHLEN]; + register int ret; if (*file != '/') { if (getcwd(buf, sizeof(buf)) == NULL) @@ -457,7 +468,10 @@ linked(file) strncat(buf, file, sizeof(buf) - strlen(buf) - 1); file = buf; } - return(symlink(file, dfname) ? NULL : file); + seteuid(euid); + ret = symlink(file, dfname); + seteuid(uid); + return(ret ? NULL : file); } /* @@ -491,6 +505,7 @@ nfile(n) register int f; int oldumask = umask(0); /* should block signals */ + seteuid(euid); f = open(n, O_WRONLY | O_EXCL | O_CREAT, FILMOD); (void) umask(oldumask); if (f < 0) { @@ -499,8 +514,9 @@ nfile(n) } if (fchown(f, userid, -1) < 0) { printf("%s: cannot chown %s\n", name, n); - cleanup(0); + cleanup(0); /* cleanup does exit */ } + seteuid(uid); if (++n[inchar] > 'z') { if (++n[inchar-2] == 't') { printf("too many files - break up the job\n"); @@ -526,6 +542,7 @@ cleanup(signo) signal(SIGQUIT, SIG_IGN); signal(SIGTERM, SIG_IGN); i = inchar; + seteuid(euid); if (tfname) do unlink(tfname); @@ -580,9 +597,9 @@ test(file) } if (read(fd, &execb, sizeof(execb)) == sizeof(execb) && !N_BADMAG(execb)) { - printf("%s: %s is an executable program", name, file); - goto error1; - } + printf("%s: %s is an executable program", name, file); + goto error1; + } (void) close(fd); if (rflag) { if ((cp = rindex(file, '/')) == NULL) { @@ -694,8 +711,10 @@ mktemps() register int len, fd, n; register char *cp; char buf[BUFSIZ]; + char *lmktemp(); (void) snprintf(buf, sizeof(buf), "%s/.seq", SD); + seteuid(euid); if ((fd = open(buf, O_RDWR|O_CREAT, 0661)) < 0) { printf("%s: cannot create %s\n", name, buf); exit(1); @@ -704,6 +723,7 @@ mktemps() printf("%s: cannot lock %s\n", name, buf); exit(1); } + seteuid(uid); n = 0; if ((len = read(fd, buf, sizeof(buf))) > 0) { for (cp = buf; len--; ) { diff --git a/usr.sbin/lpr/lprm/lprm.c b/usr.sbin/lpr/lprm/lprm.c index 20c4ee7..df3a6cb 100644 --- a/usr.sbin/lpr/lprm/lprm.c +++ b/usr.sbin/lpr/lprm/lprm.c @@ -74,6 +74,7 @@ int requ[MAXREQUESTS]; /* job number of spool entries */ int requests; /* # of spool requests */ char *user[MAXUSERS]; /* users to process */ int users; /* # of users in user array */ +uid_t uid, euid; /* real and effective user id's */ static char luser[16]; /* buffer for person */ @@ -87,6 +88,9 @@ main(argc, argv) register char *arg; struct passwd *p; + uid = getuid(); + euid = geteuid(); + seteuid(uid); /* be safe */ name = argv[0]; gethostname(host, sizeof(host)); openlog("lpd", 0, LOG_LPR); diff --git a/usr.sbin/lpr/pac/pac.c b/usr.sbin/lpr/pac/pac.c index 692f005..609d407 100644 --- a/usr.sbin/lpr/pac/pac.c +++ b/usr.sbin/lpr/pac/pac.c @@ -71,6 +71,8 @@ static int sort; /* Sort by cost */ static char *sumfile; /* summary file */ static int summarize; /* Compress accounting file */ +uid_t uid, euid; + /* * Grossness follows: * Names to be accumulated are hashed into the following @@ -106,6 +108,8 @@ main(argc, argv) register FILE *acct; register char *cp; + euid = geteuid(); /* these aren't used in pac(1) */ + uid = getuid(); while (--argc) { cp = *++argv; if (*cp++ == '-') { |