* NEWS, configure.in, libmisc/copydir.c, man/useradd.8.xml,

man/usermod.8.xml, src/Makefile.am: Added support for ACLs and
	Extended Attributes.
This commit is contained in:
nekral-guest 2010-03-30 21:01:27 +00:00
parent 6afd7859f8
commit 902aad57af
8 changed files with 167 additions and 9 deletions

View File

@ -1,3 +1,9 @@
2010-03-30 Nicolas François <nicolas.francois@centraliens.net>
* NEWS, configure.in, libmisc/copydir.c, man/useradd.8.xml,
man/usermod.8.xml, src/Makefile.am: Added support for ACLs and
Extended Attributes.
2010-03-30 Nicolas François <nicolas.francois@centraliens.net> 2010-03-30 Nicolas François <nicolas.francois@centraliens.net>
* libmisc/copydir.c: Document the sections closed by #endif * libmisc/copydir.c: Document the sections closed by #endif

3
NEWS
View File

@ -7,6 +7,9 @@ shadow-4.1.4.2 -> shadow-4.1.5 UNRELEASED
zero) when explicitly requested (e.g. with --help). zero) when explicitly requested (e.g. with --help).
* initial support for tcb (http://openwall.com/tcb/) for useradd, * initial support for tcb (http://openwall.com/tcb/) for useradd,
userdel, usermod, chage, pwck, vipw. userdel, usermod, chage, pwck, vipw.
* Added support for ACLs and Extended Attributes in useradd and usermod.
Support shall be enabled with the new --with-acl or --with-attr
configure options.
-chpasswd -chpasswd
* PAM enabled versions: restore the -e option to allow restoring * PAM enabled versions: restore the -e option to allow restoring

5
TODO
View File

@ -120,4 +120,7 @@ ALL:
- su - su
- add a login.defs configuration parameter to add variables to keep in - add a login.defs configuration parameter to add variables to keep in
the environment with "su -l" (TERM/TERMCOLOR/... the environment with "su -l" (TERM/TERMCOLOR/...)
- vipw
- set ACT and XATTR on the temporary file (and backups?)

View File

@ -33,7 +33,8 @@ AC_HEADER_STDBOOL
AC_CHECK_HEADERS(errno.h fcntl.h limits.h unistd.h sys/time.h utmp.h \ AC_CHECK_HEADERS(errno.h fcntl.h limits.h unistd.h sys/time.h utmp.h \
utmpx.h termios.h termio.h sgtty.h sys/ioctl.h syslog.h paths.h \ utmpx.h termios.h termio.h sgtty.h sys/ioctl.h syslog.h paths.h \
utime.h ulimit.h sys/resource.h gshadow.h lastlog.h \ utime.h ulimit.h sys/resource.h gshadow.h lastlog.h \
locale.h rpc/key_prot.h netdb.h) locale.h rpc/key_prot.h netdb.h acl/libacl.h attr/libattr.h
attr/error_context.h)
dnl shadow now uses the libc's shadow implementation dnl shadow now uses the libc's shadow implementation
AC_CHECK_HEADER([shadow.h],,[AC_MSG_ERROR([You need a libc with shadow.h])]) AC_CHECK_HEADER([shadow.h],,[AC_MSG_ERROR([You need a libc with shadow.h])])
@ -246,6 +247,10 @@ AC_ARG_WITH(libpam,
AC_ARG_WITH(selinux, AC_ARG_WITH(selinux,
[AC_HELP_STRING([--with-selinux], [use SELinux support @<:@default=yes if found@:>@])], [AC_HELP_STRING([--with-selinux], [use SELinux support @<:@default=yes if found@:>@])],
[with_selinux=$withval], [with_selinux=maybe]) [with_selinux=$withval], [with_selinux=maybe])
AC_ARG_WITH(acl,
[AC_HELP_STRING([--with-acl], [use ACL support @<:@default=yes if found@:>@])],
[AC_HELP_STRING([--with-attr], [use Extended Attribute support @<:@default=yes if found@:>@])],
[with_attr=$withval], [with_attr=maybe])
AC_ARG_WITH(skey, AC_ARG_WITH(skey,
[AC_HELP_STRING([--with-skey], [use S/Key support @<:@default=no@:>@])], [AC_HELP_STRING([--with-skey], [use S/Key support @<:@default=no@:>@])],
[with_skey=$withval], [with_skey=no]) [with_skey=$withval], [with_skey=no])
@ -319,6 +324,58 @@ AC_SUBST(LIBCRYPT)
AC_CHECK_LIB(crypt, crypt, [LIBCRYPT=-lcrypt], AC_CHECK_LIB(crypt, crypt, [LIBCRYPT=-lcrypt],
[AC_MSG_ERROR([crypt() not found])]) [AC_MSG_ERROR([crypt() not found])])
AC_SUBST(LIBACL)
if test "$with_acl" != "no"; then
AC_CHECK_HEADERS(acl/libacl.h attr/error_context.h, [acl_header="yes"], [acl_header="no"])
if test "$acl_header$with_acl" = "noyes" ; then
AC_MSG_ERROR([acl/libacl.h or attr/error_context.h is missing])
elif test "$acl_header" = "yes" ; then
AC_CHECK_LIB(acl, perm_copy_file,
[AC_CHECK_LIB(acl, perm_copy_fd,
[acl_lib="yes"],
[acl_lib="no"])],
[acl_lib="no"])
if test "$acl_lib$with_acl" = "noyes" ; then
AC_MSG_ERROR([libacl not found])
elif test "$acl_lib" = "no" ; then
with_acl="no"
else
AC_DEFINE(WITH_ACL, 1,
[Build shadow with ACL support])
LIBACL="-lacl"
with_acl="yes"
fi
else
with_acl="no"
fi
fi
AC_SUBST(LIBATTR)
if test "$with_attr" != "no"; then
AC_CHECK_HEADERS(attr/libattr.h attr/error_context.h, [attr_header="yes"], [attr_header="no"])
if test "$attr_header$with_attr" = "noyes" ; then
AC_MSG_ERROR([attr/libattr.h or attr/error_context.h is missing])
elif test "$attr_header" = "yes" ; then
AC_CHECK_LIB(attr, attr_copy_file,
[AC_CHECK_LIB(attr, attr_copy_fd,
[attr_lib="yes"],
[attr_lib="no"])],
[attr_lib="no"])
if test "$attr_lib$with_attr" = "noyes" ; then
AC_MSG_ERROR([libattr not found])
elif test "$attr_lib" = "no" ; then
with_attr="no"
else
AC_DEFINE(WITH_ATTR, 1,
[Build shadow with Extended Attributes support])
LIBACL="-lattr"
with_attr="yes"
fi
else
with_attr="no"
fi
fi
AC_SUBST(LIBAUDIT) AC_SUBST(LIBAUDIT)
if test "$with_audit" != "no"; then if test "$with_audit" != "no"; then
AC_CHECK_HEADER(libaudit.h, [audit_header="yes"], [audit_header="no"]) AC_CHECK_HEADER(libaudit.h, [audit_header="yes"], [audit_header="no"])
@ -565,6 +622,8 @@ if test "$with_libpam" = "yes"; then
echo " suid account management tools: $enable_acct_tools_setuid" echo " suid account management tools: $enable_acct_tools_setuid"
fi fi
echo " SELinux support: $with_selinux" echo " SELinux support: $with_selinux"
echo " ACL support: $with_acl"
echo " Extended Attributes support: $with_attr"
echo " tcb support (incomplete): $with_tcb" echo " tcb support (incomplete): $with_tcb"
echo " shadow group support: $enable_shadowgrp" echo " shadow group support: $enable_shadowgrp"
echo " S/Key support: $with_skey" echo " S/Key support: $with_skey"

View File

@ -45,6 +45,16 @@
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
#include <selinux/selinux.h> #include <selinux/selinux.h>
#endif /* WITH_SELINUX */ #endif /* WITH_SELINUX */
#if defined(WITH_ACL) || defined(WITH_ATTR)
#include <attr/error_context.h>
#endif /* WITH_ACL || WITH_ATTR */
#ifdef WITH_ACL
#include <acl/libacl.h>
#endif /* WITH_ACL */
#ifdef WITH_ATTR
#include <attr/libattr.h>
#endif /* WITH_ATTR */
static /*@null@*/const char *src_orig; static /*@null@*/const char *src_orig;
static /*@null@*/const char *dst_orig; static /*@null@*/const char *dst_orig;
@ -70,7 +80,7 @@ static int copy_symlink (const char *src, const char *dst,
#endif /* S_IFLNK */ #endif /* S_IFLNK */
static int copy_hardlink (const char *src, const char *dst, static int copy_hardlink (const char *src, const char *dst,
struct link_name *lp); struct link_name *lp);
static int copy_special (const char *dst, static int copy_special (const char *src, const char *dst,
const struct stat *statp, const struct timeval mt[], const struct stat *statp, const struct timeval mt[],
long int uid, long int gid); long int uid, long int gid);
static int copy_file (const char *src, const char *dst, static int copy_file (const char *src, const char *dst,
@ -119,6 +129,25 @@ int selinux_file_context (const char *dst_name)
} }
#endif /* WITH_SELINUX */ #endif /* WITH_SELINUX */
#if defined(WITH_ACL) || defined(WITH_ATTR)
void error (struct error_context *ctx, const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
(void) fprintf (stderr, _("%s: "), Prog);
if (vfprintf (stderr, fmt, ap) != 0) {
(void) fputs (_(": "), stderr);
}
(void) fprintf (stderr, "%s\n", strerror (errno));
va_end (ap);
}
struct error_context ctx = {
error
};
#endif /* WITH_ACL || WITH_ATTR */
/* /*
* remove_link - delete a link from the linked list * remove_link - delete a link from the linked list
*/ */
@ -369,7 +398,7 @@ static int copy_entry (const char *src, const char *dst,
*/ */
else if (!S_ISREG (sb.st_mode)) { else if (!S_ISREG (sb.st_mode)) {
err = copy_special (dst, &sb, mt, uid, gid); err = copy_special (src, dst, &sb, mt, uid, gid);
} }
/* /*
@ -413,7 +442,21 @@ static int copy_dir (const char *src, const char *dst,
|| (chown (dst, || (chown (dst,
(uid == - 1) ? statp->st_uid : (uid_t) uid, (uid == - 1) ? statp->st_uid : (uid_t) uid,
(gid == - 1) ? statp->st_gid : (gid_t) gid) != 0) (gid == - 1) ? statp->st_gid : (gid_t) gid) != 0)
#ifdef WITH_ACL
|| (perm_copy_file (src, dst, &ctx) != 0)
#else /* !WITH_ACL */
|| (chmod (dst, statp->st_mode) != 0) || (chmod (dst, statp->st_mode) != 0)
#endif /* !WITH_ACL */
#ifdef WITH_ATTR
/*
* If the third parameter is NULL, all extended attributes
* except those that define Access Control Lists are copied.
* ACLs are excluded by default because copying them between
* file systems with and without ACL support needs some
* additional logic so that no unexpected permissions result.
*/
|| (attr_copy_file (src, dst, NULL, &ctx) != 0)
#endif /* WITH_ATTR */
|| (copy_tree (src, dst, uid, gid) != 0) || (copy_tree (src, dst, uid, gid) != 0)
|| (utimes (dst, mt) != 0)) { || (utimes (dst, mt) != 0)) {
err = -1; err = -1;
@ -514,6 +557,13 @@ static int copy_symlink (const char *src, const char *dst,
|| (lchown (dst, || (lchown (dst,
(uid == -1) ? statp->st_uid : (uid_t) uid, (uid == -1) ? statp->st_uid : (uid_t) uid,
(gid == -1) ? statp->st_gid : (gid_t) gid) != 0)) { (gid == -1) ? statp->st_gid : (gid_t) gid) != 0)) {
/* FIXME: there are no modes on symlinks, right?
* ACL could be copied, but this would be much more
* complex than calling perm_copy_file.
* Ditto for Extended Attributes.
* We currently only document that ACL and Extended
* Attributes are not copied.
*/
free (oldlink); free (oldlink);
return -1; return -1;
} }
@ -542,7 +592,7 @@ static int copy_symlink (const char *src, const char *dst,
static int copy_hardlink (const char *src, const char *dst, static int copy_hardlink (const char *src, const char *dst,
struct link_name *lp) struct link_name *lp)
{ {
/* TODO: selinux needed? */ /* TODO: selinux, ACL, Extended Attributes needed? */
if (link (lp->ln_name, dst) != 0) { if (link (lp->ln_name, dst) != 0) {
return -1; return -1;
@ -574,7 +624,7 @@ static int copy_hardlink (const char *src, const char *dst,
* *
* Return 0 on success, -1 on error. * Return 0 on success, -1 on error.
*/ */
static int copy_special (const char *dst, static int copy_special (const char *src, const char *dst,
const struct stat *statp, const struct timeval mt[], const struct stat *statp, const struct timeval mt[],
long int uid, long int gid) long int uid, long int gid)
{ {
@ -588,7 +638,21 @@ static int copy_special (const char *dst,
|| (chown (dst, || (chown (dst,
(uid == -1) ? statp->st_uid : (uid_t) uid, (uid == -1) ? statp->st_uid : (uid_t) uid,
(gid == -1) ? statp->st_gid : (gid_t) gid) != 0) (gid == -1) ? statp->st_gid : (gid_t) gid) != 0)
#ifdef WITH_ACL
|| (perm_copy_file (src, dst, &ctx) != 0)
#else /* !WITH_ACL */
|| (chmod (dst, statp->st_mode & 07777) != 0) || (chmod (dst, statp->st_mode & 07777) != 0)
#endif /* !WITH_ACL */
#ifdef WITH_ATTR
/*
* If the third parameter is NULL, all extended attributes
* except those that define Access Control Lists are copied.
* ACLs are excluded by default because copying them between
* file systems with and without ACL support needs some
* additional logic so that no unexpected permissions result.
*/
|| (attr_copy_file (src, dst, NULL, &ctx) != 0)
#endif /* WITH_ATTR */
|| (utimes (dst, mt) != 0)) { || (utimes (dst, mt) != 0)) {
err = -1; err = -1;
} }
@ -628,7 +692,22 @@ static int copy_file (const char *src, const char *dst,
|| (fchown (ofd, || (fchown (ofd,
(uid == -1) ? statp->st_uid : (uid_t) uid, (uid == -1) ? statp->st_uid : (uid_t) uid,
(gid == -1) ? statp->st_gid : (gid_t) gid) != 0) (gid == -1) ? statp->st_gid : (gid_t) gid) != 0)
|| (fchmod (ofd, statp->st_mode & 07777) != 0)) { #ifdef WITH_ACL
|| (perm_copy_fd (src, ifd, dst, ofd, &ctx) != 0)
#else /* !WITH_ACL */
|| (fchmod (ofd, statp->st_mode & 07777) != 0)
#endif /* !WITH_ACL */
#ifdef WITH_ATTR
/*
* If the third parameter is NULL, all extended attributes
* except those that define Access Control Lists are copied.
* ACLs are excluded by default because copying them between
* file systems with and without ACL support needs some
* additional logic so that no unexpected permissions result.
*/
|| (attr_copy_fd (src, ifd, dst, ofd, NULL, &ctx) != 0)
#endif /* WITH_ATTR */
) {
(void) close (ifd); (void) close (ifd);
return -1; return -1;
} }

View File

@ -273,6 +273,9 @@
<filename>/etc/default/useradd</filename> or, by default, <filename>/etc/default/useradd</filename> or, by default,
<filename>/etc/skel</filename>. <filename>/etc/skel</filename>.
</para> </para>
<para>
If possible, the ACLs and extended attributes are copied.
</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>

View File

@ -223,6 +223,11 @@
This option is only valid in combination with the This option is only valid in combination with the
<option>-d</option> (or <option>--home</option>) option. <option>-d</option> (or <option>--home</option>) option.
</para> </para>
<para>
<command>usermod</command> will try to adapt the ownership of the
files and to copy the modes, ACL and extended attributes, but
manual changes might be needed afterwards.
</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>

View File

@ -106,9 +106,9 @@ su_SOURCES = \
suauth.c suauth.c
su_LDADD = $(LDADD) $(LIBPAM) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) su_LDADD = $(LDADD) $(LIBPAM) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD)
sulogin_LDADD = $(LDADD) $(LIBCRYPT) sulogin_LDADD = $(LDADD) $(LIBCRYPT)
useradd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) useradd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBACL)
userdel_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) userdel_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX)
usermod_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) usermod_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBACL)
vipw_LDADD = $(LDADD) $(LIBSELINUX) vipw_LDADD = $(LDADD) $(LIBSELINUX)
install-am: all-am install-am: all-am