* NEWS, src/userdel.c, man/userdel.8.xml: Add option -Z/--selinux-user.

* libmisc/system.c, lib/prototypes.h, libmisc/Makefile.am: Removed
	safe_system().
	* lib/selinux.c, po/POTFILES.in, lib/prototypes.h,
	lib/Makefile.am: Added helper functions for semanage.
	* README, src/useradd.c, src/usermod.c, src/userdel.c,
	configure.in: Use libsemanage instead of semanage.
This commit is contained in:
nekral-guest 2011-11-17 21:51:07 +00:00
parent f3ef11056f
commit 29050eadb5
15 changed files with 519 additions and 195 deletions

View File

@ -1,3 +1,13 @@
2011-11-16 Peter Vrabec <pvrabec@redhat.com>
* NEWS, src/userdel.c, man/userdel.8.xml: Add option -Z/--selinux-user.
* libmisc/system.c, lib/prototypes.h, libmisc/Makefile.am: Removed
safe_system().
* lib/selinux.c, po/POTFILES.in, lib/prototypes.h,
lib/Makefile.am: Added helper functions for semanage.
* README, src/useradd.c, src/usermod.c, src/userdel.c,
configure.in: Use libsemanage instead of semanage.
2011-11-16 Peter Vrabec <pvrabec@redhat.com>
* src/Makefile.am: useradd may need the LIBATTR library.

1
NEWS
View File

@ -97,6 +97,7 @@ shadow-4.1.4.3 -> shadow-4.1.5 UNRELEASED
* Do not remove a group with the same name as the user (usergroup) if
this group isn't the user's primary group.
* Add --root option.
* Add --selinux-user option.
- usermod
* Accept options in any order (username not necessarily at the end)
* When the shadow file exists but there are no shadow entries, an entry

4
README
View File

@ -37,7 +37,7 @@ S/Key support:
Authors and contributors
========================
Thanks to at least the following people for sending me patches, bug
Thanks to at least the following people for sending patches, bug
reports and various comments. This list may be incomplete, I received
a lot of mail...
@ -69,6 +69,7 @@ Greg Mortensen <loki@world.std.com>
Guido van Rooij
Guy Maor <maor@debian.org>
Hrvoje Dogan <hdogan@bjesomar.srce.hr>
Jakub Hrozek <jhrozek@redhat.com>
Janos Farkas <chexum@bankinf.banki.hu>
Jay Soffian <jay@lw.net>
Jesse Thilo <Jesse.Thilo@pobox.com>
@ -96,6 +97,7 @@ Mike Pakovic <mpakovic@users.southeast.net>
Nicolas François <nicolas.francois@centraliens.net>
Nikos Mavroyanopoulos <nmav@i-net.paiko.gr>
Pavel Machek <pavel@bug.ucw.cz>
Peter Vrabec <pvrabec@redhat.com>
Phillip Street
Rafał Maszkowski <rzm@icm.edu.pl>
Rani Chouha <ranibey@smartec.com>

View File

@ -422,22 +422,37 @@ if test "$with_libcrack" = "yes"; then
fi
AC_SUBST(LIBSELINUX)
AC_SUBST(LIBSEMANAGE)
if test "$with_selinux" != "no"; then
AC_CHECK_HEADERS(selinux/selinux.h, [selinux_header="yes"], [selinux_header="no"])
if test "$selinux_header$with_selinux" = "noyes" ; then
AC_MSG_ERROR([selinux/selinux.h is missing])
elif test "$selinux_header" = "yes" ; then
AC_CHECK_LIB(selinux, is_selinux_enabled,
[selinux_lib="yes"], [selinux_lib="no"])
fi
AC_CHECK_HEADERS(semanage/semanage.h, [semanage_header="yes"], [semanage_header="no"])
if test "$semanage_header$with_selinux" = "noyes" ; then
AC_MSG_ERROR([semanage/semanage.h is missing])
fi
if test "$selinux_header$semanage_header" = "yesyes" ; then
AC_CHECK_LIB(selinux, is_selinux_enabled, [selinux_lib="yes"], [selinux_lib="no"])
if test "$selinux_lib$with_selinux" = "noyes" ; then
AC_MSG_ERROR([libselinux not found])
elif test "$selinux_lib" = "no" ; then
with_selinux="no"
else
fi
AC_CHECK_LIB(semanage, semanage_connect, [semanage_lib="yes"], [semanage_lib="no"])
if test "$semanage_lib$with_selinux" = "noyes" ; then
AC_MSG_ERROR([libsemanage not found])
fi
if test "$selinux_lib$semanage_lib" == "yesyes" ; then
AC_DEFINE(WITH_SELINUX, 1,
[Build shadow with SELinux support])
LIBSELINUX="-lselinux"
LIBSEMANAGE="-lsemanage"
with_selinux="yes"
else
with_selinux="no"
fi
else
with_selinux="no"

