From mboxrd@z Thu Jan  1 00:00:00 1970
Received: from pigeon.gentoo.org ([208.92.234.80] helo=lists.gentoo.org)
	by finch.gentoo.org with esmtp (Exim 4.60)
	(envelope-from <gentoo-embedded+bounces-3352-garchives=archives.gentoo.org@lists.gentoo.org>)
	id 1NhPv8-0004Jf-Kl
	for garchives@archives.gentoo.org; Tue, 16 Feb 2010 16:05:07 +0000
Received: from pigeon.gentoo.org (localhost [127.0.0.1])
	by pigeon.gentoo.org (Postfix) with SMTP id 5372BE0A6A
	for <garchives@archives.gentoo.org>; Tue, 16 Feb 2010 16:05:06 +0000 (UTC)
Received: from vms173005pub.verizon.net (vms173005pub.verizon.net [206.46.173.5])
	by pigeon.gentoo.org (Postfix) with ESMTP id AFA4AE0869
	for <gentoo-embedded@lists.gentoo.org>; Tue, 16 Feb 2010 15:20:57 +0000 (UTC)
Precedence: bulk
List-Post: <mailto:gentoo-embedded@lists.gentoo.org>
List-Help: <mailto:gentoo-embedded+help@lists.gentoo.org>
List-Unsubscribe: <mailto:gentoo-embedded+unsubscribe@lists.gentoo.org>
List-Subscribe: <mailto:gentoo-embedded+subscribe@lists.gentoo.org>
List-Id: Gentoo Linux mail <gentoo-embedded.gentoo.org>
X-BeenThere: gentoo-embedded@lists.gentoo.org
Reply-to: gentoo-embedded@lists.gentoo.org
MIME-version: 1.0
Content-type: multipart/mixed; boundary="Boundary_(ID_4pxH5Gb8qSEhwHZXfZkhWA)"
Received: from [192.168.0.7] ([unknown] [173.63.22.246])
 by vms173005.mailsrvcs.net
 (Sun Java(tm) System Messaging Server 7u2-7.02 32bit (built Apr 16 2009))
 with ESMTPA id <0KXX005SRXALZ7C5@vms173005.mailsrvcs.net> for
 gentoo-embedded@lists.gentoo.org; Tue, 16 Feb 2010 09:20:47 -0600 (CST)
Message-id: <4B7AB7CC.7090302@verizon.net>
Date: Tue, 16 Feb 2010 10:20:44 -0500
From: "P. Levine" <plevine457@verizon.net>
User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.7)
 Gecko/20100206 Lightning/1.0b2pre Thunderbird/3.0.1
To: gentoo-embedded@lists.gentoo.org
Subject: Re: [gentoo-embedded] emerge --root : users not created
X-Enigmail-Version: 1.0
X-Archives-Salt: 06cdd058-4b87-4cfa-be4c-e13866f668e5
X-Archives-Hash: 66347246ac16e214069813c3c29129f9

This is a multi-part message in MIME format.

--Boundary_(ID_4pxH5Gb8qSEhwHZXfZkhWA)
Content-type: text/plain; CHARSET=US-ASCII
Content-transfer-encoding: 7BIT

On 02/16/2010 10:04 AM, P. Levine wrote:
> Peter Stuge wrote:
>> I talked to upstream on freenode/#shadow and they welcome a patch for
>> adding --chroot
>>
>> chroot() needs to happen really early since useradd and friends read
>> some configuration files to know e.g. which password encryption
>> method to use.
> 
> Attached is a tentative patch to add a chroot flag to useradd and
> groupadd (via --chroot or -R).  It compiles and works on my end
> (--chroot /usr/armv4tl-softfloat-linux-gnueabi) with various other flags
> enabled.  I'm hoping for others to test it and get some feedback before
> I submit it to shadow upstream.
> 
> There do exist a couple of issues:
> 
> sysconf(_SC_NGROUPS_MAX) is called by useradd early on.  This would
> report the maximum allowable number of groups per user on the build
> system, not the target.  To my knowledge, this is set by the kernel and
> would have to be used.  However, this tends to be a very high number for
> linux kernel >= 2.6.3 (65536) so it seems like a mute point (for linux
> kernel >= 2.6.3).
> 
> There are a number of calls to "getXXbyYY" functions (i.e., getgrgid,
> getpwnam, etc...).  These seem to be dynamically preloaded and access
> preloaded databases.  They are unaffected by chroot() (even after
> setting __nss_configure_lookup(foo, files)).  I've instead used shadow's
> own method of macro expansion to generate functions doing the
> equivalent, with recursive calls to fgetXXent functions.
> 
> And PAM functionality doesn't work and has to be disabled while using
> chroot().  I don't know very much about PAM.  Would this be a problem?
> 
> Also,  the chroot functionality could probably be easily extended to
> other modules but I'm not sure if this would be acceptable upstream.
> 
> There are a couple of cosmetic changes I'm considering as well (such as
> how --chroot flag is parsed).
> 
> -- Peter Levine

Sorry, wrong patch.

I've attached the correct one.

-- Peter Levine


--Boundary_(ID_4pxH5Gb8qSEhwHZXfZkhWA)
Content-type: text/x-patch; name=shadow-4.1.4.2-chroot.patch
Content-disposition: attachment; filename=shadow-4.1.4.2-chroot.patch
Content-Transfer-Encoding: quoted-printable

diff -Naur shadow-4.1.4.2.old/config.h.in shadow-4.1.4.2/config.h.in
--- shadow-4.1.4.2.old/config.h.in	2009-07-23 21:15:58.000000000 -0400
+++ shadow-4.1.4.2/config.h.in	2010-02-16 07:19:48.000000000 -0500
@@ -68,6 +68,12 @@
 /* Define to 1 if you have the <fcntl.h> header file. */
 #undef HAVE_FCNTL_H
=20
+/* Define to 1 if you have the `fgetgrent_r' function. */
+#undef HAVE_FGETGRENT_R
+
+/* Define to 1 if you have the `fgetpwent_r' function. */
+#undef HAVE_FGETPWENT_R
+
 /* Define to 1 if you have the `fsync' function. */
 #undef HAVE_FSYNC
