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
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
+/* 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
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 getspnam \
gettimeofday getusershell getutent initgroups lchown lckpwdf lstat \
lutimes memcpy memset setgroups sigaction strchr updwtmp updwtmpx innetgr \
- 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=`$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 getspnam \
gettimeofday getusershell getutent initgroups lchown lckpwdf lstat \
lutimes memcpy memset setgroups sigaction strchr updwtmp updwtmpx innetgr \
- 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
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/prototypes.h
--- shadow-4.1.4.2.old/lib/prototypes.h 2009-05-18 14:32:21.000000000 -0400
+++ shadow-4.1.4.2/lib/prototypes.h 2010-02-16 07:19:48.000000000 -0500
@@ -154,6 +154,7 @@
/* getgr_nam_gid.c */
extern /*...@null@*/struct group *getgr_nam_gid (const char *grname);
+extern /*...@null@*/struct group *fgetgr_nam_gid (const char *grname);
/* 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 *);
+/* 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);
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 -0500
@@ -1,5 +1,5 @@
-EXTRA_DIST = .indent.pro xgetXXbyYY.c
+EXTRA_DIST = .indent.pro xgetXXbyYY.c xfgetXXbyYY.c
INCLUDES = -I$(top_srcdir)/lib
@@ -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 -0500
@@ -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 = $(am_libmisc_a_OBJECTS)
DEFAULT_INCLUDES = -...@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
@@ -232,7 +233,7 @@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
-EXTRA_DIST = .indent.pro xgetXXbyYY.c
+EXTRA_DIST = .indent.pro xgetXXbyYY.c xfgetXXbyYY.c
INCLUDES = -I$(top_srcdir)/lib
noinst_LIBRARIES = libmisc.a
libmisc_a_SOURCES = \
@@ -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__qu...@./$(DEPDIR)/user_busy...@am__quote@
@AMDEP_TRUE@@am__include@ @am__qu...@./$(DEPDIR)/utmp...@am__quote@
@AMDEP_TRUE@@am__include@ @am__qu...@./$(DEPDIR)/valid...@am__quote@
+...@amdep_true@@am__include@ @am__qu...@./$(DEPDIR)/xfgetgrgid...@am__quote@
+...@amdep_true@@am__include@ @am__qu...@./$(DEPDIR)/xfgetgrnam...@am__quote@
+...@amdep_true@@am__include@ @am__qu...@./$(DEPDIR)/xfgetpwnam...@am__quote@
+...@amdep_true@@am__include@ @am__qu...@./$(DEPDIR)/xfgetpwuid...@am__quote@
@AMDEP_TRUE@@am__include@ @am__qu...@./$(DEPDIR)/xgetgrgid...@am__quote@
@AMDEP_TRUE@@am__include@ @am__qu...@./$(DEPDIR)/xgetgrnam...@am__quote@
@AMDEP_TRUE@@am__include@ @am__qu...@./$(DEPDIR)/xgetpwnam...@am__quote@
diff -Naur shadow-4.1.4.2.old/libmisc/getgr_nam_gid.c shadow-4.1.4.2/libmisc/getgr_nam_gid.c
--- shadow-4.1.4.2.old/libmisc/getgr_nam_gid.c 2009-04-29 09:50:14.000000000 -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);
}
+/*
+ * 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 == grname) {
+ return NULL;
+ }
+
+ errno = 0;
+ gid = strtoll (grname, &endptr, 10);
+ if ( ('\0' != *grname)
+ && ('\0' == *endptr)
+ && (ERANGE != errno)
+ && (/*...@+longintegral@*/gid == (gid_t)gid)/*...@=longintegral@*/) {
+ return xfgetgrgid ((gid_t) gid);
+ }
+ return xfgetgrnam (grname);
+}
+
diff -Naur shadow-4.1.4.2.old/libmisc/xfgetXXbyYY.c shadow-4.1.4.2/libmisc/xfgetXXbyYY.c
--- shadow-4.1.4.2.old/libmisc/xfgetXXbyYY.c 1969-12-31 19:00:00.000000000 -0500
+++ shadow-4.1.4.2/libmisc/xfgetXXbyYY.c 2010-02-16 07:19:48.000000000 -0500
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2007 - 2009, Nicolas François
+ * 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 the
+ * documentation and/or other materials provided with the distribution.
+ * 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, INCIDENTAL,
+ * 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. Care about standard library calls
+ *
+ * In general, writers of authorization-granting applications should
+ * assume that each module is likely to call any or all 'libc' functions.
+ * 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 function
+ * is likely to corrupt a pointer previously obtained by the application.
+ * The application programmer should either re-call such a 'libc'
+ * function after a call to the Linux-PAM library, or copy the structure
+ * 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 == 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 = NULL;
+ if ((stream = fopen (DB_FILE, "r")) == NULL) {
+ fprintf (stderr, _("%s: Error opening the database file.\n"),
+ "x" STRINGIZE(FUNCTION_NAME));
+ exit (1);
+ }
+#if HAVE_FUNCTION_R
+ LOOKUP_TYPE *result=NULL;
+ char *buffer=NULL;
+ /* we have to start with something */
+ size_t length = 0x100;
+
+ result = malloc(sizeof(LOOKUP_TYPE));
+ if (NULL == result) {
+ fprintf (stderr, _("%s: out of memory\n"),
+ "x" STRINGIZE(FUNCTION_NAME));
+ exit (13);
+ }
+
+ while (true) {
+ int status;
+ LOOKUP_TYPE *resbuf = NULL;
+ buffer = (char *)realloc (buffer, length);
+ if (NULL == buffer) {
+ fprintf (stderr, _("%s: out of memory\n"),
+ "x" STRINGIZE(FUNCTION_NAME));
+ exit (13);
+ }
+ errno = 0;
+ status = REENTRANT_NAME(stream, result, buffer,
+ length, &resbuf);
+ while ((0 ==status) && (resbuf == result)) {
+ if (F_COMPARE) {
+ /* Build a result structure that can be freed by
+ * the shadow *_free functions. */
+ LOOKUP_TYPE *ret_result = DUP_FUNCTION(result);
+ (void) fclose (stream);
+ free(buffer);
+ free(result);
+ return ret_result;
+ } else {
+ status = REENTRANT_NAME(stream, result, buffer,
+ length, &resbuf);
+ }
+ }
+
+ if (ERANGE != errno) {
+ (void) fclose (stream);
+ free (buffer);
+ free (result);
+ return NULL;
+ }
+
+ if (length <= ((size_t)-1 / 4)) {
+ length *= 4;
+ } else if (length == (size_t) -1) {
+ break;
+ } else {
+ length = (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 = F_FUNCTION_NAME(stream);
+
+ while (result) {
+ if (F_COMPARE) {
+ result = DUP_FUNCTION(result);
+ if (NULL == result) {
+ fprintf (stderr, _("%s: out of memory\n"),
+ "x" STRINGIZE(FUNCTION_NAME));
+ exit (13);
+ }
+ break;
+ } else {
+ result = 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 -0500
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2007 - 2009, Nicolas François
+ * 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 the
+ * documentation and/or other materials provided with the distribution.
+ * 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, INCIDENTAL,
+ * 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. Care about standard library calls
+ *
+ * In general, writers of authorization-granting applications should
+ * assume that each module is likely to call any or all 'libc' functions.
+ * 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 function
+ * is likely to corrupt a pointer previously obtained by the application.
+ * The application programmer should either re-call such a 'libc'
+ * function after a call to the Linux-PAM library, or copy the structure
+ * 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 -0500
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2007 - 2009, Nicolas François
+ * 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 the
+ * documentation and/or other materials provided with the distribution.
+ * 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, INCIDENTAL,
+ * 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. Care about standard library calls
+ *
+ * In general, writers of authorization-granting applications should
+ * assume that each module is likely to call any or all 'libc' functions.
+ * 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 function
+ * is likely to corrupt a pointer previously obtained by the application.
+ * The application programmer should either re-call such a 'libc'
+ * function after a call to the Linux-PAM library, or copy the structure
+ * 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 -0500
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2007 - 2009, Nicolas François
+ * 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 the
+ * documentation and/or other materials provided with the distribution.
+ * 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, INCIDENTAL,
+ * 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. Care about standard library calls
+ *
+ * In general, writers of authorization-granting applications should
+ * assume that each module is likely to call any or all 'libc' functions.
+ * 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 function
+ * is likely to corrupt a pointer previously obtained by the application.
+ * The application programmer should either re-call such a 'libc'
+ * function after a call to the Linux-PAM library, or copy the structure
+ * 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 -0500
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2007 - 2009, Nicolas François
+ * 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 the
+ * documentation and/or other materials provided with the distribution.
+ * 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, INCIDENTAL,
+ * 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. Care about standard library calls
+ *
+ * In general, writers of authorization-granting applications should
+ * assume that each module is likely to call any or all 'libc' functions.
+ * 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 function
+ * is likely to corrupt a pointer previously obtained by the application.
+ * The application programmer should either re-call such a 'libc'
+ * function after a call to the Linux-PAM library, or copy the structure
+ * 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 will 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/groupadd.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>
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 will 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 field blank, which causes the system to select the default login shell specified by the
diff -Naur shadow-4.1.4.2.old/man/useradd.8.xml shadow-4.1.4.2/man/useradd.8.xml
--- shadow-4.1.4.2.old/man/useradd.8.xml 2009-05-21 08:02:13.000000000 -0400
+++ 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;
+#define VALID(s) (strcspn (s, ":\n") == strlen (s))
+
static /*...@null@*/char *group_name;
static gid_t group_id;
static /*...@null@*/char *group_passwd;
@@ -81,6 +83,8 @@
static bool gflg = false; /* ID value for the new group */
static bool fflg = false; /* if group already exists, do nothing and exit(0) */
static bool rflg = false; /* create a system account */
+static bool Rflg = false; /* root directory offset to access files from */
+
static bool pflg = false; /* new encrypted password */
#ifdef SHADOWGRP
@@ -121,6 +125,7 @@
" (non-unique) GID\n"), stderr);
(void) fputs (_(" -p, --password PASSWORD use this encrypted password for the new group\n"), stderr);
(void) fputs (_(" -r, --system create a system account\n"), stderr);
+ (void) fputs (_(" -R, --chroot ROOT_DIR access files from an alternate root directory\n"), stderr);
(void) fputs ("\n", stderr);
exit (E_USAGE);
}
@@ -373,6 +378,8 @@
/*
* Parse the command line options.
*/
+ int argc_saved = argc;
+ static bool parse_chroot = false;
char *cp;
int option_index = 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'}
};
while ((c =
- getopt_long (argc, argv, "fg:hK:op:r", long_options,
+ getopt_long (argc, argv, "fg:hK:op:rR:", long_options,
&option_index)) != -1) {
+ if (!parse_chroot) {
+ switch (c) {
+ case 'R':
+ if ((!VALID(optarg))
+ || (optarg[0] != '/')) {
+ fprintf (stderr,
+ _("%s: invalid root directory '%s'\n"),
+ Prog, optarg);
+ exit (E_BAD_ARG);
+ }
+ if ( chroot(optarg) != 0 ) {
+ fprintf (stderr,
+ _("%s: unable to change root directory to '%s': %s\n"),
+ Prog, optarg, strerror (errno));
+ exit (1);
+ }
+ Rflg = true;
+ break;
+ default:
+ break;
+ }
+ } else {
switch (c) {
case 'f':
/*
@@ -443,9 +473,20 @@
case 'r':
rflg = true;
break;
+ case 'R':
+ break;
default:
usage ();
}
+ }
+ }
+
+ /* Finished parsing for chroot flag */
+ if (!parse_chroot) {
+ parse_chroot = true;
+ argc = argc_saved;
+ optind = 0;
+ return;
}
/*
@@ -476,8 +517,10 @@
/*
* Check if the group already exist.
*/
- /* local, no need for xgetgrnam */
- if (getgrnam (group_name) != NULL) {
+ /* no chroot flag, local, no need for xgetgrnam */
+ if (((!Rflg) && (getgrnam (group_name) != NULL)) ||
+ /* chroot flag set, use compatible xfgetgrnam */
+ ((Rflg) && (xfgetgrnam (group_name) != NULL))) {
/* The group already exist */
if (fflg) {
/* OK, no need to do anything */
@@ -489,7 +532,8 @@
exit (E_NAME_IN_USE);
}
- if (gflg && (getgrgid (group_id) != NULL)) {
+ if (((gflg) && (!Rflg) && (getgrgid (group_id) != NULL)) ||
+ ((gflg) && (Rflg) && (xfgetgrgid (group_id) != 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 = 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");
/*
+ * 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 = false, /* do not create a group having the same name as the user, but add the user to def_group (or the group specified with -g) */
oflg = false, /* permit non-unique user ID to be specified with -u */
rflg = false, /* create a system account */
+ Rflg = false, /* root directory offset to access files from */
sflg = false, /* shell program for new account */
uflg = false, /* specify user ID for new account */
Uflg = 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;
/*
* Open the defaults file for reading.
@@ -317,7 +319,11 @@
* Primary GROUP identifier
*/
if (MATCH (buf, DGROUP)) {
- const struct group *grp = getgr_nam_gid (cp);
+ if (!Rflg) {
+ grp = getgr_nam_gid (cp);
+ } else {
+ grp = fgetgr_nam_gid (cp);
+ }
if (NULL == 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 = getgr_nam_gid (list);
+ if (!Rflg) {
+ grp = getgr_nam_gid (list);
+ } else {
+ grp = fgetgr_nam_gid (list);
+ }
/*
* 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 account\n"), stderr);
+ (void) fputs (_(" -R, --chroot ROOT_DIR access files from an alternate 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 account\n"), stderr);
(void) fputs (_(" -U, --user-group create a group with the same name as the user\n"), stderr);
@@ -960,6 +971,8 @@
* Parse the command line options.
*/
int c;
+ int argc_saved = argc;
+ static bool parse_chroot = false;
static struct option long_options[] = {
{"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 = 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)) != -1) {
+ if (!parse_chroot) {
+ switch (c) {
+ case 'R':
+ if ((!VALID(optarg))
+ || (optarg[0] != '/')) {
+ fprintf (stderr,
+ _("%s: invalid root directory '%s'\n"),
+ Prog, optarg);
+ exit (E_BAD_ARG);
+ }
+ if ( chroot(optarg) != 0 ) {
+ fprintf (stderr,
+ _("%s: unable to change root directory to '%s': %s\n"),
+ Prog, optarg, strerror (errno));
+ fail_exit (1);
+ }
+ Rflg = true;
+ break;
+ default:
+ break;
+ }
+ } else {
switch (c) {
case 'b':
if ( ( !VALID (optarg) )
@@ -1081,7 +1117,11 @@
fflg = true;
break;
case 'g':
- grp = getgr_nam_gid (optarg);
+ if (!Rflg) {
+ grp = getgr_nam_gid (optarg);
+ } else {
+ grp = fgetgr_nam_gid (optarg);
+ }
if (NULL == grp) {
fprintf (stderr,
_("%s: group '%s' does not exist\n"),
@@ -1159,6 +1199,8 @@
case 'r':
rflg = true;
break;
+ case 'R':
+ break;
case 's':
if ( ( !VALID (optarg) )
|| ( ('\0' != optarg[0])
@@ -1204,6 +1246,14 @@
usage ();
}
anyflag = true;
+ }
+ }
+ /* Finished parsing for chroot flag */
+ if (!parse_chroot) {
+ parse_chroot = true;
+ argc = argc_saved;
+ optind = 0;
+ return;
}
}
@@ -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) == NULL)) {
+ /* no chroot flag, local, no need for xgetpwuid */
+ if ((((!Rflg) && (!lflg)) && (getpwuid (user_id) == NULL)) ||
+ /* chroot flag set, use compatible xfgetpwuid */
+ ((!lflg) && (xfgetpwuid (user_id) == NULL))) {
faillog_reset (user_id);
lastlog_reset (user_id);
}
@@ -1806,7 +1858,11 @@
return;
}
- gr = getgrnam ("mail"); /* local, no need for xgetgrnam */
+ if (!Rflg) {
+ gr = getgrnam ("mail"); /* no chroot flag, local, no need for xgetgrnam */
+ } else {
+ gr = xfgetgrnam ("mail"); /* chroot flag set, use compatible xfgetgrnam */
+ }
if (NULL == gr) {
fputs (_("Group 'mail' not found. Creating the user mailbox file with 0600 mode.\n"),
stderr);
@@ -1861,6 +1917,12 @@
*/
user_groups[0] = (char *) 0;
+ /*
+ * Parse the chroot option before other options
+ * and before accessing any database files,
+ * but after opening the log.
+ */
+ process_flags (argc, argv);
is_shadow_pwd = spw_file_present ();
#ifdef SHADOWGRP
@@ -1873,6 +1935,8 @@
#ifdef ACCT_TOOLS_SETUID
#ifdef USE_PAM
+ /* chroot doesn't work with PAM libs */
+ if (!Rflg) {
{
struct passwd *pampw;
pampw = 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 */
@@ -1920,7 +1985,8 @@
/*
* Start with a quick check to see if the user exists.
*/
- if (getpwnam (user_name) != NULL) { /* local, no need for xgetpwnam */
+ if (((!Rflg) && (getpwnam (user_name) != NULL)) || /* no chroot flag, local, no need for xgetpwnam */
+ ((Rflg) && (xfgetpwnam (user_name) != 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) != NULL) {
+ /* no chroot flag, local, no need for xgetgrnam */
+ if (((!Rflg) && (getgrnam (user_name) != NULL)) ||
+ /* chroot flag set, use compatible xfgetgrnam */
+ ((Rflg) && (xfgetgrnam (user_name) != NULL))) {
fprintf (stderr,
_("%s: group %s exists - if you want to add this user to that group, use -g.\n"),
Prog, user_name);
@@ -1974,7 +2042,8 @@
fail_exit (E_UID_IN_USE);
}
} else {
- if (getpwuid (user_id) != NULL) {
+ if (((!Rflg) && (getpwuid (user_id) != NULL)) ||
+ ((Rflg) && (xfgetpwuid (user_id) != NULL))) {
fprintf (stderr,
_("%s: UID %lu is not unique\n"),
Prog, (unsigned long) user_id);