View File

@ -39,6 +39,7 @@ libshadow_la_SOURCES = \
pwio.c \
pwio.h \
pwmem.c \
selinux.c \
sgetgrent.c \
sgetpwent.c \
sgetspent.c \

View File

@ -297,6 +297,10 @@ extern void process_root_flag (const char* short_opt, int argc, char **argv);
/* salt.c */
extern /*@observer@*/const char *crypt_make_salt (/*@null@*//*@observer@*/const char *meth, /*@null@*/void *arg);
/* selinux.c */
int set_seuser(const char *login_name, const char *seuser_name);
int del_seuser(const char *login_name);
/* setugid.c */
extern int setup_groups (const struct passwd *info);
extern int change_uid (const struct passwd *info);
@ -345,12 +349,6 @@ extern int shell (const char *file, /*@null@*/const char *arg, char *const envp[
extern int run_command (const char *cmd, const char *argv[],
/*@null@*/const char *envp[], /*@out@*/int *status);
/* system.c */
extern int safe_system (const char *command,
const char *argv[],
/*@null@*/const char *env[],
bool ignore_stderr);
/* strtoday.c */
extern long strtoday (const char *);

374
lib/selinux.c Normal file
View File

@ -0,0 +1,374 @@
/*
* Copyright (c) 2010 , Jakub Hrozek <jhrozek@redhat.com>
* Copyright (c) 2011 , Peter Vrabec <pvrabec@redhat.com>
* 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.
*/
#include <config.h>
#ifdef WITH_SELINUX
#include "defines.h"
#include <stdio.h>
#include <stdarg.h>
#include <selinux/selinux.h>
#include <semanage/semanage.h>
#ifndef DEFAULT_SERANGE
#define DEFAULT_SERANGE "s0"
#endif
static void semanage_error_callback (void *varg,
semanage_handle_t *handle,
const char *fmt, ...)
{
int ret;
char * message = NULL;
va_list ap;
va_start (ap, fmt);
ret = vasprintf (&message, fmt, ap);
va_end (ap);
if (ret < 0) {
/* ENOMEM */
return;
}
switch (semanage_msg_get_level (handle)) {
case SEMANAGE_MSG_ERR:
case SEMANAGE_MSG_WARN:
fprintf (stderr, _("[libsemanage]: %s\n"), message);
break;
case SEMANAGE_MSG_INFO:
/* nop */
break;
}
free (message);
}
static semanage_handle_t *semanage_init (void)
{
int ret;
semanage_handle_t *handle = NULL;
handle = semanage_handle_create ();
if (NULL == handle) {
fprintf (stderr,
_("Cannot create SELinux management handle\n"));
return NULL;
}
semanage_msg_set_callback (handle, semanage_error_callback, NULL);
ret = semanage_is_managed (handle);
if (ret != 1) {
fprintf (stderr, _("SELinux policy not managed\n"));
goto fail;
}
ret = semanage_access_check (handle);
if (ret < SEMANAGE_CAN_READ) {
fprintf (stderr, _("Cannot read SELinux policy store\n"));
goto fail;
}
ret = semanage_connect (handle);
if (ret != 0) {
fprintf (stderr,
_("Cannot establish SELinux management connection\n"));
goto fail;
}
ret = semanage_begin_transaction (handle);
if (ret != 0) {
fprintf (stderr, _("Cannot begin SELinux transaction\n"));
goto fail;
}
return handle;
fail:
semanage_handle_destroy (handle);
return NULL;
}
static int semanage_user_mod (semanage_handle_t *handle,
semanage_seuser_key_t *key,
const char *login_name,
const char *seuser_name)
{
int ret;
semanage_seuser_t *seuser = NULL;
semanage_seuser_query (handle, key, &seuser);
if (NULL == seuser) {
fprintf (stderr,
_("Could not query seuser for %s\n"), login_name);
ret = 1;
goto done;
}
ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE);
if (ret != 0) {
fprintf (stderr,
_("Could not set serange for %s\n"), login_name);
ret = 1;
goto done;
}
ret = semanage_seuser_set_sename (handle, seuser, seuser_name);
if (ret != 0) {
fprintf (stderr,
_("Could not set sename for %s\n"),
login_name);
ret = 1;
goto done;
}
ret = semanage_seuser_modify_local (handle, key, seuser);
if (ret != 0) {
fprintf (stderr,
_("Could not modify login mapping for %s\n"),
login_name);
ret = 1;
goto done;
}
ret = 0;
done:
semanage_seuser_free (seuser);
return ret;
}
static int semanage_user_add (semanage_handle_t *handle,
semanage_seuser_key_t *key,
const char *login_name,
const char *seuser_name)
{
int ret;
semanage_seuser_t *seuser = NULL;
ret = semanage_seuser_create (handle, &seuser);
if (ret != 0) {
fprintf (stderr,
_("Cannot create SELinux login mapping for %s\n"),
login_name);
ret = 1;
goto done;
}
ret = semanage_seuser_set_name (handle, seuser, login_name);
if (ret != 0) {
fprintf (stderr, _("Could not set name for %s\n"), login_name);
ret = 1;
goto done;
}
ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE);
if (ret != 0) {
fprintf (stderr,
_("Could not set serange for %s\n"),
login_name);
ret = 1;
goto done;
}
ret = semanage_seuser_set_sename (handle, seuser, seuser_name);
if (ret != 0) {
fprintf (stderr,
_("Could not set SELinux user for %s\n"),
login_name);
ret = 1;
goto done;
}
ret = semanage_seuser_modify_local (handle, key, seuser);
if (ret != 0) {
fprintf (stderr,
_("Could not add login mapping for %s\n"),
login_name);
ret = 1;
goto done;
}
ret = 0;
done:
semanage_seuser_free (seuser);
return ret;
}
int set_seuser (const char *login_name, const char *seuser_name)
{
semanage_handle_t *handle = NULL;
semanage_seuser_key_t *key = NULL;
int ret;
int seuser_exists = 0;
if (NULL == seuser_name) {
/* don't care, just let system pick the defaults */
return 0;
}
handle = semanage_init ();
if (NULL == handle) {
fprintf (stderr, _("Cannot init SELinux management\n"));
ret = 1;
goto done;
}
ret = semanage_seuser_key_create (handle, login_name, &key);
if (ret != 0) {
fprintf (stderr, _("Cannot create SELinux user key\n"));
ret = 1;
goto done;
}
ret = semanage_seuser_exists (handle, key, &seuser_exists);
if (ret < 0) {
fprintf (stderr, _("Cannot verify the SELinux user\n"));
ret = 1;
goto done;
}
if (0 != seuser_exists) {
ret = semanage_user_mod (handle, key, login_name, seuser_name);
if (ret != 0) {
fprintf (stderr,
_("Cannot modify SELinux user mapping\n"));
ret = 1;
goto done;
}
} else {
ret = semanage_user_add (handle, key, login_name, seuser_name);
if (ret != 0) {
fprintf (stderr,
_("Cannot add SELinux user mapping\n"));
ret = 1;
goto done;
}
}
ret = semanage_commit (handle);
if (ret < 0) {
fprintf (stderr, _("Cannot commit SELinux transaction\n"));
ret = 1;
goto done;
}
ret = 0;
done:
semanage_seuser_key_free (key);
semanage_handle_destroy (handle);
return ret;
}
int del_seuser (const char *login_name)
{
semanage_handle_t *handle = NULL;
semanage_seuser_key_t *key = NULL;
int ret;
int exists = 0;
handle = semanage_init ();
if (NULL == handle) {
fprintf (stderr, _("Cannot init SELinux management\n"));
ret = 1;
goto done;
}
ret = semanage_seuser_key_create (handle, login_name, &key);
if (ret != 0) {
fprintf (stderr, _("Cannot create SELinux user key\n"));
ret = 1;
goto done;
}
ret = semanage_seuser_exists (handle, key, &exists);
if (ret < 0) {
fprintf (stderr, _("Cannot verify the SELinux user\n"));
ret = 1;
goto done;
}
if (0 == exists) {
fprintf (stderr,
_("Login mapping for %s is not defined, OK if default mapping was used\n"),
login_name);
ret = 0; /* probably default mapping */
goto done;
}
ret = semanage_seuser_exists_local (handle, key, &exists);
if (ret < 0) {
fprintf (stderr, _("Cannot verify the SELinux user\n"));
ret = 1;
goto done;
}
if (0 == exists) {
fprintf (stderr,
_("Login mapping for %s is defined in policy, cannot be deleted\n"),
login_name);
ret = 0; /* Login mapping defined in policy can't be deleted */
goto done;
}
ret = semanage_seuser_del_local (handle, key);
if (ret != 0) {
fprintf (stderr,
_("Could not delete login mapping for %s"),
login_name);
ret = 1;
goto done;
}
ret = semanage_commit (handle);
if (ret < 0) {
fprintf (stderr, _("Cannot commit SELinux transaction\n"));
ret = 1;
goto done;
}
ret = 0;
done:
semanage_handle_destroy (handle);
return ret;
}
#else /* !WITH_SELINUX */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* !WITH_SELINUX */

