From owner-freebsd-current Thu Dec 23 15:45: 8 1999 Delivered-To: freebsd-current@freebsd.org Received: from mail.rpi.edu (mail.rpi.edu [128.113.100.7]) by hub.freebsd.org (Postfix) with ESMTP id 72F1614C28 for ; Thu, 23 Dec 1999 15:45:05 -0800 (PST) (envelope-from drosih@rpi.edu) Received: from [128.113.24.47] (gilead.acs.rpi.edu [128.113.24.47]) by mail.rpi.edu (8.9.3/8.9.3) with ESMTP id SAA21322; Thu, 23 Dec 1999 18:44:51 -0500 Mime-Version: 1.0 X-Sender: drosih@mail.rpi.edu Message-Id: In-Reply-To: References: Date: Thu, 23 Dec 1999 18:44:57 -0500 To: Alfred Perlstein , Andre Albsmeier From: Garance A Drosihn Subject: Re: NO! Re: [PATCHES] Two fixes for lpd/lpc for review and test Cc: Warner Losh , current@FreeBSD.ORG Content-Type: text/plain; charset="us-ascii" ; format="flowed" Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG At 2:33 AM -0800 12/10/99, Alfred Perlstein wrote: >Can someone take a look at this? > >Basically, it makes the link to the file, if it can unlink the original >it will then chown the spool file if it can't delete or read the original >then the user didn't have permission and it backs out. Okay, I've finally gotten back to this and come up with an alternate version, which I think should be pretty safe. It includes some checks which are probably redundant for freebsd, but which would be necessary on some other platforms I use this on. It's basically Alfred's code, with a few more checks for symlinks and to make sure race conditions can't trick us. If no problems are found with this, I'll submit it as a PR follow-on to #bin/11997 Pardon the difference in version-numbering, I probably don't have CVS setup exactly right for version numbers to match freebsd's... Index: lpr.c =================================================================== RCS file: /Users/cvsdepot/lpr-fbsd/lpr/lpr.c,v retrieving revision 1.1.1.1 diff -U5 -r1.1.1.1 lpr.c --- lpr.c 1999/11/30 16:15:22 1.1.1.1 +++ lpr.c 1999/12/23 23:31:43 @@ -382,10 +382,65 @@ nact++; continue; } if (sflag) printf("%s: %s: not linked, copying instead\n", name, arg); + + if (f) { + /* + * The user wants the file removed after it is copied, + * so see if it can be mv'ed instead of copy/unlink'ed. + * This will be much faster and better than copying the + * file, especially for larger files. Can be very + * useful for services like samba, pcnfs, CAP, et al. + */ + int ret, didlink; + struct stat statb2; + seteuid(euid); + didlink = 0; + /* don't do this if the user's file is a symlink */ + if (lstat(arg, &statb) < 0) goto nohardlink; + if (S_ISLNK(statb.st_mode)) goto nohardlink; + /* if the attempt to link fails, abandon the move */ + if (link(arg, dfname) != 0) goto nohardlink; + didlink = 1; + /* make sure the user hasn't tried to trick us via + * any race conditions */ + if (lstat(dfname, &statb2) < 0) goto nohardlink; + if (statb.st_dev != statb2.st_dev) goto nohardlink; + if (statb.st_ino != statb2.st_ino) goto nohardlink; + + /* if we can access and remove the given file without + * special setuid-ness then this method is safe. */ + seteuid(uid); + ret = access(dfname, R_OK); + if (ret == 0) + ret = unlink(arg); + seteuid(euid); + /* the user does not have access to read or remove + * this file, so abandon the move and fall back to + * the usual (copy) methods. */ + if (ret != 0) goto nohardlink; + + /* unlink of user file was successful. fixup perms, + * add entries to control file, and skip copy step */ + chown(dfname, userid, getegid()); + chmod(dfname, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + seteuid(uid); + if (format == 'p') + card('T', title ? title : arg); + for (i = 0; i < ncopies; i++) + card(format, &dfname[inchar-2]); + card('U', &dfname[inchar-2]); + card('N', arg); + nact++; + continue; +nohardlink: + if (didlink) unlink(dfname); + seteuid(uid); /* restore old uid */ + } /* end: if (f) */ + if ((i = open(arg, O_RDONLY)) < 0) { printf("%s: cannot open %s\n", name, arg); } else { copy(pp, i, arg); (void) close(i); =================================================================== --- Garance Alistair Drosehn = gad@eclipse.acs.rpi.edu Senior Systems Programmer or drosih@rpi.edu Rensselaer Polytechnic Institute To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message