Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 23 Dec 1999 18:44:57 -0500
From:      Garance A Drosihn <drosih@rpi.edu>
To:        Alfred Perlstein <bright@wintelcom.net>, Andre Albsmeier <andre.albsmeier@mchp.siemens.de>
Cc:        Warner Losh <imp@village.org>, current@FreeBSD.ORG
Subject:   Re: NO! Re: [PATCHES] Two fixes for lpd/lpc for review and test
Message-ID:  <v0421010cb488621c20e1@[128.113.24.47]>
In-Reply-To: <Pine.BSF.4.21.9912100211050.4557-100000@fw.wintelcom.net>
References:  <Pine.BSF.4.21.9912100211050.4557-100000@fw.wintelcom.net>

next in thread | previous in thread | raw e-mail | index | archive | help
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




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?v0421010cb488621c20e1>