View File

@ -50,7 +50,6 @@ libmisc_a_SOURCES = \
setugid.c \
setupenv.c \
shell.c \
system.c \
strtoday.c \
sub.c \
sulog.c \

View File

@ -1,79 +0,0 @@
/*
* Copyright (c) 2009 , Dan Walsh <dwalsh@redhat.com>
* Copyright (c) 2010 , 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.
*/
#include <config.h>
#ident "$Id$"
#include <stdio.h>
#include <sys/wait.h>
#include <fcntl.h>
#include "prototypes.h"
#include "defines.h"
int safe_system (const char *command,
const char *argv[],
/*@null@*/const char *env[],
bool ignore_stderr)
{
int status = -1;
int fd;
pid_t pid;
pid = fork();
if (pid < 0) {
return -1;
}
if (pid != 0) { /* Parent */
if (waitpid (pid, &status, 0) > 0) {
return status;
} else {
return -1;
}
}
fd = open ("/dev/null", O_RDWR);
/* Child */
/* Close Stdin */
if (dup2 (fd, 0) == -1) {
exit (EXIT_FAILURE);
}
if (ignore_stderr) {
/* Close Stderr */
if (dup2 (fd, 2) == -1) {
exit (EXIT_FAILURE);
}
}
(void) execve (command, (char *const *) argv, (char *const *) env);
(void) fprintf (stderr, _("Failed to exec '%s'\n"), argv[0]);
exit (EXIT_FAILURE);
}

