#define DLOG_INIT "LOG_INIT"
/* local function prototypes */
-NORETURN static void fail_exit (int);
+NORETURN static void fail_exit (int, bool);
static void get_defaults (struct option_flags *);
static void show_defaults (void);
static int set_defaults (void);
static int get_groups (char *, struct option_flags *);
-static struct group * get_local_group (char * grp_name);
+static struct group * get_local_group (char * grp_name, bool process_selinux);
NORETURN static void usage (int status);
static void new_pwent (struct passwd *);
static void new_spent (struct spwd *);
-static void grp_update (void);
+static void grp_update (bool);
static void process_flags (int argc, char **argv, struct option_flags *flags);
static void close_files (struct option_flags *flags);
static void close_group_files (bool process_selinux);
static void unlock_group_files (bool process_selinux);
-static void open_files (void);
-static void open_group_files (void);
-static void open_shadow (void);
+static void open_files (bool process_selinux);
+static void open_group_files (bool process_selinux);
+static void open_shadow (bool process_selinux);
static void faillog_reset (uid_t);
#ifdef ENABLE_LASTLOG
static void lastlog_reset (uid_t);
#endif /* ENABLE_LASTLOG */
static void tallylog_reset (const char *);
-static void usr_update (unsigned long subuid_count, unsigned long subgid_count);
+static void usr_update (unsigned long subuid_count, unsigned long subgid_count,
+ struct option_flags *flags);
static void create_home (struct option_flags *flags);
static void create_mail (struct option_flags *flags);
static void check_uid_range(int rflg, uid_t user_id);
/*
* fail_exit - undo as much as possible
*/
-static void fail_exit (int code)
+static void fail_exit (int code, bool process_selinux)
{
#ifdef WITH_AUDIT
int type;
SYSLOG((LOG_ERR, "failed to remove %s", prefix_user_home));
}
- if (spw_locked && spw_unlock(true) == 0) {
+ if (spw_locked && spw_unlock(process_selinux) == 0) {
fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname());
SYSLOG((LOG_ERR, "failed to unlock %s", spw_dbname()));
/* continue */
}
- if (pw_locked && pw_unlock(true) == 0) {
+ if (pw_locked && pw_unlock(process_selinux) == 0) {
fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname());
SYSLOG((LOG_ERR, "failed to unlock %s", pw_dbname()));
/* continue */
}
- if (gr_locked && gr_unlock(true) == 0) {
+ if (gr_locked && gr_unlock(process_selinux) == 0) {
fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname());
SYSLOG((LOG_ERR, "failed to unlock %s", gr_dbname()));
/* continue */
}
#ifdef SHADOWGRP
- if (sgr_locked && sgr_unlock(true) == 0) {
+ if (sgr_locked && sgr_unlock(process_selinux) == 0) {
fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname());
SYSLOG((LOG_ERR, "failed to unlock %s", sgr_dbname()));
/* continue */
}
#endif
#ifdef ENABLE_SUBIDS
- if (sub_uid_locked && sub_uid_unlock(true) == 0) {
+ if (sub_uid_locked && sub_uid_unlock(process_selinux) == 0) {
fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname());
SYSLOG((LOG_ERR, "failed to unlock %s", sub_uid_dbname()));
/* continue */
}
- if (sub_gid_locked && sub_gid_unlock(true) == 0) {
+ if (sub_gid_locked && sub_gid_unlock(process_selinux) == 0) {
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname());
SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname()));
/* continue */
/*
* Open the group files
*/
- open_group_files ();
+ open_group_files (process_selinux);
/*
* So long as there is some data to be converted, strip off
* Names starting with digits are treated as numerical
* GID values, otherwise the string is looked up as is.
*/
- grp = get_local_group(g);
+ grp = get_local_group(g, process_selinux);
/*
* There must be a match, either by GID value or by
* If the name exists the group information is returned, otherwise NULL is
* returned.
*/
-static struct group * get_local_group(char * grp_name)
+static struct group * get_local_group(char * grp_name, bool process_selinux)
{
gid_t gid;
struct group *result_grp = NULL;
fprintf (stderr,
_("%s: Out of memory. Cannot find group '%s'.\n"),
Prog, grp_name);
- fail_exit (E_GRP_UPDATE);
+ fail_exit (E_GRP_UPDATE, process_selinux);
}
}
* close_files() should be called afterwards to commit the changes
* and unlocking the group files.
*/
-static void grp_update (void)
+static void grp_update (bool process_selinux)
{
const struct group *grp;
struct group *ngrp;
_("%s: Out of memory. Cannot update %s.\n"),
Prog, gr_dbname ());
SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", gr_dbname (), user_name));
- fail_exit (E_GRP_UPDATE); /* XXX */
+ fail_exit (E_GRP_UPDATE, process_selinux); /* XXX */
}
/*
_("%s: failed to prepare the new %s entry '%s'\n"),
Prog, gr_dbname (), ngrp->gr_name);
SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", gr_dbname (), user_name));
- fail_exit (E_GRP_UPDATE);
+ fail_exit (E_GRP_UPDATE, process_selinux);
}
#ifdef WITH_AUDIT
audit_logger_with_group (AUDIT_USER_MGMT,
_("%s: Out of memory. Cannot update %s.\n"),
Prog, sgr_dbname ());
SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", sgr_dbname (), user_name));
- fail_exit (E_GRP_UPDATE); /* XXX */
+ fail_exit (E_GRP_UPDATE, process_selinux); /* XXX */
}
/*
Prog, sgr_dbname (), nsgrp->sg_namp);
SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", sgr_dbname (), user_name));
- fail_exit (E_GRP_UPDATE);
+ fail_exit (E_GRP_UPDATE, process_selinux);
}
#ifdef WITH_AUDIT
audit_logger_with_group (AUDIT_USER_MGMT,
if (pw_close (process_selinux) == 0) {
fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ());
SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ()));
- fail_exit (E_PW_UPDATE);
+ fail_exit (E_PW_UPDATE, process_selinux);
}
if (is_shadow_pwd && (spw_close (process_selinux) == 0)) {
fprintf (stderr,
_("%s: failure while writing changes to %s\n"), Prog, spw_dbname ());
SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ()));
- fail_exit (E_PW_UPDATE);
+ fail_exit (E_PW_UPDATE, process_selinux);
}
close_group_files (process_selinux);
fprintf (stderr,
_("%s: failure while writing changes to %s\n"), Prog, sub_uid_dbname ());
SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ()));
- fail_exit (E_SUB_UID_UPDATE);
+ fail_exit (E_SUB_UID_UPDATE, process_selinux);
}
if (is_sub_gid && (sub_gid_close (process_selinux) == 0)) {
fprintf (stderr,
_("%s: failure while writing changes to %s\n"), Prog, sub_gid_dbname ());
SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_gid_dbname ()));
- fail_exit (E_SUB_GID_UPDATE);
+ fail_exit (E_SUB_GID_UPDATE, process_selinux);
}
#endif /* ENABLE_SUBIDS */
if (is_shadow_pwd) {
_("%s: failure while writing changes to %s\n"),
Prog, gr_dbname());
SYSLOG((LOG_ERR, "failure while writing changes to %s", gr_dbname()));
- fail_exit(E_GRP_UPDATE);
+ fail_exit(E_GRP_UPDATE, process_selinux);
}
#ifdef SHADOWGRP
if (is_shadow_grp && sgr_close(process_selinux) == 0) {
_("%s: failure while writing changes to %s\n"),
Prog, sgr_dbname());
SYSLOG((LOG_ERR, "failure while writing changes to %s", sgr_dbname()));
- fail_exit(E_GRP_UPDATE);
+ fail_exit(E_GRP_UPDATE, process_selinux);
}
#endif /* SHADOWGRP */
}
*
* open_files() opens the two password files.
*/
-static void open_files (void)
+static void open_files (bool process_selinux)
{
if (pw_lock () == 0) {
fprintf (stderr,
pw_locked = true;
if (pw_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ());
- fail_exit (E_PW_UPDATE);
+ fail_exit (E_PW_UPDATE, process_selinux);
}
/* shadow file will be opened by open_shadow(); */
- open_group_files ();
+ open_group_files (process_selinux);
#ifdef ENABLE_SUBIDS
if (is_sub_uid) {
fprintf (stderr,
_("%s: cannot lock %s; try again later.\n"),
Prog, sub_uid_dbname ());
- fail_exit (E_SUB_UID_UPDATE);
+ fail_exit (E_SUB_UID_UPDATE, process_selinux);
}
sub_uid_locked = true;
if (sub_uid_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sub_uid_dbname ());
- fail_exit (E_SUB_UID_UPDATE);
+ fail_exit (E_SUB_UID_UPDATE, process_selinux);
}
}
if (is_sub_gid) {
fprintf (stderr,
_("%s: cannot lock %s; try again later.\n"),
Prog, sub_gid_dbname ());
- fail_exit (E_SUB_GID_UPDATE);
+ fail_exit (E_SUB_GID_UPDATE, process_selinux);
}
sub_gid_locked = true;
if (sub_gid_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sub_gid_dbname ());
- fail_exit (E_SUB_GID_UPDATE);
+ fail_exit (E_SUB_GID_UPDATE, process_selinux);
}
}
#endif /* ENABLE_SUBIDS */
}
-static void open_group_files (void)
+static void open_group_files (bool process_selinux)
{
if (gr_lock () == 0) {
fprintf (stderr,
_("%s: cannot lock %s; try again later.\n"),
Prog, gr_dbname ());
- fail_exit (E_GRP_UPDATE);
+ fail_exit (E_GRP_UPDATE, process_selinux);
}
gr_locked = true;
if (gr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ());
- fail_exit (E_GRP_UPDATE);
+ fail_exit (E_GRP_UPDATE, process_selinux);
}
#ifdef SHADOWGRP
fprintf (stderr,
_("%s: cannot lock %s; try again later.\n"),
Prog, sgr_dbname ());
- fail_exit (E_GRP_UPDATE);
+ fail_exit (E_GRP_UPDATE, process_selinux);
}
sgr_locked = true;
if (sgr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sgr_dbname ());
- fail_exit (E_GRP_UPDATE);
+ fail_exit (E_GRP_UPDATE, process_selinux);
}
}
#endif /* SHADOWGRP */
}
-static void open_shadow (void)
+static void open_shadow (bool process_selinux)
{
if (!is_shadow_pwd) {
return;
fprintf (stderr,
_("%s: cannot lock %s; try again later.\n"),
Prog, spw_dbname ());
- fail_exit (E_PW_UPDATE);
+ fail_exit (E_PW_UPDATE, process_selinux);
}
spw_locked = true;
if (spw_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, spw_dbname ());
- fail_exit (E_PW_UPDATE);
+ fail_exit (E_PW_UPDATE, process_selinux);
}
}
* grp_add() writes the new records to the group files.
*/
-static void grp_add (void)
+static void grp_add (bool process_selinux)
{
struct group grp;
grp.gr_name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
- fail_exit (E_GRP_UPDATE);
+ fail_exit (E_GRP_UPDATE, process_selinux);
}
#ifdef SHADOWGRP
/*
grp.gr_name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
- fail_exit (E_GRP_UPDATE);
+ fail_exit (E_GRP_UPDATE, process_selinux);
}
#endif /* SHADOWGRP */
SYSLOG ((LOG_INFO, "new group: name=%s, GID=%u", user_name, user_gid));
* usr_update() creates the password file entries for this user
* and will update the group entries if required.
*/
-static void usr_update (unsigned long subuid_count, unsigned long subgid_count)
+static void
+usr_update (unsigned long subuid_count, unsigned long subgid_count,
+ struct option_flags *flags)
{
struct passwd pwent;
struct spwd spent;
char *tty;
+ bool process_selinux;
+
+ process_selinux = !flags->chroot && !flags->prefix;
/*
* Fill in the password structure with any new fields, making
fprintf (stderr,
_("%s: failed to prepare the new %s entry '%s'\n"),
Prog, pw_dbname (), pwent.pw_name);
- fail_exit (E_PW_UPDATE);
+ fail_exit (E_PW_UPDATE, process_selinux);
}
/*
fprintf (stderr,
_("%s: failed to prepare the new %s entry '%s'\n"),
Prog, spw_dbname (), spent.sp_namp);
- fail_exit (E_PW_UPDATE);
+ fail_exit (E_PW_UPDATE, process_selinux);
}
#ifdef ENABLE_SUBIDS
if (is_sub_uid && !local_sub_uid_assigned(user_name) &&
fprintf (stderr,
_("%s: failed to prepare the new %s entry\n"),
Prog, sub_uid_dbname ());
- fail_exit (E_SUB_UID_UPDATE);
+ fail_exit (E_SUB_UID_UPDATE, process_selinux);
}
if (is_sub_gid && !local_sub_gid_assigned(user_name) &&
(sub_gid_add(user_name, sub_gid_start, subgid_count) == 0)) {
fprintf (stderr,
_("%s: failed to prepare the new %s entry\n"),
Prog, sub_uid_dbname ());
- fail_exit (E_SUB_GID_UPDATE);
+ fail_exit (E_SUB_GID_UPDATE, process_selinux);
}
#endif /* ENABLE_SUBIDS */
* Do any group file updates for this user.
*/
if (do_grp_update) {
- grp_update ();
+ grp_update (process_selinux);
}
}
fprintf(stderr,
_("%s: error while duplicating string %s\n"),
Prog, user_home);
- fail_exit(E_HOMEDIR);
+ fail_exit(E_HOMEDIR, process_selinux);
}
#ifdef WITH_SELINUX
fprintf(stderr,
_("%s: cannot set SELinux context for home directory %s\n"),
Prog, user_home);
- fail_exit(E_HOMEDIR);
+ fail_exit(E_HOMEDIR, process_selinux);
}
}
#endif
fprintf(stderr,
_("%s: error while duplicating string in BTRFS check %s\n"),
Prog, path);
- fail_exit(E_HOMEDIR);
+ fail_exit(E_HOMEDIR, process_selinux);
}
stpcpy(&btrfs_check[strlen(path) - strlen(cp) - 1], "");
if (is_btrfs(btrfs_check) <= 0) {
fprintf(stderr,
_("%s: home directory \"%s\" must be mounted on BTRFS\n"),
Prog, path);
- fail_exit(E_HOMEDIR);
+ fail_exit(E_HOMEDIR, process_selinux);
}
free(btrfs_check);
// make subvolume to mount for user instead of directory
fprintf(stderr,
_("%s: failed to create BTRFS subvolume: %s\n"),
Prog, path);
- fail_exit(E_HOMEDIR);
+ fail_exit(E_HOMEDIR, process_selinux);
}
}
else
if (mkdir(path, 0) != 0) {
fprintf(stderr, _("%s: cannot create directory %s\n"),
Prog, path);
- fail_exit(E_HOMEDIR);
+ fail_exit(E_HOMEDIR, process_selinux);
}
if (chown(path, 0, 0) < 0) {
fprintf(stderr,
fprintf(stderr,
_("%s: cannot reset SELinux file creation context\n"),
Prog);
- fail_exit(E_HOMEDIR);
+ fail_exit(E_HOMEDIR, process_selinux);
}
}
#endif
struct group *gr;
bool process_selinux;
+ process_selinux = !flags->chroot && !flags->prefix;
+
if (!strcaseeq(create_mail_spool, "yes"))
return;
fprintf(stderr,
_("%s: cannot set SELinux context for mailbox file %s\n"),
Prog, file);
- fail_exit(E_MAILBOXFILE);
+ fail_exit(E_MAILBOXFILE, process_selinux);
}
}
#endif
fprintf(stderr,
_("%s: cannot reset SELinux file creation context\n"),
Prog);
- fail_exit(E_MAILBOXFILE);
+ fail_exit(E_MAILBOXFILE, process_selinux);
}
}
#endif
unsigned long subuid_count = 0;
unsigned long subgid_count = 0;
struct option_flags flags;
+ bool process_selinux;
log_set_progname(Prog);
log_set_logfd(stderr);
get_defaults (&flags);
process_flags (argc, argv, &flags);
+ process_selinux = !flags.chroot && !flags.prefix;
#ifdef ENABLE_SUBIDS
uid_min = getdef_ulong ("UID_MIN", 1000UL);
fprintf (stderr,
_("%s: Cannot determine your user name.\n"),
Prog);
- fail_exit (1);
+ fail_exit (1, process_selinux);
}
retval = pam_start (Prog, pampw?pampw->pw_name:"root", &conv, &pamh);
if (NULL != pamh) {
(void) pam_end (pamh, retval);
}
- fail_exit (1);
+ fail_exit (1, process_selinux);
}
(void) pam_end (pamh, retval);
#endif /* USE_PAM */
*/
if (prefix_getpwnam (user_name) != NULL) { /* local, no need for xgetpwnam */
fprintf (stderr, _("%s: user '%s' already exists\n"), Prog, user_name);
- fail_exit (E_NAME_IN_USE);
+ fail_exit (E_NAME_IN_USE, process_selinux);
}
/*
fprintf (stderr,
_("%s: group %s exists - if you want to add this user to that group, use -g.\n"),
Prog, user_name);
- fail_exit (E_NAME_IN_USE);
+ fail_exit (E_NAME_IN_USE, process_selinux);
}
}
* - flush nscd caches for passwd and group services,
* - then close and update the files.
*/
- open_files ();
+ open_files (process_selinux);
if (!oflg) {
/* first, seek for a valid uid to use for this user.
if (!uflg) {
if (find_new_uid (rflg, &user_id, NULL) < 0) {
fprintf (stderr, _("%s: can't create user\n"), Prog);
- fail_exit (E_UID_IN_USE);
+ fail_exit (E_UID_IN_USE, process_selinux);
}
} else {
if (prefix_getpwuid (user_id) != NULL) {
fprintf (stderr,
_("%s: UID %lu is not unique\n"),
Prog, (unsigned long) user_id);
- fail_exit (E_UID_IN_USE);
+ fail_exit (E_UID_IN_USE, process_selinux);
}
}
}
fprintf (stderr,
_("%s: Failed to create tcb directory for %s\n"),
Prog, user_name);
- fail_exit (E_UID_IN_USE);
+ fail_exit (E_UID_IN_USE, process_selinux);
}
}
#endif
- open_shadow ();
+ open_shadow (process_selinux);
/* do we have to add a group for that user? This is why we need to
* open the group files in the open_files() function --gafton */
fprintf (stderr,
_("%s: can't create group\n"),
Prog);
- fail_exit (4);
+ fail_exit (4, process_selinux);
}
- grp_add ();
+ grp_add (process_selinux);
}
#ifdef ENABLE_SUBIDS
fprintf (stderr,
_("%s: can't create subordinate user IDs\n"),
Prog);
- fail_exit(E_SUB_UID_UPDATE);
+ fail_exit(E_SUB_UID_UPDATE, process_selinux);
}
}
if (is_sub_gid && subgid_count != 0) {
fprintf (stderr,
_("%s: can't create subordinate group IDs\n"),
Prog);
- fail_exit(E_SUB_GID_UPDATE);
+ fail_exit(E_SUB_GID_UPDATE, process_selinux);
}
}
#endif /* ENABLE_SUBIDS */
- usr_update (subuid_count, subgid_count);
+ usr_update (subuid_count, subgid_count, &flags);
close_files (&flags);
"add-selinux-user-mapping",
user_name, user_id, SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
- fail_exit (E_SE_UPDATE);
+ fail_exit (E_SE_UPDATE, process_selinux);
}
}
#endif /* WITH_SELINUX */