=20
diff -Naur shadow-4.1.4.2.old/configure shadow-4.1.4.2/configure
--- shadow-4.1.4.2.old/configure	2009-07-23 21:15:56.000000000 -0400
+++ shadow-4.1.4.2/configure	2010-02-16 07:19:48.000000000 -0500
@@ -13536,7 +13536,8 @@
 for ac_func in l64a fchmod fchown fsync futimes getgroups gethostname ge=
tspnam \
 	gettimeofday getusershell getutent initgroups lchown lckpwdf lstat \
 	lutimes memcpy memset setgroups sigaction strchr updwtmp updwtmpx innet=
gr \
-	getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r getaddrinfo
+	fgetpwent_r fgetgrent_r getpwnam_r getpwuid_r getgrnam_r getgrgid_r \
+	getspnam_r getaddrinfo
 do
 as_ac_var=3D`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 { $as_echo "$as_me:$LINENO: checking for $ac_func" >&5
diff -Naur shadow-4.1.4.2.old/configure.in shadow-4.1.4.2/configure.in
--- shadow-4.1.4.2.old/configure.in	2009-07-23 21:10:31.000000000 -0400
+++ shadow-4.1.4.2/configure.in	2010-02-16 07:19:48.000000000 -0500
@@ -41,7 +41,8 @@
 AC_CHECK_FUNCS(l64a fchmod fchown fsync futimes getgroups gethostname ge=
tspnam \
 	gettimeofday getusershell getutent initgroups lchown lckpwdf lstat \
 	lutimes memcpy memset setgroups sigaction strchr updwtmp updwtmpx innet=
gr \
-	getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r getaddrinfo)
+	fgetpwent_r fgetgrent_r getpwnam_r getpwuid_r getgrnam_r getgrgid_r \
+	getspnam_r getaddrinfo)
 AC_SYS_LARGEFILE
=20
 dnl Checks for typedefs, structures, and compiler characteristics.
diff -Naur shadow-4.1.4.2.old/lib/prototypes.h shadow-4.1.4.2/lib/prototy=
pes.h
--- shadow-4.1.4.2.old/lib/prototypes.h	2009-05-18 14:32:21.000000000 -04=
00
+++ shadow-4.1.4.2/lib/prototypes.h	2010-02-16 07:19:48.000000000 -0500
@@ -154,6 +154,7 @@
=20
 /* getgr_nam_gid.c */
 extern /*@null@*/struct group *getgr_nam_gid (const char *grname);
+extern /*@null@*/struct group *fgetgr_nam_gid (const char *grname);
=20
 /* getlong.c */
 extern int getlong (const char *numstr, /*@out@*/long int *result);
@@ -400,6 +401,15 @@
 /* xgetspnam.c */
 extern /*@null@*/ /*@only@*/struct spwd *xgetspnam(const char *);
=20
+/* xfgetpwnam.c */
+extern /*@null@*/ /*@only@*/struct passwd *xfgetpwnam (const char *);
+/* xfgetpwuid.c */
+extern /*@null@*/ /*@only@*/struct passwd *xfgetpwuid (uid_t);
+/* xfgetgrnam.c */
+extern /*@null@*/ /*@only@*/struct group *xfgetgrnam (const char *);
+/* xfgetgrgid.c */
+extern /*@null@*/ /*@only@*/struct group *xfgetgrgid (gid_t);
+
 /* yesno.c */
 extern bool yes_or_no (bool read_only);
=20
diff -Naur shadow-4.1.4.2.old/libmisc/Makefile.am shadow-4.1.4.2/libmisc/=
Makefile.am
--- shadow-4.1.4.2.old/libmisc/Makefile.am	2009-05-17 14:39:06.000000000 =
-0400
+++ shadow-4.1.4.2/libmisc/Makefile.am	2010-02-16 07:19:48.000000000 -050=
0
@@ -1,5 +1,5 @@
=20
-EXTRA_DIST =3D .indent.pro xgetXXbyYY.c
+EXTRA_DIST =3D .indent.pro xgetXXbyYY.c xfgetXXbyYY.c
=20
 INCLUDES =3D -I$(top_srcdir)/lib
=20
@@ -59,6 +59,10 @@
 	user_busy.c \
 	utmp.c \
 	valid.c \
+	xfgetpwnam.c \
+	xfgetpwuid.c \
+	xfgetgrnam.c \
+	xfgetgrgid.c \
 	xgetpwnam.c \
 	xgetpwuid.c \
 	xgetgrnam.c \
diff -Naur shadow-4.1.4.2.old/libmisc/Makefile.in shadow-4.1.4.2/libmisc/=
Makefile.in
--- shadow-4.1.4.2.old/libmisc/Makefile.in	2009-07-23 21:15:59.000000000 =
-0400
+++ shadow-4.1.4.2/libmisc/Makefile.in	2010-02-16 07:19:48.000000000 -050=
0
@@ -64,9 +64,10 @@
 	shell.$(OBJEXT) system.$(OBJEXT) strtoday.$(OBJEXT) \
 	sub.$(OBJEXT) sulog.$(OBJEXT) ttytype.$(OBJEXT) tz.$(OBJEXT) \
 	ulimit.$(OBJEXT) user_busy.$(OBJEXT) utmp.$(OBJEXT) \
-	valid.$(OBJEXT) xgetpwnam.$(OBJEXT) xgetpwuid.$(OBJEXT) \
-	xgetgrnam.$(OBJEXT) xgetgrgid.$(OBJEXT) xgetspnam.$(OBJEXT) \
-	xmalloc.$(OBJEXT) yesno.$(OBJEXT)
+	valid.$(OBJEXT) xfgetpwnam.$(OBJEXT) xfgetpwuid.$(OBJEXT) \
+	xfgetgrnam.$(OBJEXT) xfgetgrgid.$(OBJEXT) xgetpwnam.$(OBJEXT) \
+	xgetpwuid.$(OBJEXT) xgetgrnam.$(OBJEXT) xgetgrgid.$(OBJEXT) \
+	xgetspnam.$(OBJEXT) xmalloc.$(OBJEXT) yesno.$(OBJEXT)
 libmisc_a_OBJECTS =3D $(am_libmisc_a_OBJECTS)
 DEFAULT_INCLUDES =3D -I.@am__isrc@ -I$(top_builddir)
 depcomp =3D $(SHELL) $(top_srcdir)/depcomp
@@ -232,7 +233,7 @@
 top_build_prefix =3D @top_build_prefix@
 top_builddir =3D @top_builddir@
 top_srcdir =3D @top_srcdir@
-EXTRA_DIST =3D .indent.pro xgetXXbyYY.c
+EXTRA_DIST =3D .indent.pro xgetXXbyYY.c xfgetXXbyYY.c
 INCLUDES =3D -I$(top_srcdir)/lib
 noinst_LIBRARIES =3D libmisc.a
 libmisc_a_SOURCES =3D \
@@ -289,6 +290,10 @@
 	user_busy.c \
 	utmp.c \
 	valid.c \
+	xfgetpwnam.c \
+	xfgetpwuid.c \
+	xfgetgrnam.c \
+	xfgetgrgid.c \
 	xgetpwnam.c \
 	xgetpwuid.c \
 	xgetgrnam.c \
@@ -395,6 +400,10 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/user_busy.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utmp.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/valid.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xfgetgrgid.Po@am__quote=
@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xfgetgrnam.Po@am__quote=
@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xfgetpwnam.Po@am__quote=
@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xfgetpwuid.Po@am__quote=
@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xgetgrgid.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xgetgrnam.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xgetpwnam.Po@am__quote@
diff -Naur shadow-4.1.4.2.old/libmisc/getgr_nam_gid.c shadow-4.1.4.2/libm=
isc/getgr_nam_gid.c
--- shadow-4.1.4.2.old/libmisc/getgr_nam_gid.c	2009-04-29 09:50:14.000000=
000 -0400
+++ shadow-4.1.4.2/libmisc/getgr_nam_gid.c	2010-02-16 07:19:48.000000000 =
-0500
@@ -64,3 +64,29 @@
 	return xgetgrnam (grname);
 }
=20
+/*
+ * fgetgr_nam_gid - Return a pointer to the group specified by a string
+ * using recursive calls to fgetgrent.
+ * The string may be a valid GID or a valid groupname.
+ * If the group does not exist on the system, NULL is returned.
+ */
+extern /*@null@*/struct group *fgetgr_nam_gid (const char *grname)
+{
+	long long int gid;
+	char *endptr;
+
+	if (NULL =3D=3D grname) {
+		return NULL;
+	}
+
+	errno =3D 0;
+	gid =3D strtoll (grname, &endptr, 10);
+	if (   ('\0' !=3D *grname)
+	    && ('\0' =3D=3D *endptr)
+	    && (ERANGE !=3D errno)
+	    && (/*@+longintegral@*/gid =3D=3D (gid_t)gid)/*@=3Dlongintegral@*/)=
 {
+		return xfgetgrgid ((gid_t) gid);
+	}
+	return xfgetgrnam (grname);
+}
+
diff -Naur shadow-4.1.4.2.old/libmisc/xfgetXXbyYY.c shadow-4.1.4.2/libmis=
c/xfgetXXbyYY.c
--- shadow-4.1.4.2.old/libmisc/xfgetXXbyYY.c	1969-12-31 19:00:00.00000000=
0 -0500
+++ shadow-4.1.4.2/libmisc/xfgetXXbyYY.c	2010-02-16 07:19:48.000000000 -0=
500
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2007 - 2009, Nicolas Fran=C3=A7ois
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in th=
e
+ *    documentation and/or other materials provided with the distributio=
n.
+ * 3. The name of the copyright holders or contributors may not be used =
to
+ *    endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR=
 A
+ * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTA=
L,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * According to the Linux-PAM documentation:
+ *
+ *  4.1.=C2=A0Care about standard library calls
+ *
+ *  In general, writers of authorization-granting applications should
+ *  assume that each module is likely to call any or all 'libc' function=
s.
+ *  For 'libc' functions that return pointers to static/dynamically
+ *  allocated structures (ie.  the library allocates the memory and the
+ *  user is not expected to 'free()' it) any module call to this functio=
n
+ *  is likely to corrupt a pointer previously obtained by the applicatio=
n.
+ *  The application programmer should either re-call such a 'libc'
+ *  function after a call to the Linux-PAM library, or copy the structur=
e
+ *  contents to some safe area of memory before passing control to the
+ *  Linux-PAM library.
+ *
+ *  Two important function classes that fall into this category are
+ *  getpwnam(3) and syslog(3).
+ *
+ * This file provide wrapper to the getpwnam or getpwnam_r functions.
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include "prototypes.h"
+
+#define F_FUNCTION_NAME	F_FUNCTION_NAME1 (DB_TYPE)
+#define F_FUNCTION_NAME1(name) F_FUNCTION_NAME2 (name)
+#define F_FUNCTION_NAME2(name) fget##name##ent
+#define F_COMPARE F_COMPARE1 (DB_TYPE,ARG_NAME)
+#define F_COMPARE1(name1,name2) F_COMPARE2 (name1,name2)
+#define F_COMPARE2(name1,name2) F_COMPARE3 (name1 ## _ ## name2,name2)
+#define F_COMPARE3(name1,name2) F_COMPARE_## name2 (result->name1,name2)
+#define F_COMPARE_gid	F_COMPARE_num
+#define F_COMPARE_uid	F_COMPARE_num
+#define F_COMPARE_namp	F_COMPARE_str
+#define F_COMPARE_name	F_COMPARE_str
+#define F_COMPARE_num(name1,name2)	(name1 =3D=3D name2)
+#define F_COMPARE_str(name1,name2)	(!strcmp(name1,name2))
+
+#define XFUNCTION_NAME XPREFIX (FUNCTION_NAME)
+#define XPREFIX(name) XPREFIX1 (name)
+#define XPREFIX1(name) x##name
+#define REENTRANT_NAME APPEND_R (F_FUNCTION_NAME)
+#define APPEND_R(name) APPEND_R1 (name)
+#define APPEND_R1(name) name##_r
+#define STRINGIZE(name) STRINGIZE1 (name)
+#define STRINGIZE1(name) #name
+
+/*@null@*/ /*@only@*/LOOKUP_TYPE *XFUNCTION_NAME (ARG_TYPE ARG_NAME)
+{
+	FILE *stream =3D NULL;
+	if ((stream =3D fopen (DB_FILE, "r")) =3D=3D NULL) {
+		fprintf (stderr, _("%s: Error opening the database file.\n"),
+		         "x" STRINGIZE(FUNCTION_NAME));
+		exit (1);
+	}
+#if HAVE_FUNCTION_R
+	LOOKUP_TYPE *result=3DNULL;
+	char *buffer=3DNULL;
+	/* we have to start with something */
+	size_t length =3D 0x100;
+
+	result =3D malloc(sizeof(LOOKUP_TYPE));
+	if (NULL =3D=3D result) {
+		fprintf (stderr, _("%s: out of memory\n"),
+		         "x" STRINGIZE(FUNCTION_NAME));
+		exit (13);
+	}
+
+	while (true) {
+		int status;
+		LOOKUP_TYPE *resbuf =3D NULL;
+		buffer =3D (char *)realloc (buffer, length);
+		if (NULL =3D=3D buffer) {
+			fprintf (stderr, _("%s: out of memory\n"),
+			         "x" STRINGIZE(FUNCTION_NAME));
+			exit (13);
+		}
+		errno =3D 0;
+		status =3D REENTRANT_NAME(stream, result, buffer,
+	                        length, &resbuf);
+		while ((0 =3D=3Dstatus) && (resbuf =3D=3D result)) {
+			if (F_COMPARE) {
+				/* Build a result structure that can be freed by
+				 * the shadow *_free functions. */
+				LOOKUP_TYPE *ret_result =3D DUP_FUNCTION(result);
+				(void) fclose (stream);
+				free(buffer);
+				free(result);
+				return ret_result;
+			} else {
+				status =3D REENTRANT_NAME(stream, result, buffer,
+		                	        length, &resbuf);
+			}
+		}
+
+		if (ERANGE !=3D errno) {
+			(void) fclose (stream);
+			free (buffer);
+			free (result);
+			return NULL;
+		}
+
+		if (length <=3D ((size_t)-1 / 4)) {
+			length *=3D 4;
+		} else if (length =3D=3D (size_t) -1) {
+			break;
+		} else {
+			length =3D (size_t) -1;
+		}
+	}
+
+	(void) fclose (stream);
+	free(buffer);
+	free(result);
+	return NULL;
+
+#else /* !HAVE_FUNCTION_R */
+
+	/* No reentrant function.
+	 * Duplicate the structure to avoid other call to overwrite it.
+	 *
+	 * We should also restore the initial structure. But that would be
+	 * overkill.
+	 */
+	LOOKUP_TYPE *result =3D F_FUNCTION_NAME(stream);
+
+	while (result) {
+		if (F_COMPARE) {
+			result =3D DUP_FUNCTION(result);
+			if (NULL =3D=3D result) {
+				fprintf (stderr, _("%s: out of memory\n"),
+				         "x" STRINGIZE(FUNCTION_NAME));
+				exit (13);
+			}
+			break;
+		} else {
+			result =3D F_FUNCTION_NAME(stream);
+		}
+	}
+
+	(void) fclose (stream);
+	return result;
+#endif
+}
+
diff -Naur shadow-4.1.4.2.old/libmisc/xfgetgrgid.c shadow-4.1.4.2/libmisc=
/xfgetgrgid.c
--- shadow-4.1.4.2.old/libmisc/xfgetgrgid.c	1969-12-31 19:00:00.000000000=
 -0500
+++ shadow-4.1.4.2/libmisc/xfgetgrgid.c	2010-02-16 07:19:48.000000000 -05=
00
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2007 - 2009, Nicolas Fran=C3=A7ois
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in th=
e
+ *    documentation and/or other materials provided with the distributio=
n.
+ * 3. The name of the copyright holders or contributors may not be used =
to
+ *    endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR=
 A
+ * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTA=
L,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * According to the Linux-PAM documentation:
+ *
+ *  4.1.=C2=A0Care about standard library calls
+ *
+ *  In general, writers of authorization-granting applications should
+ *  assume that each module is likely to call any or all 'libc' function=
s.
+ *  For 'libc' functions that return pointers to static/dynamically
+ *  allocated structures (ie.  the library allocates the memory and the
+ *  user is not expected to 'free()' it) any module call to this functio=
n
+ *  is likely to corrupt a pointer previously obtained by the applicatio=
n.
+ *  The application programmer should either re-call such a 'libc'
+ *  function after a call to the Linux-PAM library, or copy the structur=
e
+ *  contents to some safe area of memory before passing control to the
+ *  Linux-PAM library.
+ *
+ *  Two important function classes that fall into this category are
+ *  getpwnam(3) and syslog(3).
+ *
+ * This file provide wrapper to the getpwnam or getpwnam_r functions.
+ */
+
+#include <config.h>
+
+#include "groupio.h"
+
+#define LOOKUP_TYPE	struct group
+#define FUNCTION_NAME	fgetgrgid
+#define ARG_TYPE	gid_t
+#define ARG_NAME	gid
+#define DB_TYPE	gr
+#define DB_FILE GROUP_FILE
+#define DUP_FUNCTION	__gr_dup
+#define HAVE_FUNCTION_R (defined HAVE_FGETGRENT_R)
+
+#include "xfgetXXbyYY.c"
+
diff -Naur shadow-4.1.4.2.old/libmisc/xfgetgrnam.c shadow-4.1.4.2/libmisc=
/xfgetgrnam.c
--- shadow-4.1.4.2.old/libmisc/xfgetgrnam.c	1969-12-31 19:00:00.000000000=
 -0500
+++ shadow-4.1.4.2/libmisc/xfgetgrnam.c	2010-02-16 07:19:48.000000000 -05=
00
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2007 - 2009, Nicolas Fran=C3=A7ois
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in th=
e
+ *    documentation and/or other materials provided with the distributio=
n.
+ * 3. The name of the copyright holders or contributors may not be used =
to
+ *    endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR=
 A
+ * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTA=
L,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * According to the Linux-PAM documentation:
+ *
+ *  4.1.=C2=A0Care about standard library calls
+ *
+ *  In general, writers of authorization-granting applications should
+ *  assume that each module is likely to call any or all 'libc' function=
s.
+ *  For 'libc' functions that return pointers to static/dynamically
+ *  allocated structures (ie.  the library allocates the memory and the
+ *  user is not expected to 'free()' it) any module call to this functio=
n
+ *  is likely to corrupt a pointer previously obtained by the applicatio=
n.
+ *  The application programmer should either re-call such a 'libc'
+ *  function after a call to the Linux-PAM library, or copy the structur=
e
+ *  contents to some safe area of memory before passing control to the
+ *  Linux-PAM library.
+ *
+ *  Two important function classes that fall into this category are
+ *  getpwnam(3) and syslog(3).
+ *
+ * This file provide wrapper to the getpwnam or getpwnam_r functions.
+ */
+
+#include <config.h>
+
+#include "groupio.h"
+
+#define LOOKUP_TYPE	struct group
+#define FUNCTION_NAME	fgetgrnam
+#define ARG_TYPE	const char *
+#define ARG_NAME	name
+#define DB_TYPE	gr
+#define DB_FILE	GROUP_FILE
+#define DUP_FUNCTION	__gr_dup
+#define HAVE_FUNCTION_R (defined HAVE_FGETGRENT_R)
+
+#include "xfgetXXbyYY.c"
+
diff -Naur shadow-4.1.4.2.old/libmisc/xfgetpwnam.c shadow-4.1.4.2/libmisc=
/xfgetpwnam.c
--- shadow-4.1.4.2.old/libmisc/xfgetpwnam.c	1969-12-31 19:00:00.000000000=
 -0500
+++ shadow-4.1.4.2/libmisc/xfgetpwnam.c	2010-02-16 07:19:48.000000000 -05=
00
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2007 - 2009, Nicolas Fran=C3=A7ois
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in th=
e
+ *    documentation and/or other materials provided with the distributio=
n.
+ * 3. The name of the copyright holders or contributors may not be used =
to
+ *    endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR=
 A
+ * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTA=
L,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * According to the Linux-PAM documentation:
+ *
+ *  4.1.=C2=A0Care about standard library calls
+ *
+ *  In general, writers of authorization-granting applications should
+ *  assume that each module is likely to call any or all 'libc' function=
s.
+ *  For 'libc' functions that return pointers to static/dynamically
+ *  allocated structures (ie.  the library allocates the memory and the
+ *  user is not expected to 'free()' it) any module call to this functio=
n
+ *  is likely to corrupt a pointer previously obtained by the applicatio=
n.
+ *  The application programmer should either re-call such a 'libc'
+ *  function after a call to the Linux-PAM library, or copy the structur=
e
+ *  contents to some safe area of memory before passing control to the
+ *  Linux-PAM library.
+ *
+ *  Two important function classes that fall into this category are
+ *  getpwnam(3) and syslog(3).
+ *
+ * This file provide wrapper to the getpwnam or getpwnam_r functions.
+ */
+
+#include <config.h>
+
+#include "pwio.h"
+
+#define LOOKUP_TYPE	struct passwd
+#define FUNCTION_NAME	fgetpwnam
+#define ARG_TYPE	const char *
+#define ARG_NAME	name
+#define DB_TYPE	pw
+#define DB_FILE PASSWD_FILE
+#define DUP_FUNCTION	__pw_dup
+#define HAVE_FUNCTION_R (defined HAVE_FGETPWENT_R)
+
+#include "xfgetXXbyYY.c"
+
diff -Naur shadow-4.1.4.2.old/libmisc/xfgetpwuid.c shadow-4.1.4.2/libmisc=
/xfgetpwuid.c
--- shadow-4.1.4.2.old/libmisc/xfgetpwuid.c	1969-12-31 19:00:00.000000000=
 -0500
+++ shadow-4.1.4.2/libmisc/xfgetpwuid.c	2010-02-16 07:19:48.000000000 -05=
00
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2007 - 2009, Nicolas Fran=C3=A7ois
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in th=
e
+ *    documentation and/or other materials provided with the distributio=
n.
+ * 3. The name of the copyright holders or contributors may not be used =
to
+ *    endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR=
 A
+ * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTA=
L,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * According to the Linux-PAM documentation:
+ *
+ *  4.1.=C2=A0Care about standard library calls
+ *
+ *  In general, writers of authorization-granting applications should
+ *  assume that each module is likely to call any or all 'libc' function=
s.
+ *  For 'libc' functions that return pointers to static/dynamically
+ *  allocated structures (ie.  the library allocates the memory and the
+ *  user is not expected to 'free()' it) any module call to this functio=
n
+ *  is likely to corrupt a pointer previously obtained by the applicatio=
n.
+ *  The application programmer should either re-call such a 'libc'
+ *  function after a call to the Linux-PAM library, or copy the structur=
e
+ *  contents to some safe area of memory before passing control to the
+ *  Linux-PAM library.
+ *
+ *  Two important function classes that fall into this category are
+ *  getpwnam(3) and syslog(3).
+ *
+ * This file provide wrapper to the getpwnam or getpwnam_r functions.
+ */
+
+#include <config.h>
+
+#include "pwio.h"
+
+#define LOOKUP_TYPE	struct passwd
+#define FUNCTION_NAME	fgetpwuid
+#define ARG_TYPE	uid_t
+#define ARG_NAME	uid
+#define DB_TYPE	pw
+#define DB_FILE PASSWD_FILE
+#define DUP_FUNCTION	__pw_dup
+#define HAVE_FUNCTION_R (defined HAVE_FGETPWENT_R)
+
+#include "xfgetXXbyYY.c"
+
diff -Naur shadow-4.1.4.2.old/man/groupadd.8 shadow-4.1.4.2/man/groupadd.=
8
--- shadow-4.1.4.2.old/man/groupadd.8	2009-07-23 21:16:24.000000000 -0400
+++ shadow-4.1.4.2/man/groupadd.8	2010-02-16 07:19:48.000000000 -0500
@@ -99,6 +99,18 @@
 login\&.defs, instead of
 \fBGID_MIN\fR\-\fBGID_MAX\fR\&.
 .RE
+.PP
+\fB\-R\fR, \fB\-\-chroot\fR \fIROOT_DIR\fR
+.RS 4
+Access files from a root directory other than /\&.
+.sp
+Instead of accessing or altering files from the usual directory, paths w=
ill be prefixed with
+\fBROOT_DIR\fR\&.
+.sp
+For instance, instead of adding a group to
+/etc/group, the group would be added to
+\fBROOT_DIR\fR/etc/group\&.
+.RE
 .SH "CONFIGURATION"
 .PP
 The following configuration variables in
diff -Naur shadow-4.1.4.2.old/man/groupadd.8.xml shadow-4.1.4.2/man/group=
add.8.xml
--- shadow-4.1.4.2.old/man/groupadd.8.xml	2009-05-21 08:02:13.000000000 -=
0400
+++ shadow-4.1.4.2/man/groupadd.8.xml	2010-02-16 07:19:48.000000000 -0500
@@ -179,6 +179,26 @@
 	  </para>
 	</listitem>
       </varlistentry>
+      <varlistentry>
+	<term>
+	  <option>-R</option>, <option>--chroot</option>
+	  <replaceable>ROOT_DIR</replaceable>
+	</term>
+	<listitem>
+	  <para>
+	    Access files from a root directory other than /.
+	  </para>
+	  <para>
+	    Instead of accessing or altering files from the usual directory,
+	    paths will be prefixed with <option>ROOT_DIR</option>.
+	  </para>
+	  <para>
+	    For instance, instead of adding a group to
+	    <filename>/etc/group</filename>, the group would be added to
+	    <filename><option>ROOT_DIR</option>/etc/group</filename>.
+	  </para>
+	</listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
=20
diff -Naur shadow-4.1.4.2.old/man/useradd.8 shadow-4.1.4.2/man/useradd.8
--- shadow-4.1.4.2.old/man/useradd.8	2009-07-23 21:16:44.000000000 -0400
+++ shadow-4.1.4.2/man/useradd.8	2010-02-16 07:19:48.000000000 -0500
@@ -285,6 +285,18 @@
 options if you want a home directory for a system account to be created\=
&.
 .RE
 .PP
+\fB\-R\fR, \fB\-\-chroot\fR \fIROOT_DIR\fR
+.RS 4
+Access files from a root directory other than /\&.
+.sp
+Instead of accessing or altering files from the usual directory, paths w=
ill be prefixed with
+\fBROOT_DIR\fR\&.
+.sp
+For instance, instead of adding a user to
+/etc/passwd, the user would be added to
+\fBROOT_DIR\fR/etc/passwd\&.
+.RE
+.PP
 \fB\-s\fR, \fB\-\-shell\fR \fISHELL\fR
 .RS 4
 The name of the user\'s login shell\&. The default is to leave this fiel=
d blank, which causes the system to select the default login shell specif=
ied by the
diff -Naur shadow-4.1.4.2.old/man/useradd.8.xml shadow-4.1.4.2/man/userad=
d.8.xml
--- shadow-4.1.4.2.old/man/useradd.8.xml	2009-05-21 08:02:13.000000000 -0=
400
+++ shadow-4.1.4.2/man/useradd.8.xml	2010-02-16 07:19:48.000000000 -0500
@@ -425,6 +425,26 @@
       </varlistentry>
       <varlistentry>
 	<term>
+	  <option>-R</option>, <option>--chroot</option>
+	  <replaceable>ROOT_DIR</replaceable>
+	</term>
+	<listitem>
+	  <para>
+	    Access files from a root directory other than /.
+	  </para>
+	  <para>
+	    Instead of accessing or altering files from the usual directory,
+	    paths will be prefixed with <option>ROOT_DIR</option>.
+	  </para>
+	  <para>
+	    For instance, instead of adding a user to
+	    <filename>/etc/passwd</filename>, the user would be added to
+	    <filename><option>ROOT_DIR</option>/etc/passwd</filename>.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term>
 	  <option>-s</option>, <option>--shell</option>
 	  <replaceable>SHELL</replaceable>
 	</term>
diff -Naur shadow-4.1.4.2.old/src/groupadd.c shadow-4.1.4.2/src/groupadd.=
c
--- shadow-4.1.4.2.old/src/groupadd.c	2009-06-05 18:16:58.000000000 -0400
+++ shadow-4.1.4.2/src/groupadd.c	2010-02-16 08:18:58.000000000 -0500
@@ -72,6 +72,8 @@
  */
 char *Prog;
=20
+#define	VALID(s)	(strcspn (s, ":\n") =3D=3D strlen (s))
+
 static /*@null@*/char *group_name;
 static gid_t group_id;
 static /*@null@*/char *group_passwd;
@@ -81,6 +83,8 @@
 static bool gflg =3D false;	/* ID value for the new group */
 static bool fflg =3D false;	/* if group already exists, do nothing and e=
xit(0) */
 static bool rflg =3D false;	/* create a system account */
+static bool Rflg =3D false;	/* root directory offset to access files fro=
m */
+
 static bool pflg =3D false;	/* new encrypted password */
=20
 #ifdef SHADOWGRP
@@ -121,6 +125,7 @@
 	                "                                (non-unique) GID\n"), =
stderr);
 	(void) fputs (_("  -p, --password PASSWORD       use this encrypted pas=
sword for the new group\n"), stderr);
 	(void) fputs (_("  -r, --system                  create a system accoun=
t\n"), stderr);
+	(void) fputs (_("  -R, --chroot ROOT_DIR         access files from an a=
lternate root directory\n"), stderr);
 	(void) fputs ("\n", stderr);
 	exit (E_USAGE);
 }
@@ -373,6 +378,8 @@
 	/*
 	 * Parse the command line options.
 	 */
+	int argc_saved =3D argc;
+	static bool parse_chroot =3D  false;
 	char *cp;
 	int option_index =3D 0;
 	int c;
@@ -384,12 +391,35 @@
 		{"non-unique", no_argument, NULL, 'o'},
 		{"password", required_argument, NULL, 'p'},
 		{"system", no_argument, NULL, 'r'},
+		{"chroot", required_argument, NULL, 'R'},
 		{NULL, 0, NULL, '\0'}
 	};
=20
 	while ((c =3D
-		getopt_long (argc, argv, "fg:hK:op:r", long_options,
+		getopt_long (argc, argv, "fg:hK:op:rR:", long_options,
 		             &option_index)) !=3D -1) {
+		if (!parse_chroot) {
+		switch (c) {
+		case 'R':
+			if ((!VALID(optarg))
+			    || (optarg[0] !=3D '/')) {
+				fprintf (stderr,
+				         _("%s: invalid root directory '%s'\n"),
+				         Prog, optarg);
+				exit (E_BAD_ARG);
+			}
+			if ( chroot(optarg) !=3D 0 ) {
+				fprintf (stderr,
+			         _("%s: unable to change root directory to '%s': %s\n"),
+			         Prog, optarg, strerror (errno));
+				exit (1);
+			}
+			Rflg =3D true;
+			break;
+		default:
+			break;
+		}
+		} else {
 		switch (c) {
 		case 'f':
 			/*
@@ -443,9 +473,20 @@
 		case 'r':
 			rflg =3D true;
 			break;
+		case 'R':
+			break;
 		default:
 			usage ();
 		}
+		}
+	}
+
+	/* Finished parsing for chroot flag */
+	if (!parse_chroot) {
+		parse_chroot =3D true;
+		argc =3D argc_saved;
+		optind =3D 0;
+		return;
 	}
=20
 	/*
@@ -476,8 +517,10 @@
 	/*
 	 * Check if the group already exist.
 	 */
-	/* local, no need for xgetgrnam */
-	if (getgrnam (group_name) !=3D NULL) {
+	/* no chroot flag, local, no need for xgetgrnam */
+	if (((!Rflg) && (getgrnam (group_name) !=3D NULL)) ||
+	/* chroot flag set, use compatible xfgetgrnam */
+		((Rflg) && (xfgetgrnam (group_name) !=3D NULL))) {
 		/* The group already exist */
 		if (fflg) {
 			/* OK, no need to do anything */
@@ -489,7 +532,8 @@
 		exit (E_NAME_IN_USE);
 	}
=20
-	if (gflg && (getgrgid (group_id) !=3D NULL)) {
+	if (((gflg) && (!Rflg) && (getgrgid (group_id) !=3D NULL)) ||
+		((gflg) && (Rflg) && (xfgetgrgid (group_id) !=3D NULL))) {
 		/* A GID was specified, and a group already exist with that GID
 		 *  - either we will use this GID anyway (-o)
 		 *  - either we ignore the specified GID and
@@ -524,6 +568,8 @@
 {
 #ifdef ACCT_TOOLS_SETUID
 #ifdef USE_PAM
+	/* chroot doesn't work with PAM libs */
+	if (!Rflg) {
 	pam_handle_t *pamh =3D NULL;
 	int retval;
 	struct passwd *pampw;
@@ -553,6 +599,7 @@
 		fprintf (stderr, _("%s: PAM authentication failed\n"), Prog);
 		exit (1);
 	}
+	}
 #endif				/* USE_PAM */
 #endif				/* ACCT_TOOLS_SETUID */
 }
@@ -579,6 +626,12 @@
 	OPENLOG ("groupadd");
=20
 	/*
+	 * Parse the chroot option before other options
+	 * but after opening the log.
+	 */
+	process_flags (argc, argv);
+
+	/*
 	 * Parse the command line options.
 	 */
 	process_flags (argc, argv);
diff -Naur shadow-4.1.4.2.old/src/useradd.c shadow-4.1.4.2/src/useradd.c
--- shadow-4.1.4.2.old/src/useradd.c	2009-06-05 18:16:58.000000000 -0400
+++ shadow-4.1.4.2/src/useradd.c	2010-02-16 08:17:32.000000000 -0500
@@ -143,6 +143,7 @@
     Nflg =3D false,		/* do not create a group having the same name as th=
e user, but add the user to def_group (or the group specified with -g) */
     oflg =3D false,		/* permit non-unique user ID to be specified with -=
u */
     rflg =3D false,		/* create a system account */
+    Rflg =3D false,		/* root directory offset to access files from */
     sflg =3D false,		/* shell program for new account */
     uflg =3D false,		/* specify user ID for new account */
     Uflg =3D false,		/* create a group having the same name as the user =
*/
@@ -286,6 +287,7 @@
 	FILE *fp;
 	char buf[1024];
 	char *cp;
+	const struct group *grp;
=20
 	/*
 	 * Open the defaults file for reading.
@@ -317,7 +319,11 @@
 		 * Primary GROUP identifier
 		 */
 		if (MATCH (buf, DGROUP)) {
-			const struct group *grp =3D getgr_nam_gid (cp);
+			if (!Rflg) {
+				grp =3D getgr_nam_gid (cp);
+			} else {
+				grp =3D fgetgr_nam_gid (cp);
+			}
 			if (NULL =3D=3D grp) {
 				fprintf (stderr,
 				         _("%s: group '%s' does not exist\n"),
@@ -618,7 +624,11 @@
 		 * Names starting with digits are treated as numerical
 		 * GID values, otherwise the string is looked up as is.
 		 */
-		grp =3D getgr_nam_gid (list);
+		if (!Rflg) {
+			grp =3D getgr_nam_gid (list);
+		} else {
+			grp =3D fgetgr_nam_gid (list);
+		}
=20
 		/*
 		 * There must be a match, either by GID value or by
@@ -712,6 +722,7 @@
 	                "                                (non-unique) UID\n"), =
stderr);
 	(void) fputs (_("  -p, --password PASSWORD       encrypted password of =
the new account\n"), stderr);
 	(void) fputs (_("  -r, --system                  create a system accoun=
t\n"), stderr);
+	(void) fputs (_("  -R, --chroot ROOT_DIR         access files from an a=
lternate root directory\n"), stderr);
 	(void) fputs (_("  -s, --shell SHELL             login shell of the new=
 account\n"), stderr);
 	(void) fputs (_("  -u, --uid UID                 user ID of the new acc=
ount\n"), stderr);
 	(void) fputs (_("  -U, --user-group              create a group with th=
e same name as the user\n"), stderr);
@@ -960,6 +971,8 @@
 		 * Parse the command line options.
 		 */
 		int c;
+		int argc_saved =3D argc;
+		static bool parse_chroot =3D  false;
 		static struct option long_options[] =3D {
 			{"base-dir", required_argument, NULL, 'b'},
 			{"comment", required_argument, NULL, 'c'},
@@ -979,6 +992,7 @@
 			{"non-unique", no_argument, NULL, 'o'},
 			{"password", required_argument, NULL, 'p'},
 			{"system", no_argument, NULL, 'r'},
+			{"chroot", required_argument, NULL, 'R'},
 			{"shell", required_argument, NULL, 's'},
 #ifdef WITH_SELINUX
 			{"selinux-user", required_argument, NULL, 'Z'},
@@ -989,11 +1003,33 @@
 		};
 		while ((c =3D getopt_long (argc, argv,
 #ifdef WITH_SELINUX
-		                         "b:c:d:De:f:g:G:k:K:lmMNop:rs:u:UZ:",
+		                         "b:c:d:De:f:g:G:k:K:lmMNop:rR:s:u:UZ:",
 #else
-		                         "b:c:d:De:f:g:G:k:K:lmMNop:rs:u:U",
+		                         "b:c:d:De:f:g:G:k:K:lmMNop:rR:s:u:U",
 #endif
 		                         long_options, NULL)) !=3D -1) {
+			if (!parse_chroot) {
+			switch (c) {
+			case 'R':
+				if ((!VALID(optarg))
+				    || (optarg[0] !=3D '/')) {
+					fprintf (stderr,
+					         _("%s: invalid root directory '%s'\n"),
+					         Prog, optarg);
+					exit (E_BAD_ARG);
+				}
+				if ( chroot(optarg) !=3D 0 ) {
+					fprintf (stderr,
+				         _("%s: unable to change root directory to '%s': %s\n"),
+				         Prog, optarg, strerror (errno));
+					fail_exit (1);
+				}
+				Rflg =3D true;
+				break;
+			default:
+				break;
+			}
+			} else {
 			switch (c) {
 			case 'b':
 				if (   ( !VALID (optarg) )
@@ -1081,7 +1117,11 @@
 				fflg =3D true;
 				break;
 			case 'g':
-				grp =3D getgr_nam_gid (optarg);
+				if (!Rflg) {
+					grp =3D getgr_nam_gid (optarg);
+				} else {
+					grp =3D fgetgr_nam_gid (optarg);
+				}
 				if (NULL =3D=3D grp) {
 					fprintf (stderr,
 					         _("%s: group '%s' does not exist\n"),
@@ -1159,6 +1199,8 @@
 			case 'r':
 				rflg =3D true;
 				break;
+			case 'R':
+				break;
 			case 's':
 				if (   ( !VALID (optarg) )
 				    || (   ('\0' !=3D optarg[0])
@@ -1204,6 +1246,14 @@
 				usage ();
 			}
 			anyflag =3D true;
+			}
+		}
+		/* Finished parsing for chroot flag */
+		if (!parse_chroot) {
+			parse_chroot =3D true;
+			argc =3D argc_saved;
+			optind =3D 0;
+			return;
 		}
 	}
=20
@@ -1663,8 +1713,10 @@
 	 * no user with this UID exists yet (entries for shared UIDs
 	 * are left unchanged).  --marekm
 	 */
-	/* local, no need for xgetpwuid */
-	if ((!lflg) && (getpwuid (user_id) =3D=3D NULL)) {
+	/* no chroot flag, local, no need for xgetpwuid */
+	if ((((!Rflg) && (!lflg)) && (getpwuid (user_id) =3D=3D NULL)) ||
+		/* chroot flag set, use compatible xfgetpwuid */
+		((!lflg) && (xfgetpwuid (user_id) =3D=3D NULL))) {
 		faillog_reset (user_id);
 		lastlog_reset (user_id);
 	}
@@ -1806,7 +1858,11 @@
 			return;
 		}
=20
-		gr =3D getgrnam ("mail"); /* local, no need for xgetgrnam */
+		if (!Rflg) {
+			gr =3D getgrnam ("mail"); /* no chroot flag, local, no need for xgetg=
rnam */
+		} else {
+			gr =3D xfgetgrnam ("mail"); /* chroot flag set, use compatible xfgetg=
rnam */
+		}
 		if (NULL =3D=3D gr) {
 			fputs (_("Group 'mail' not found. Creating the user mailbox file with=
 0600 mode.\n"),
 			       stderr);
@@ -1861,6 +1917,12 @@
 	 */
 	user_groups[0] =3D (char *) 0;
=20
+	/*
+	 * Parse the chroot option before other options
+	 * and before accessing any database files,
+	 * but after opening the log.
+	 */
+	process_flags (argc, argv);
=20
 	is_shadow_pwd =3D spw_file_present ();
 #ifdef SHADOWGRP
@@ -1873,6 +1935,8 @@
=20
 #ifdef ACCT_TOOLS_SETUID
 #ifdef USE_PAM
+	/* chroot doesn't work with PAM libs */
+	if (!Rflg) {
 	{
 		struct passwd *pampw;
 		pampw =3D getpwuid (getuid ()); /* local, no need for xgetpwuid */
@@ -1901,6 +1965,7 @@
 		fprintf (stderr, _("%s: PAM authentication failed\n"), Prog);
 		fail_exit (1);
 	}
+	}
 #endif				/* USE_PAM */
 #endif				/* ACCT_TOOLS_SETUID */
=20
@@ -1920,7 +1985,8 @@
 	/*
 	 * Start with a quick check to see if the user exists.
 	 */
-	if (getpwnam (user_name) !=3D NULL) { /* local, no need for xgetpwnam *=
/
+	if (((!Rflg) && (getpwnam (user_name) !=3D NULL)) || /* no chroot flag,=
 local, no need for xgetpwnam */
+		((Rflg) && (xfgetpwnam (user_name) !=3D NULL))) { /* chroot flag set, =
use compatible xfgetpwnam */
 		fprintf (stderr, _("%s: user '%s' already exists\n"), Prog, user_name)=
;
 #ifdef WITH_AUDIT
 		audit_logger (AUDIT_ADD_USER, Prog,
@@ -1938,8 +2004,10 @@
 	 * --bero
 	 */
 	if (Uflg) {
-		/* local, no need for xgetgrnam */
-		if (getgrnam (user_name) !=3D NULL) {
+		/* no chroot flag, local, no need for xgetgrnam */
+		if (((!Rflg) && (getgrnam (user_name) !=3D NULL)) ||
+			/* chroot flag set, use compatible xfgetgrnam */
+			((Rflg) && (xfgetgrnam (user_name) !=3D NULL))) {
 			fprintf (stderr,
 			         _("%s: group %s exists - if you want to add this user to tha=
t group, use -g.\n"),
 			         Prog, user_name);
@@ -1974,7 +2042,8 @@
 				fail_exit (E_UID_IN_USE);
 			}
 		} else {
-			if (getpwuid (user_id) !=3D NULL) {
+			if (((!Rflg) && (getpwuid (user_id) !=3D NULL)) ||=20
+				((Rflg) && (xfgetpwuid (user_id) !=3D NULL))) {
 				fprintf (stderr,
 				         _("%s: UID %lu is not unique\n"),
 				         Prog, (unsigned long) user_id);


--Boundary_(ID_4pxH5Gb8qSEhwHZXfZkhWA)--