View File

@ -136,6 +136,16 @@
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-Z</option>, <option>--selinux-user</option>
</term>
<listitem>
<para>
Remove any SELinux user mapping for the user's login.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -17,6 +17,7 @@ lib/port.c
lib/pwauth.c
lib/pwio.c
lib/pwmem.c
lib/selinux.c
lib/sgetgrent.c
lib/sgetpwent.c
lib/sgetspent.c

View File

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

View File

@ -112,7 +112,7 @@ static const char *user_shell = "";
static const char *create_mail_spool = "";
#ifdef WITH_SELINUX
static const char *user_selinux = "";
#endif
#endif /* WITH_SELINUX */
static long user_expire = -1;
static bool is_shadow_pwd;
@ -145,6 +145,9 @@ static bool
oflg = false, /* permit non-unique user ID to be specified with -u */
rflg = false, /* create a system account */
sflg = false, /* shell program for new account */
#ifdef WITH_SELINUX
Zflg = false, /* new selinux user */
#endif /* WITH_SELINUX */
uflg = false, /* specify user ID for new account */
Uflg = false; /* create a group having the same name as the user */
@ -164,6 +167,7 @@ static bool home_added = false;
#define E_GRP_UPDATE 10 /* can't update group file */
#define E_HOMEDIR 12 /* can't create home directory */
#define E_MAIL_SPOOL 13 /* can't create mail spool */
#define E_SE_UPDATE 14 /* can't update SELinux user mapping */
#define DGROUP "GROUP="
#define DHOME "HOME="
@ -181,9 +185,6 @@ static int set_defaults (void);
static int get_groups (char *);
static void usage (int status);
static void new_pwent (struct passwd *);
#ifdef WITH_SELINUX
static void selinux_update_mapping (void);
#endif
static long scale_age (long);
static void new_spent (struct spwd *);
@ -730,7 +731,7 @@ static void usage (int status)
(void) fputs (_(" -U, --user-group create a group with the same name as the user\n"), usageout);
#ifdef WITH_SELINUX
(void) fputs (_(" -Z, --selinux-user SEUSER use a specific SEUSER for the SELinux user mapping\n"), usageout);
#endif
#endif /* WITH_SELINUX */
(void) fputs ("\n", usageout);
exit (status);
}
@ -1004,15 +1005,15 @@ static void process_flags (int argc, char **argv)
{"user-group", no_argument, NULL, 'U'},
#ifdef WITH_SELINUX
{"selinux-user", required_argument, NULL, 'Z'},
#endif
#endif /* WITH_SELINUX */
{NULL, 0, NULL, '\0'}
};
while ((c = getopt_long (argc, argv,
#ifdef WITH_SELINUX
"b:c:d:De:f:g:G:hk:K:lmMNop:rR:s:u:UZ:",
#else
#else /* !WITH_SELINUX */
"b:c:d:De:f:g:G:hk:K:lmMNop:rR:s:u:U",
#endif
#endif /* !WITH_SELINUX */
long_options, NULL)) != -1) {
switch (c) {
case 'b':
@ -1213,6 +1214,7 @@ static void process_flags (int argc, char **argv)
case 'Z':
if (is_selinux_enabled () > 0) {
user_selinux = optarg;
Zflg = true;
} else {
fprintf (stderr,
_("%s: -Z requires SELinux enabled kernel\n"),
@ -1221,7 +1223,7 @@ static void process_flags (int argc, char **argv)
exit (E_BAD_ARG);
}
break;
#endif
#endif /* WITH_SELINUX */
default:
usage (E_USAGE);
}
@ -1745,32 +1747,6 @@ static void usr_update (void)
}
}
#ifdef WITH_SELINUX
static void selinux_update_mapping (void) {
if (is_selinux_enabled () <= 0) return;
if ('\0' != *user_selinux) { /* must be done after passwd write() */
const char *argv[7];
argv[0] = "/usr/sbin/semanage";
argv[1] = "login";
argv[2] = "-a";
argv[3] = "-s";
argv[4] = user_selinux;
argv[5] = user_name;
argv[6] = NULL;
if (safe_system (argv[0], argv, NULL, false) != 0) {
fprintf (stderr,
_("%s: warning: the user name %s to %s SELinux user mapping failed.\n"),
Prog, user_name, user_selinux);
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_USER, Prog,
"adding SELinux user mapping",
user_name, (unsigned int) user_id, 0);
#endif
}
}
}
#endif
/*
* create_home - create the user's home directory
*
@ -2082,8 +2058,20 @@ int main (int argc, char **argv)
close_files ();
#ifdef WITH_SELINUX
selinux_update_mapping ();
#endif
if (Zflg && ('\0' != *user_selinux)) {
if (set_seuser (user_name, user_selinux) != 0) {
fprintf (stderr,
_("%s: warning: the user name %s to %s SELinux user mapping failed.\n"),
Prog, user_name, user_selinux);
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_USER, Prog,
"adding SELinux user mapping",
user_name, (unsigned int) user_id, 0);
#endif /* WITH_AUDIT */
fail_exit (E_SE_UPDATE);
}
}
#endif /* WITH_SELINUX */
nscd_flush_cache ("passwd");
nscd_flush_cache ("group");

View File

@ -74,6 +74,7 @@
#define E_USER_BUSY 8 /* user currently logged in */
#define E_GRP_UPDATE 10 /* can't update group file */
#define E_HOMEDIR 12 /* can't remove home directory */
#define E_SE_UPDATE 14 /* can't update SELinux user mapping */
/*
* Global variables
@ -87,6 +88,7 @@ static char *user_home;
static bool fflg = false;
static bool rflg = false;
static bool Zflg = false;
static bool is_shadow_pwd;
@ -134,6 +136,9 @@ static void usage (int status)
(void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
(void) fputs (_(" -r, --remove remove home directory and mail spool\n"), usageout);
(void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout);
#ifdef WITH_SELINUX
(void) fputs (_(" -Z, --selinux-user remove any SELinux user mapping for the user\n"), usageout);
#endif /* WITH_SELINUX */
(void) fputs ("\n", usageout);
exit (status);
}
@ -870,13 +875,21 @@ int main (int argc, char **argv)
*/
int c;
static struct option long_options[] = {
{"force", no_argument, NULL, 'f'},
{"help", no_argument, NULL, 'h'},
{"remove", no_argument, NULL, 'r'},
{"root", required_argument, NULL, 'R'},
{"force", no_argument, NULL, 'f'},
{"help", no_argument, NULL, 'h'},
{"remove", no_argument, NULL, 'r'},
{"root", required_argument, NULL, 'R'},
#ifdef WITH_SELINUX
{"selinux-user", no_argument, NULL, 'Z'},
#endif /* WITH_SELINUX */
{NULL, 0, NULL, '\0'}
};
while ((c = getopt_long (argc, argv, "fhrR:",
while ((c = getopt_long (argc, argv,
#ifdef WITH_SELINUX
"fhrR:Z",
#else /* !WITH_SELINUX */
"fhrR:",
#endif /* !WITH_SELINUX */
long_options, NULL)) != -1) {
switch (c) {
case 'f': /* force remove even if not owned by user */
@ -890,6 +903,19 @@ int main (int argc, char **argv)
break;
case 'R': /* no-op, handled in process_root_flag () */
break;
#ifdef WITH_SELINUX
case 'Z':
if (is_selinux_enabled () > 0) {
Zflg = true;
} else {
fprintf (stderr,
_("%s: -Z requires SELinux enabled kernel\n"),
Prog);
exit (E_BAD_ARG);
}
break;
#endif /* WITH_SELINUX */
default:
usage (E_USAGE);
}
@ -1091,14 +1117,18 @@ int main (int argc, char **argv)
#endif /* WITH_AUDIT */
#ifdef WITH_SELINUX
if (is_selinux_enabled () > 0) {
const char *args[5];
args[0] = "/usr/sbin/semanage";
args[1] = "login";
args[2] = "-d";
args[3] = user_name;
args[4] = NULL;
safe_system (args[0], args, NULL, true);
if (Zflg) {
if (del_seuser (user_name) != 0) {
fprintf (stderr,
_("%s: warning: the user name %s to SELinux user mapping removal failed.\n"),
Prog, user_name);
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_USER, Prog,
"removing SELinux user mapping",
user_name, (unsigned int) user_id, 0);
#endif /* WITH_AUDIT */
fail_exit (E_SE_UPDATE);
}
}
#endif /* WITH_SELINUX */

View File

@ -85,6 +85,7 @@
#define E_GRP_UPDATE 10 /* can't update group file */
/* #define E_NOSPACE 11 insufficient space to move home dir */
#define E_HOMEDIR 12 /* unable to complete home dir move */
#define E_SE_UPDATE 13 /* can't update SELinux user mapping */
#define VALID(s) (strcspn (s, ":\n") == strlen (s))
/*
* Global variables
@ -105,7 +106,7 @@ static char *user_newhome;
static char *user_shell;
#ifdef WITH_SELINUX
static const char *user_selinux = "";
#endif
#endif /* WITH_SELINUX */
static char *user_newshell;
static long user_expire;
static long user_newexpire;
@ -154,10 +155,6 @@ static void date_to_str (/*@unique@*//*@out@*/char *buf, size_t maxsize,
static int get_groups (char *);
static /*@noreturn@*/void usage (int status);
static void new_pwent (struct passwd *);
#ifdef WITH_SELINUX
static void selinux_update_mapping (void);
#endif
static void new_spent (struct spwd *);
static /*@noreturn@*/void fail_exit (int);
static void update_group (void);
@ -338,8 +335,8 @@ static /*@noreturn@*/void usage (int status)
(void) fputs (_(" -u, --uid UID new UID for the user account\n"), usageout);
(void) fputs (_(" -U, --unlock unlock the user account\n"), usageout);
#ifdef WITH_SELINUX
(void) fputs (_(" -Z, --selinux-user new SELinux user mapping for the user account\n"), usageout);
#endif
(void) fputs (_(" -Z, --selinux-user SEUSER new SELinux user mapping for the user account\n"), usageout);
#endif /* WITH_SELINUX */
(void) fputs ("\n", usageout);
exit (status);
}
@ -894,15 +891,15 @@ static void process_flags (int argc, char **argv)
{"unlock", no_argument, NULL, 'U'},
#ifdef WITH_SELINUX
{"selinux-user", required_argument, NULL, 'Z'},
#endif
#endif /* WITH_SELINUX */
{NULL, 0, NULL, '\0'}
};
while ((c = getopt_long (argc, argv,
#ifdef WITH_SELINUX
"ac:d:e:f:g:G:hl:Lmop:R:s:u:UZ:",
#else
#else /* !WITH_SELINUX */
"ac:d:e:f:g:G:hl:Lmop:R:s:u:U",
#endif
#endif /* !WITH_SELINUX */
long_options, NULL)) != -1) {
switch (c) {
case 'a':
@ -1033,7 +1030,7 @@ static void process_flags (int argc, char **argv)
exit (E_BAD_ARG);
}
break;
#endif
#endif /* WITH_SELINUX */
default:
usage (E_USAGE);
}
@ -1175,7 +1172,7 @@ static void process_flags (int argc, char **argv)
lflg || Gflg || gflg || fflg || eflg || dflg || cflg
#ifdef WITH_SELINUX
|| Zflg
#endif
#endif /* WITH_SELINUX */
)) {
fprintf (stderr, _("%s: no changes\n"), Prog);
exit (E_SUCCESS);
@ -1893,10 +1890,20 @@ int main (int argc, char **argv)
nscd_flush_cache ("group");
#ifdef WITH_SELINUX
if (Zflg) {
selinux_update_mapping ();
if (Zflg && *user_selinux) {
if (set_seuser (user_name, user_selinux) != 0) {
fprintf (stderr,
_("%s: warning: the user name %s to %s SELinux user mapping failed.\n"),
Prog, user_name, user_selinux);
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
"modifying User mapping ",
user_name, (unsigned int) user_id, 0);
#endif /* WITH_AUDIT */
fail_exit (E_SE_UPDATE);
}
}
#endif
#endif /* WITH_SELINUX */
if (mflg) {
move_home ();
@ -1906,7 +1913,7 @@ int main (int argc, char **argv)
if (lflg || uflg) {
move_mailbox ();
}
#endif
#endif /* NO_MOVE_MAILBOX */
if (uflg) {
update_lastlog ();
@ -1940,36 +1947,3 @@ int main (int argc, char **argv)
return E_SUCCESS;
}
#ifdef WITH_SELINUX
static void selinux_update_mapping (void) {
const char *argv[7];
if (is_selinux_enabled () <= 0) {
return;
}
if ('\0' != *user_selinux) {
argv[0] = "/usr/sbin/semanage";
argv[1] = "login";
argv[2] = "-m";
argv[3] = "-s";
argv[4] = user_selinux;
argv[5] = user_name;
argv[6] = NULL;
if (safe_system (argv[0], argv, NULL, true) != 0) {
argv[2] = "-a";
if (safe_system (argv[0], argv, NULL, false) != 0) {
fprintf (stderr,
_("%s: warning: the user name %s to %s SELinux user mapping failed.\n"),
Prog, user_name, user_selinux);
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
"modifying User mapping ",
user_name, (unsigned int) user_id, 0);
#endif
}
}
}
}
#endif