Imported Upstream version 4.2

This commit is contained in:
Christian Perrier
2014-03-01 19:59:36 +01:00
parent db1dc7288b
commit 65b471a2f2
706 changed files with 46966 additions and 139295 deletions

35
src/.gitignore vendored Normal file
View File

@@ -0,0 +1,35 @@
/chage
/chfn
/chgpasswd
/chpasswd
/chsh
/expiry
/faillog
/gpasswd
/groupadd
/groupdel
/groupmems
/groupmod
/groups
/grpck
/grpconv
/grpunconv
/id
/lastlog
/login
/logoutd
/newgrp
/newgidmap
/newuidmap
/newusers
/nologin
/passwd
/pwck
/pwconv
/pwunconv
/su
/sulogin
/useradd
/userdel
/usermod
/vipw

View File

@@ -25,6 +25,9 @@ INCLUDES = \
bin_PROGRAMS = groups login su
sbin_PROGRAMS = nologin
ubin_PROGRAMS = faillog lastlog chage chfn chsh expiry gpasswd newgrp passwd
if ENABLE_SUBIDS
ubin_PROGRAMS += newgidmap newuidmap
endif
usbin_PROGRAMS = \
chgpasswd \
chpasswd \
@@ -49,7 +52,7 @@ usbin_PROGRAMS = \
noinst_PROGRAMS = id sulogin
suidbins = su
suidubins = chage chfn chsh expiry gpasswd newgrp passwd
suidubins = chage chfn chsh expiry gpasswd newgrp passwd newuidmap newgidmap
if ACCT_TOOLS_SETUID
suidubins += chage chgpasswd chpasswd groupadd groupdel groupmod newusers useradd userdel usermod
endif
@@ -78,6 +81,8 @@ LIBCRYPT_NOPAM = $(LIBCRYPT)
endif
chage_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX)
newuidmap_LDADD = $(LDADD) $(LIBSELINUX)
newgidmap_LDADD = $(LDADD) $(LIBSELINUX)
chfn_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD)
chgpasswd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBSELINUX) $(LIBCRYPT)
chsh_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD)

File diff suppressed because it is too large Load Diff

View File

@@ -32,7 +32,7 @@
#include <config.h>
#ident "$Id: chage.c 3642 2011-11-19 21:56:10Z nekral-guest $"
#ident "$Id$"
#include <ctype.h>
#include <fcntl.h>

View File

@@ -32,7 +32,7 @@
#include <config.h>
#ident "$Id: chfn.c 3576 2011-11-13 16:24:57Z nekral-guest $"
#ident "$Id$"
#include <fcntl.h>
#include <pwd.h>

View File

@@ -32,7 +32,7 @@
#include <config.h>
#ident "$Id: chgpasswd.c 3652 2011-12-09 21:31:39Z nekral-guest $"
#ident "$Id$"
#include <fcntl.h>
#include <getopt.h>
@@ -459,6 +459,7 @@ int main (int argc, char **argv)
&& ( (NULL == crypt_method)
|| (0 != strcmp (crypt_method, "NONE")))) {
void *arg = NULL;
const char *salt;
if (md5flg) {
crypt_method = "MD5";
}
@@ -467,8 +468,14 @@ int main (int argc, char **argv)
arg = &sha_rounds;
}
#endif
cp = pw_encrypt (newpwd,
crypt_make_salt (crypt_method, arg));
salt = crypt_make_salt (crypt_method, arg);
cp = pw_encrypt (newpwd, salt);
if (NULL == cp) {
fprintf (stderr,
_("%s: failed to crypt password with salt '%s': %s\n"),
Prog, salt, strerror (errno));
fail_exit (1);
}
}
/*

View File

@@ -32,7 +32,7 @@
#include <config.h>
#ident "$Id: chpasswd.c 3652 2011-12-09 21:31:39Z nekral-guest $"
#ident "$Id$"
#include <fcntl.h>
#include <getopt.h>
@@ -482,6 +482,7 @@ int main (int argc, char **argv)
&& ( (NULL == crypt_method)
|| (0 != strcmp (crypt_method, "NONE")))) {
void *arg = NULL;
const char *salt;
if (md5flg) {
crypt_method = "MD5";
}
@@ -490,8 +491,14 @@ int main (int argc, char **argv)
arg = &sha_rounds;
}
#endif
cp = pw_encrypt (newpwd,
crypt_make_salt(crypt_method, arg));
salt = crypt_make_salt (crypt_method, arg);
cp = pw_encrypt (newpwd, salt);
if (NULL == cp) {
fprintf (stderr,
_("%s: failed to crypt password with salt '%s': %s\n"),
Prog, salt, strerror (errno));
fail_exit (1);
}
}
/*

View File

@@ -32,7 +32,7 @@
#include <config.h>
#ident "$Id: chsh.c 3640 2011-11-19 21:51:52Z nekral-guest $"
#ident "$Id$"
#include <fcntl.h>
#include <getopt.h>

View File

@@ -32,7 +32,7 @@
#include <config.h>
#ident "$Id: expiry.c 3640 2011-11-19 21:51:52Z nekral-guest $"
#ident "$Id$"
#include <pwd.h>
#include <signal.h>

View File

@@ -32,7 +32,7 @@
#include <config.h>
#ident "$Id: faillog.c 3639 2011-11-19 21:44:34Z nekral-guest $"
#ident "$Id$"
#include <getopt.h>
#include <pwd.h>

View File

@@ -32,7 +32,7 @@
#include <config.h>
#ident "$Id: gpasswd.c 3640 2011-11-19 21:51:52Z nekral-guest $"
#ident "$Id$"
#include <errno.h>
#include <fcntl.h>
@@ -898,6 +898,7 @@ static void change_passwd (struct group *gr)
char *cp;
static char pass[BUFSIZ];
int retries;
const char *salt;
/*
* A new password is to be entered and it must be encrypted, etc.
@@ -938,7 +939,14 @@ static void change_passwd (struct group *gr)
exit (1);
}
cp = pw_encrypt (pass, crypt_make_salt (NULL, NULL));
salt = crypt_make_salt (NULL, NULL);
cp = pw_encrypt (pass, salt);
if (NULL == cp) {
fprintf (stderr,
_("%s: failed to crypt password with salt '%s': %s\n"),
Prog, salt, strerror (errno));
exit (1);
}
memzero (pass, sizeof pass);
#ifdef SHADOWGRP
if (is_shadowgrp) {

View File

@@ -32,7 +32,7 @@
#include <config.h>
#ident "$Id: groupadd.c 3576 2011-11-13 16:24:57Z nekral-guest $"
#ident "$Id$"
#include <ctype.h>
#include <fcntl.h>

View File

@@ -32,7 +32,7 @@
#include <config.h>
#ident "$Id: groupdel.c 3576 2011-11-13 16:24:57Z nekral-guest $"
#ident "$Id$"
#include <ctype.h>
#include <fcntl.h>

View File

@@ -32,7 +32,7 @@
#include <config.h>
#ident "$Id: groupmod.c 3576 2011-11-13 16:24:57Z nekral-guest $"
#ident "$Id$"
#include <ctype.h>
#include <fcntl.h>

View File

@@ -32,7 +32,7 @@
#include <config.h>
#ident "$Id: groups.c 3233 2010-08-22 19:36:09Z nekral-guest $"
#ident "$Id$"
#include <grp.h>
#include <pwd.h>

View File

@@ -33,7 +33,7 @@
#include <config.h>
#ident "$Id: grpck.c 3559 2011-11-06 18:39:53Z nekral-guest $"
#ident "$Id$"
#include <fcntl.h>
#include <grp.h>

View File

@@ -36,7 +36,7 @@
*/
#include <config.h>
#ident "$Id: grpconv.c 3640 2011-11-19 21:51:52Z nekral-guest $"
#ident "$Id$"
#include <errno.h>
#include <fcntl.h>

View File

@@ -37,7 +37,7 @@
#include <config.h>
#ident "$Id: grpunconv.c 3726 2012-05-18 19:32:32Z nekral-guest $"
#ident "$Id$"
#include <stdio.h>
#include <stdlib.h>

View File

@@ -40,7 +40,7 @@
#include <config.h>
#ident "$Id: id.c 3182 2010-03-23 11:26:34Z nekral-guest $"
#ident "$Id$"
#include <grp.h>
#include <pwd.h>

View File

@@ -32,7 +32,7 @@
#include <config.h>
#ident "$Id: lastlog.c 3560 2011-11-06 18:39:59Z nekral-guest $"
#ident "$Id$"
#include <getopt.h>
#include <lastlog.h>

View File

@@ -32,7 +32,7 @@
#include <config.h>
#ident "$Id: login.c 3743 2012-05-25 11:51:53Z nekral-guest $"
#ident "$Id$"
#include <errno.h>
#include <grp.h>

View File

@@ -22,7 +22,7 @@
#endif
#ifndef USE_PAM
#ident "$Id: login_nopam.c 3182 2010-03-23 11:26:34Z nekral-guest $"
#ident "$Id$"
#include "prototypes.h"
/*

View File

@@ -31,7 +31,7 @@
#include <config.h>
#ident "$Id: logoutd.c 3233 2010-08-22 19:36:09Z nekral-guest $"
#ident "$Id$"
#include <fcntl.h>
#include <signal.h>

183
src/newgidmap.c Normal file
View File

@@ -0,0 +1,183 @@
/*
* Copyright (c) 2013 Eric Biederman
* 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>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "defines.h"
#include "prototypes.h"
#include "subordinateio.h"
#include "idmapping.h"
/*
* Global variables
*/
const char *Prog;
static bool verify_range(struct passwd *pw, struct map_range *range)
{
/* An empty range is invalid */
if (range->count == 0)
return false;
/* Test /etc/subgid */
if (have_sub_gids(pw->pw_name, range->lower, range->count))
return true;
/* Allow a process to map it's own gid */
if ((range->count == 1) && (pw->pw_gid == range->lower))
return true;
return false;
}
static void verify_ranges(struct passwd *pw, int ranges,
struct map_range *mappings)
{
struct map_range *mapping;
int idx;
mapping = mappings;
for (idx = 0; idx < ranges; idx++, mapping++) {
if (!verify_range(pw, mapping)) {
fprintf(stderr, _( "%s: gid range [%lu-%lu) -> [%lu-%lu) not allowed\n"),
Prog,
mapping->upper,
mapping->upper + mapping->count,
mapping->lower,
mapping->lower + mapping->count);
exit(EXIT_FAILURE);
}
}
}
static void usage(void)
{
fprintf(stderr, _("usage: %s <pid> <gid> <lowergid> <count> [ <gid> <lowergid> <count> ] ... \n"), Prog);
exit(EXIT_FAILURE);
}
/*
* newgidmap - Set the gid_map for the specified process
*/
int main(int argc, char **argv)
{
char proc_dir_name[PATH_MAX];
char *target_str;
pid_t target, parent;
int proc_dir_fd;
int ranges;
struct map_range *mappings;
struct stat st;
struct passwd *pw;
int written;
Prog = Basename (argv[0]);
/*
* The valid syntax are
* newgidmap target_pid
*/
if (argc < 2)
usage();
/* Find the process that needs it's user namespace
* gid mapping set.
*/
target_str = argv[1];
if (!get_pid(target_str, &target))
usage();
written = snprintf(proc_dir_name, sizeof(proc_dir_name), "/proc/%u/",
target);
if ((written <= 0) || (written >= sizeof(proc_dir_name))) {
fprintf(stderr, "%s: snprintf of proc path failed: %s\n",
Prog, strerror(errno));
}
proc_dir_fd = open(proc_dir_name, O_DIRECTORY);
if (proc_dir_fd < 0) {
fprintf(stderr, _("%s: Could not open proc directory for target %u\n"),
Prog, target);
return EXIT_FAILURE;
}
/* Who am i? */
pw = get_my_pwent ();
if (NULL == pw) {
fprintf (stderr,
_("%s: Cannot determine your user name.\n"),
Prog);
SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)",
(unsigned long) getuid ()));
return EXIT_FAILURE;
}
/* Get the effective uid and effective gid of the target process */
if (fstat(proc_dir_fd, &st) < 0) {
fprintf(stderr, _("%s: Could not stat directory for target %u\n"),
Prog, target);
return EXIT_FAILURE;
}
/* Verify real user and real group matches the password entry
* and the effective user and group of the program whose
* mappings we have been asked to set.
*/
if ((getuid() != pw->pw_uid) ||
(getgid() != pw->pw_gid) ||
(pw->pw_uid != st.st_uid) ||
(pw->pw_gid != st.st_gid)) {
fprintf(stderr, _( "%s: Target %u is owned by a different user\n" ),
Prog, target);
return EXIT_FAILURE;
}
if (!sub_gid_open(O_RDONLY)) {
return EXIT_FAILURE;
}
ranges = ((argc - 2) + 2) / 3;
mappings = get_map_ranges(ranges, argc - 2, argv + 2);
if (!mappings)
usage();
verify_ranges(pw, ranges, mappings);
write_mapping(proc_dir_fd, ranges, mappings, "gid_map");
sub_gid_close();
return EXIT_SUCCESS;
}

View File

@@ -32,7 +32,7 @@
#include <config.h>
#ident "$Id: newgrp.c 3458 2011-07-30 01:41:56Z nekral-guest $"
#ident "$Id$"
#include <errno.h>
#include <grp.h>
@@ -184,6 +184,16 @@ static void check_perms (const struct group *grp,
cpasswd = pw_encrypt (cp, grp->gr_passwd);
strzero (cp);
if (NULL == cpasswd) {
fprintf (stderr,
_("%s: failed to crypt password with previous salt: %s\n"),
Prog, strerror (errno));
SYSLOG ((LOG_INFO,
"Failed to crypt password with previous salt of group '%s'",
groupname));
goto failure;
}
if (grp->gr_passwd[0] == '\0' ||
strcmp (cpasswd, grp->gr_passwd) != 0) {
#ifdef WITH_AUDIT

183
src/newuidmap.c Normal file
View File

@@ -0,0 +1,183 @@
/*
* Copyright (c) 2013 Eric Biederman
* 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>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "defines.h"
#include "prototypes.h"
#include "subordinateio.h"
#include "idmapping.h"
/*
* Global variables
*/
const char *Prog;
static bool verify_range(struct passwd *pw, struct map_range *range)
{
/* An empty range is invalid */
if (range->count == 0)
return false;
/* Test /etc/subuid */
if (have_sub_uids(pw->pw_name, range->lower, range->count))
return true;
/* Allow a process to map it's own uid */
if ((range->count == 1) && (pw->pw_uid == range->lower))
return true;
return false;
}
static void verify_ranges(struct passwd *pw, int ranges,
struct map_range *mappings)
{
struct map_range *mapping;
int idx;
mapping = mappings;
for (idx = 0; idx < ranges; idx++, mapping++) {
if (!verify_range(pw, mapping)) {
fprintf(stderr, _( "%s: uid range [%lu-%lu) -> [%lu-%lu) not allowed\n"),
Prog,
mapping->upper,
mapping->upper + mapping->count,
mapping->lower,
mapping->lower + mapping->count);
exit(EXIT_FAILURE);
}
}
}
void usage(void)
{
fprintf(stderr, _("usage: %s <pid> <uid> <loweruid> <count> [ <uid> <loweruid> <count> ] ... \n"), Prog);
exit(EXIT_FAILURE);
}
/*
* newuidmap - Set the uid_map for the specified process
*/
int main(int argc, char **argv)
{
char proc_dir_name[PATH_MAX];
char *target_str;
pid_t target, parent;
int proc_dir_fd;
int ranges;
struct map_range *mappings;
struct stat st;
struct passwd *pw;
int written;
Prog = Basename (argv[0]);
/*
* The valid syntax are
* newuidmap target_pid
*/
if (argc < 2)
usage();
/* Find the process that needs it's user namespace
* uid mapping set.
*/
target_str = argv[1];
if (!get_pid(target_str, &target))
usage();
written = snprintf(proc_dir_name, sizeof(proc_dir_name), "/proc/%u/",
target);
if ((written <= 0) || (written >= sizeof(proc_dir_name))) {
fprintf(stderr, "%s: snprintf of proc path failed: %s\n",
Prog, strerror(errno));
}
proc_dir_fd = open(proc_dir_name, O_DIRECTORY);
if (proc_dir_fd < 0) {
fprintf(stderr, _("%s: Could not open proc directory for target %u\n"),
Prog, target);
return EXIT_FAILURE;
}
/* Who am i? */
pw = get_my_pwent ();
if (NULL == pw) {
fprintf (stderr,
_("%s: Cannot determine your user name.\n"),
Prog);
SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)",
(unsigned long) getuid ()));
return EXIT_FAILURE;
}
/* Get the effective uid and effective gid of the target process */
if (fstat(proc_dir_fd, &st) < 0) {
fprintf(stderr, _("%s: Could not stat directory for target %u\n"),
Prog, target);
return EXIT_FAILURE;
}
/* Verify real user and real group matches the password entry
* and the effective user and group of the program whose
* mappings we have been asked to set.
*/
if ((getuid() != pw->pw_uid) ||
(getgid() != pw->pw_gid) ||
(pw->pw_uid != st.st_uid) ||
(pw->pw_gid != st.st_gid)) {
fprintf(stderr, _( "%s: Target %u is owned by a different user\n" ),
Prog, target);
return EXIT_FAILURE;
}
if (!sub_uid_open(O_RDONLY)) {
return EXIT_FAILURE;
}
ranges = ((argc - 2) + 2) / 3;
mappings = get_map_ranges(ranges, argc - 2, argv + 2);
if (!mappings)
usage();
verify_ranges(pw, ranges, mappings);
write_mapping(proc_dir_fd, ranges, mappings, "uid_map");
sub_uid_close();
return EXIT_SUCCESS;
}

View File

@@ -40,7 +40,7 @@
#include <config.h>
#ident "$Id: newusers.c 3652 2011-12-09 21:31:39Z nekral-guest $"
#ident "$Id$"
#include <sys/types.h>
#include <sys/stat.h>
@@ -65,6 +65,9 @@
#include "pwio.h"
#include "sgroupio.h"
#include "shadowio.h"
#ifdef ENABLE_SUBIDS
#include "subordinateio.h"
#endif /* ENABLE_SUBIDS */
#include "chkname.h"
/*
@@ -90,6 +93,12 @@ static bool sgr_locked = false;
static bool pw_locked = false;
static bool gr_locked = false;
static bool spw_locked = false;
#ifdef ENABLE_SUBIDS
static bool is_sub_uid = false;
static bool is_sub_gid = false;
static bool sub_uid_locked = false;
static bool sub_gid_locked = false;
#endif /* ENABLE_SUBIDS */
/* local function prototypes */
static void usage (int status);
@@ -98,7 +107,7 @@ static int add_group (const char *, const char *, gid_t *, gid_t);
static int get_user_id (const char *, uid_t *);
static int add_user (const char *, uid_t, gid_t);
#ifndef USE_PAM
static void update_passwd (struct passwd *, const char *);
static int update_passwd (struct passwd *, const char *);
#endif /* !USE_PAM */
static int add_passwd (struct passwd *, const char *);
static void process_flags (int argc, char **argv);
@@ -178,6 +187,22 @@ static void fail_exit (int code)
}
}
#endif
#ifdef ENABLE_SUBIDS
if (sub_uid_locked) {
if (sub_uid_unlock () == 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) {
if (sub_gid_unlock () == 0) {
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ()));
/* continue */
}
}
#endif /* ENABLE_SUBIDS */
exit (code);
}
@@ -384,9 +409,15 @@ static int add_user (const char *name, uid_t uid, gid_t gid)
}
#ifndef USE_PAM
static void update_passwd (struct passwd *pwd, const char *password)
/*
* update_passwd - update the password in the passwd entry
*
* Return 0 if successful.
*/
static int update_passwd (struct passwd *pwd, const char *password)
{
void *crypt_arg = NULL;
char *cp;
if (crypt_method != NULL) {
#ifdef USE_SHA_CRYPT
if (sflg) {
@@ -398,10 +429,18 @@ static void update_passwd (struct passwd *pwd, const char *password)
if ((crypt_method != NULL) && (0 == strcmp(crypt_method, "NONE"))) {
pwd->pw_passwd = (char *)password;
} else {
pwd->pw_passwd = pw_encrypt (password,
crypt_make_salt (crypt_method,
crypt_arg));
const char *salt = crypt_make_salt (crypt_method, crypt_arg);
cp = pw_encrypt (password, salt);
if (NULL == cp) {
fprintf (stderr,
_("%s: failed to crypt password with salt '%s': %s\n"),
Prog, salt, strerror (errno));
return 1;
}
pwd->pw_passwd = cp;
}
return 0;
}
#endif /* !USE_PAM */
@@ -412,6 +451,7 @@ static int add_passwd (struct passwd *pwd, const char *password)
{
const struct spwd *sp;
struct spwd spent;
char *cp;
#ifndef USE_PAM
void *crypt_arg = NULL;
@@ -429,8 +469,7 @@ static int add_passwd (struct passwd *pwd, const char *password)
* harder since there are zillions of things to do ...
*/
if (!is_shadow) {
update_passwd (pwd, password);
return 0;
return update_passwd (pwd, password);
}
#endif /* USE_PAM */
@@ -448,7 +487,14 @@ static int add_passwd (struct passwd *pwd, const char *password)
} else {
const char *salt = crypt_make_salt (crypt_method,
crypt_arg);
spent.sp_pwdp = pw_encrypt (password, salt);
cp = pw_encrypt (password, salt);
if (NULL == cp) {
fprintf (stderr,
_("%s: failed to crypt password with salt '%s': %s\n"),
Prog, salt, strerror (errno));
return 1;
}
spent.sp_pwdp = cp;
}
spent.sp_lstchg = (long) time ((time_t *) 0) / SCALE;
if (0 == spent.sp_lstchg) {
@@ -466,8 +512,7 @@ static int add_passwd (struct passwd *pwd, const char *password)
* the password set someplace else.
*/
if (strcmp (pwd->pw_passwd, "x") != 0) {
update_passwd (pwd, password);
return 0;
return update_passwd (pwd, password);
}
#else /* USE_PAM */
/*
@@ -492,7 +537,14 @@ static int add_passwd (struct passwd *pwd, const char *password)
spent.sp_pwdp = (char *)password;
} else {
const char *salt = crypt_make_salt (crypt_method, crypt_arg);
spent.sp_pwdp = pw_encrypt (password, salt);
cp = pw_encrypt (password, salt);
if (NULL == cp) {
fprintf (stderr,
_("%s: failed to crypt password with salt '%s': %s\n"),
Prog, salt, strerror (errno));
return 1;
}
spent.sp_pwdp = cp;
}
#else
/*
@@ -732,6 +784,26 @@ static void open_files (void)
sgr_locked = true;
}
#endif
#ifdef ENABLE_SUBIDS
if (is_sub_uid) {
if (sub_uid_lock () == 0) {
fprintf (stderr,
_("%s: cannot lock %s; try again later.\n"),
Prog, sub_uid_dbname ());
fail_exit (EXIT_FAILURE);
}
sub_uid_locked = true;
}
if (is_sub_gid) {
if (sub_gid_lock () == 0) {
fprintf (stderr,
_("%s: cannot lock %s; try again later.\n"),
Prog, sub_gid_dbname ());
fail_exit (EXIT_FAILURE);
}
sub_gid_locked = true;
}
#endif /* ENABLE_SUBIDS */
if (pw_open (O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ());
@@ -751,6 +823,24 @@ static void open_files (void)
fail_exit (EXIT_FAILURE);
}
#endif
#ifdef ENABLE_SUBIDS
if (is_sub_uid) {
if (sub_uid_open (O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sub_uid_dbname ());
fail_exit (EXIT_FAILURE);
}
}
if (is_sub_gid) {
if (sub_gid_open (O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sub_gid_dbname ());
fail_exit (EXIT_FAILURE);
}
}
#endif /* ENABLE_SUBIDS */
}
/*
@@ -795,6 +885,21 @@ static void close_files (void)
SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ()));
fail_exit (EXIT_FAILURE);
}
#ifdef ENABLE_SUBIDS
if (is_sub_uid && (sub_uid_close () == 0)) {
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 (EXIT_FAILURE);
}
if (is_sub_gid && (sub_gid_close () == 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 (EXIT_FAILURE);
}
#endif /* ENABLE_SUBIDS */
if (gr_unlock () == 0) {
fprintf (stderr,
_("%s: failed to unlock %s\n"),
@@ -823,6 +928,24 @@ static void close_files (void)
sgr_locked = false;
}
#endif
#ifdef ENABLE_SUBIDS
if (is_sub_uid) {
if (sub_uid_unlock () == 0) {
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ()));
/* continue */
}
sub_uid_locked = false;
}
if (is_sub_gid) {
if (sub_gid_unlock () == 0) {
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ()));
/* continue */
}
sub_gid_locked = false;
}
#endif /* ENABLE_SUBIDS */
}
int main (int argc, char **argv)
@@ -864,6 +987,10 @@ int main (int argc, char **argv)
#ifdef SHADOWGRP
is_shadow_grp = sgr_file_present ();
#endif
#ifdef ENABLE_SUBIDS
is_sub_uid = sub_uid_file_present ();
is_sub_gid = sub_gid_file_present ();
#endif /* ENABLE_SUBIDS */
open_files ();
@@ -1044,6 +1171,48 @@ int main (int argc, char **argv)
errors++;
continue;
}
#ifdef ENABLE_SUBIDS
/*
* Add subordinate uids if the user does not have them.
*/
if (is_sub_uid && !sub_uid_assigned(fields[0])) {
uid_t sub_uid_start = 0;
unsigned long sub_uid_count = 0;
if (find_new_sub_uids(fields[0], &sub_uid_start, &sub_uid_count) == 0) {
if (sub_uid_add(fields[0], sub_uid_start, sub_uid_count) == 0) {
fprintf (stderr,
_("%s: failed to prepare new %s entry\n"),
Prog, sub_uid_dbname ());
}
} else {
fprintf (stderr,
_("%s: can't find subordinate user range\n"),
Prog);
errors++;
}
}
/*
* Add subordinate gids if the user does not have them.
*/
if (is_sub_gid && !sub_gid_assigned(fields[0])) {
gid_t sub_gid_start = 0;
unsigned long sub_gid_count = 0;
if (find_new_sub_gids(fields[0], &sub_gid_start, &sub_gid_count) == 0) {
if (sub_gid_add(fields[0], sub_gid_start, sub_gid_count) == 0) {
fprintf (stderr,
_("%s: failed to prepare new %s entry\n"),
Prog, sub_uid_dbname ());
}
} else {
fprintf (stderr,
_("%s: can't find subordinate group range\n"),
Prog);
errors++;
}
}
#endif /* ENABLE_SUBIDS */
}
/*

View File

@@ -26,7 +26,7 @@
#include <config.h>
#ident "$Id: nologin.c 2862 2009-05-09 13:14:23Z nekral-guest $"
#ident "$Id$"
#include <stdio.h>
#include <stdlib.h>

View File

@@ -32,7 +32,7 @@
#include <config.h>
#ident "$Id: passwd.c 3710 2012-02-13 20:32:00Z nekral-guest $"
#ident "$Id$"
#include <errno.h>
#include <fcntl.h>
@@ -218,6 +218,7 @@ static int new_password (const struct passwd *pw)
{
char *clear; /* Pointer to clear text */
char *cipher; /* Pointer to cipher text */
const char *salt; /* Pointer to new salt */
char *cp; /* Pointer to getpass() response */
char orig[200]; /* Original password */
char pass[200]; /* New password */
@@ -242,6 +243,18 @@ static int new_password (const struct passwd *pw)
}
cipher = pw_encrypt (clear, crypt_passwd);
if (NULL == cipher) {
strzero (clear);
fprintf (stderr,
_("%s: failed to crypt password with previous salt: %s\n"),
Prog, strerror (errno));
SYSLOG ((LOG_INFO,
"Failed to crypt password with previous salt of user '%s'",
pw->pw_name));
return -1;
}
if (strcmp (cipher, crypt_passwd) != 0) {
strzero (clear);
strzero (cipher);
@@ -348,9 +361,17 @@ static int new_password (const struct passwd *pw)
/*
* Encrypt the password, then wipe the cleartext password.
*/
cp = pw_encrypt (pass, crypt_make_salt (NULL, NULL));
salt = crypt_make_salt (NULL, NULL);
cp = pw_encrypt (pass, salt);
memzero (pass, sizeof pass);
if (NULL == cp) {
fprintf (stderr,
_("%s: failed to crypt password with salt '%s': %s\n"),
Prog, salt, strerror (errno));
return -1;
}
#ifdef HAVE_LIBCRACK_HIST
HistUpdate (pw->pw_name, crypt_passwd);
#endif /* HAVE_LIBCRACK_HIST */

View File

@@ -33,7 +33,7 @@
#include <config.h>
#ident "$Id: pwck.c 3574 2011-11-13 16:24:39Z nekral-guest $"
#ident "$Id$"
#include <fcntl.h>
#include <grp.h>

View File

@@ -55,7 +55,7 @@
#include <config.h>
#ident "$Id: pwconv.c 3743 2012-05-25 11:51:53Z nekral-guest $"
#ident "$Id$"
#include <errno.h>
#include <fcntl.h>

View File

@@ -32,7 +32,7 @@
#include <config.h>
#ident "$Id: pwunconv.c 3743 2012-05-25 11:51:53Z nekral-guest $"
#ident "$Id$"
#include <fcntl.h>
#include <pwd.h>

View File

@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2000 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2012, Nicolas François
* Copyright (c) 2007 - 2013, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -53,7 +53,7 @@
#include <config.h>
#ident "$Id: su.c 3743 2012-05-25 11:51:53Z nekral-guest $"
#ident "$Id$"
#include <getopt.h>
#include <grp.h>
@@ -181,7 +181,7 @@ static bool iswheel (const char *username)
static RETSIGTYPE kill_child (int unused(s))
{
if (0 != pid_child) {
(void) kill (pid_child, SIGKILL);
(void) kill (-pid_child, SIGKILL);
(void) fputs (_(" ...killed.\n"), stderr);
} else {
(void) fputs (_(" ...waiting for child to terminate.\n"),
@@ -347,6 +347,7 @@ static void prepare_pam_close_session (void)
if ( ((pid_t)-1 == pid)
&& (EINTR == errno)
&& (SIGTSTP == caught)) {
caught = 0;
/* Except for SIGTSTP, which request to
* stop the child.
* We will SIGSTOP ourself on the next
@@ -370,7 +371,13 @@ static void prepare_pam_close_session (void)
(void) fputs ("\n", stderr);
(void) fputs (_("Session terminated, terminating shell..."),
stderr);
(void) kill (pid_child, caught);
(void) kill (-pid_child, caught);
(void) signal (SIGALRM, kill_child);
(void) alarm (2);
(void) wait (&status);
(void) fputs (_(" ...terminated.\n"), stderr);
}
ret = pam_close_session (pamh, 0);
@@ -383,14 +390,6 @@ static void prepare_pam_close_session (void)
(void) pam_setcred (pamh, PAM_DELETE_CRED);
(void) pam_end (pamh, PAM_SUCCESS);
if (0 != caught) {
(void) signal (SIGALRM, kill_child);
(void) alarm (2);
(void) wait (&status);
(void) fputs (_(" ...terminated.\n"), stderr);
}
exit ((0 != WIFEXITED (status)) ? WEXITSTATUS (status)
: WTERMSIG (status) + 128);
/* Only the child returns. See above. */

View File

@@ -32,7 +32,7 @@
#include <config.h>
#ident "$Id: sulogin.c 3521 2011-10-18 20:28:01Z nekral-guest $"
#ident "$Id$"
#include <fcntl.h>
#include <pwd.h>

View File

@@ -32,7 +32,7 @@
#include <config.h>
#ident "$Id: useradd.c 3743 2012-05-25 11:51:53Z nekral-guest $"
#ident "$Id$"
#include <assert.h>
#include <ctype.h>
@@ -65,6 +65,9 @@
#include "sgroupio.h"
#endif
#include "shadowio.h"
#ifdef ENABLE_SUBIDS
#include "subordinateio.h"
#endif /* ENABLE_SUBIDS */
#ifdef WITH_TCB
#include "tcbfuncs.h"
#endif
@@ -121,6 +124,16 @@ static bool is_shadow_pwd;
static bool is_shadow_grp;
static bool sgr_locked = false;
#endif
#ifdef ENABLE_SUBIDS
static bool is_sub_uid = false;
static bool is_sub_gid = false;
static bool sub_uid_locked = false;
static bool sub_gid_locked = false;
static uid_t sub_uid_start; /* New subordinate uid range */
static unsigned long sub_uid_count;
static gid_t sub_gid_start; /* New subordinate gid range */
static unsigned long sub_gid_count;
#endif /* ENABLE_SUBIDS */
static bool pw_locked = false;
static bool gr_locked = false;
static bool spw_locked = false;
@@ -168,6 +181,10 @@ 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_SE_UPDATE 14 /* can't update SELinux user mapping */
#ifdef ENABLE_SUBIDS
#define E_SUB_UID_UPDATE 16 /* can't update the subordinate uid file */
#define E_SUB_GID_UPDATE 18 /* can't update the subordinate gid file */
#endif /* ENABLE_SUBIDS */
#define DGROUP "GROUP="
#define DHOME "HOME="
@@ -268,6 +285,34 @@ static void fail_exit (int code)
}
}
#endif
#ifdef ENABLE_SUBIDS
if (sub_uid_locked) {
if (sub_uid_unlock () == 0) {
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ()));
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_USER, Prog,
"unlocking subordinate user file",
user_name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
/* continue */
}
}
if (sub_gid_locked) {
if (sub_gid_unlock () == 0) {
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ()));
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_USER, Prog,
"unlocking subordinate group file",
user_name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
/* continue */
}
}
#endif /* ENABLE_SUBIDS */
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_USER, Prog,
@@ -1378,6 +1423,20 @@ static void close_files (void)
}
#endif
}
#ifdef ENABLE_SUBIDS
if (is_sub_uid && (sub_uid_close () == 0)) {
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);
}
if (is_sub_gid && (sub_gid_close () == 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);
}
#endif /* ENABLE_SUBIDS */
if (is_shadow_pwd) {
if (spw_unlock () == 0) {
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ());
@@ -1432,6 +1491,36 @@ static void close_files (void)
sgr_locked = false;
}
#endif
#ifdef ENABLE_SUBIDS
if (is_sub_uid) {
if (sub_uid_unlock () == 0) {
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ()));
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_USER, Prog,
"unlocking subordinate user file",
user_name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
/* continue */
}
sub_uid_locked = false;
}
if (is_sub_gid) {
if (sub_gid_unlock () == 0) {
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ()));
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_USER, Prog,
"unlocking subordinate group file",
user_name, AUDIT_NO_ID,
SHADOW_AUDIT_FAILURE);
#endif
/* continue */
}
sub_gid_locked = false;
}
#endif /* ENABLE_SUBIDS */
}
/*
@@ -1486,6 +1575,38 @@ static void open_files (void)
}
}
#endif
#ifdef ENABLE_SUBIDS
if (is_sub_uid) {
if (sub_uid_lock () == 0) {
fprintf (stderr,
_("%s: cannot lock %s; try again later.\n"),
Prog, sub_uid_dbname ());
fail_exit (E_SUB_UID_UPDATE);
}
sub_uid_locked = true;
if (sub_uid_open (O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sub_uid_dbname ());
fail_exit (E_SUB_UID_UPDATE);
}
}
if (is_sub_gid) {
if (sub_gid_lock () == 0) {
fprintf (stderr,
_("%s: cannot lock %s; try again later.\n"),
Prog, sub_gid_dbname ());
fail_exit (E_SUB_GID_UPDATE);
}
sub_gid_locked = true;
if (sub_gid_open (O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sub_gid_dbname ());
fail_exit (E_SUB_GID_UPDATE);
}
}
#endif /* ENABLE_SUBIDS */
}
static void open_shadow (void)
@@ -1732,13 +1853,29 @@ static void usr_update (void)
#endif
fail_exit (E_PW_UPDATE);
}
#ifdef ENABLE_SUBIDS
if (is_sub_uid &&
(sub_uid_add(user_name, sub_uid_start, sub_uid_count) == 0)) {
fprintf (stderr,
_("%s: failed to prepare the new %s entry\n"),
Prog, sub_uid_dbname ());
fail_exit (E_SUB_UID_UPDATE);
}
if (is_sub_gid &&
(sub_gid_add(user_name, sub_gid_start, sub_gid_count) == 0)) {
fprintf (stderr,
_("%s: failed to prepare the new %s entry\n"),
Prog, sub_uid_dbname ());
fail_exit (E_SUB_GID_UPDATE);
}
#endif /* ENABLE_SUBIDS */
#ifdef WITH_AUDIT
audit_logger (AUDIT_ADD_USER, Prog,
"adding user",
user_name, (unsigned int) user_id,
SHADOW_AUDIT_SUCCESS);
#endif
/*
* Do any group file updates for this user.
*/
@@ -1884,6 +2021,10 @@ int main (int argc, char **argv)
#ifdef SHADOWGRP
is_shadow_grp = sgr_file_present ();
#endif
#ifdef ENABLE_SUBIDS
is_sub_uid = sub_uid_file_present ();
is_sub_gid = sub_gid_file_present ();
#endif /* ENABLE_SUBIDS */
get_defaults ();
@@ -2034,6 +2175,25 @@ int main (int argc, char **argv)
grp_add ();
}
#ifdef ENABLE_SUBIDS
if (is_sub_uid) {
if (find_new_sub_uids(user_name, &sub_uid_start, &sub_uid_count) < 0) {
fprintf (stderr,
_("%s: can't create subordinate user IDs\n"),
Prog);
fail_exit(E_SUB_UID_UPDATE);
}
}
if (is_sub_gid) {
if (find_new_sub_gids(user_name, &sub_gid_start, &sub_gid_count) < 0) {
fprintf (stderr,
_("%s: can't create subordinate group IDs\n"),
Prog);
fail_exit(E_SUB_GID_UPDATE);
}
}
#endif /* ENABLE_SUBIDS */
usr_update ();
if (mflg) {

View File

@@ -32,7 +32,7 @@
#include <config.h>
#ident "$Id: userdel.c 3743 2012-05-25 11:51:53Z nekral-guest $"
#ident "$Id$"
#include <errno.h>
#include <fcntl.h>
@@ -65,6 +65,9 @@
#endif /* WITH_TCB */
/*@-exitarg@*/
#include "exitcodes.h"
#ifdef ENABLE_SUBIDS
#include "subordinateio.h"
#endif /* ENABLE_SUBIDS */
/*
* exit status values
@@ -75,6 +78,10 @@
#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 */
#ifdef ENABLE_SUBIDS
#define E_SUB_UID_UPDATE 16 /* can't update the subordinate uid file */
#define E_SUB_GID_UPDATE 18 /* can't update the subordinate gid file */
#endif /* ENABLE_SUBIDS */
/*
* Global variables
@@ -99,6 +106,12 @@ static bool sgr_locked = false;
static bool pw_locked = false;
static bool gr_locked = false;
static bool spw_locked = false;
#ifdef ENABLE_SUBIDS
static bool is_sub_uid;
static bool is_sub_gid;
static bool sub_uid_locked = false;
static bool sub_gid_locked = false;
#endif /* ENABLE_SUBIDS */
/* local function prototypes */
static void usage (int status);
@@ -437,6 +450,36 @@ static void close_files (void)
sgr_locked = false;
}
#endif /* SHADOWGRP */
#ifdef ENABLE_SUBIDS
if (is_sub_uid) {
if (sub_uid_close () == 0) {
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);
}
if (sub_uid_unlock () == 0) {
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ()));
/* continue */
}
sub_uid_locked = false;
}
if (is_sub_gid) {
if (sub_gid_close () == 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);
}
if (sub_gid_unlock () == 0) {
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ()));
/* continue */
}
sub_gid_locked = false;
}
#endif /* ENABLE_SUBIDS */
}
/*
@@ -474,6 +517,22 @@ static void fail_exit (int code)
}
}
#endif /* SHADOWGRP */
#ifdef ENABLE_SUBIDS
if (sub_uid_locked) {
if (sub_uid_unlock () == 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) {
if (sub_gid_unlock () == 0) {
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ()));
/* continue */
}
}
#endif /* ENABLE_SUBIDS */
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
@@ -595,6 +654,60 @@ static void open_files (void)
}
}
#endif /* SHADOWGRP */
#ifdef ENABLE_SUBIDS
if (is_sub_uid) {
if (sub_uid_lock () == 0) {
fprintf (stderr,
_("%s: cannot lock %s; try again later.\n"),
Prog, sub_uid_dbname ());
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"locking subordinate user file",
user_name, (unsigned int) user_id,
SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
fail_exit (E_SUB_UID_UPDATE);
}
sub_uid_locked = true;
if (sub_uid_open (O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"), Prog, sub_uid_dbname ());
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"opening subordinate user file",
user_name, (unsigned int) user_id,
SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
fail_exit (E_SUB_UID_UPDATE);
}
}
if (is_sub_gid) {
if (sub_gid_lock () == 0) {
fprintf (stderr,
_("%s: cannot lock %s; try again later.\n"),
Prog, sub_gid_dbname ());
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"locking subordinate group file",
user_name, (unsigned int) user_id,
SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
fail_exit (E_SUB_GID_UPDATE);
}
sub_gid_locked = true;
if (sub_gid_open (O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"), Prog, sub_gid_dbname ());
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"opening subordinate group file",
user_name, (unsigned int) user_id,
SHADOW_AUDIT_FAILURE);
#endif /* WITH_AUDIT */
fail_exit (E_SUB_GID_UPDATE);
}
}
#endif /* ENABLE_SUBIDS */
}
/*
@@ -619,6 +732,20 @@ static void update_user (void)
Prog, user_name, spw_dbname ());
fail_exit (E_PW_UPDATE);
}
#ifdef ENABLE_SUBIDS
if (is_sub_uid && sub_uid_remove(user_name, 0, ULONG_MAX) == 0) {
fprintf (stderr,
_("%s: cannot remove entry %lu from %s\n"),
Prog, (unsigned long)user_id, sub_uid_dbname ());
fail_exit (E_SUB_UID_UPDATE);
}
if (is_sub_gid && sub_gid_remove(user_name, 0, ULONG_MAX) == 0) {
fprintf (stderr,
_("%s: cannot remove entry %lu from %s\n"),
Prog, (unsigned long)user_id, sub_gid_dbname ());
fail_exit (E_SUB_GID_UPDATE);
}
#endif /* ENABLE_SUBIDS */
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
"deleting user entries",
@@ -966,6 +1093,10 @@ int main (int argc, char **argv)
#ifdef SHADOWGRP
is_shadow_grp = sgr_file_present ();
#endif /* SHADOWGRP */
#ifdef ENABLE_SUBIDS
is_sub_uid = sub_uid_file_present ();
is_sub_gid = sub_gid_file_present ();
#endif /* ENABLE_SUBIDS */
/*
* Start with a quick check to see if the user exists.

View File

@@ -32,7 +32,7 @@
#include <config.h>
#ident "$Id: usermod.c 3650 2011-11-21 22:02:15Z nekral-guest $"
#ident "$Id$"
#include <ctype.h>
#include <errno.h>
@@ -63,6 +63,9 @@
#include "sgroupio.h"
#endif
#include "shadowio.h"
#ifdef ENABLE_SUBIDS
#include "subordinateio.h"
#endif /* ENABLE_SUBIDS */
#ifdef WITH_TCB
#include "tcbfuncs.h"
#endif
@@ -86,7 +89,13 @@
/* #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 */
#ifdef ENABLE_SUBIDS
#define E_SUB_UID_UPDATE 16 /* can't update the subordinate uid file */
#define E_SUB_GID_UPDATE 18 /* can't update the subordinate gid file */
#endif /* ENABLE_SUBIDS */
#define VALID(s) (strcspn (s, ":\n") == strlen (s))
/*
* Global variables
*/
@@ -132,6 +141,12 @@ static bool
#ifdef WITH_SELINUX
Zflg = false, /* new selinux user */
#endif
#ifdef ENABLE_SUBIDS
vflg = false, /* add subordinate uids */
Vflg = false, /* delete subordinate uids */
wflg = false, /* add subordinate gids */
Wflg = false, /* delete subordinate gids */
#endif /* ENABLE_SUBIDS */
uflg = false, /* specify new user ID */
Uflg = false; /* unlock the password */
@@ -141,12 +156,21 @@ static bool is_shadow_pwd;
static bool is_shadow_grp;
#endif
#ifdef ENABLE_SUBIDS
static bool is_sub_uid = false;
static bool is_sub_gid = false;
#endif /* ENABLE_SUBIDS */
static bool pw_locked = false;
static bool spw_locked = false;
static bool gr_locked = false;
#ifdef SHADOWGRP
static bool sgr_locked = false;
#endif
#ifdef ENABLE_SUBIDS
static bool sub_uid_locked = false;
static bool sub_gid_locked = false;
#endif /* ENABLE_SUBIDS */
/* local function prototypes */
@@ -302,6 +326,71 @@ static int get_groups (char *list)
return 0;
}
#ifdef ENABLE_SUBIDS
struct ulong_range
{
unsigned long first;
unsigned long last;
};
static struct ulong_range getulong_range(const char *str)
{
struct ulong_range result = { .first = ULONG_MAX, .last = 0 };
long long first, last;
char *pos;
errno = 0;
first = strtoll(str, &pos, 10);
if (('\0' == *str) || ('-' != *pos ) || (ERANGE == errno) ||
(first != (unsigned long int)first))
goto out;
errno = 0;
last = strtoll(pos + 1, &pos, 10);
if (('\0' != *pos ) || (ERANGE == errno) ||
(last != (unsigned long int)last))
goto out;
if (first > last)
goto out;
result.first = (unsigned long int)first;
result.last = (unsigned long int)last;
out:
return result;
}
struct ulong_range_list_entry {
struct ulong_range_list_entry *next;
struct ulong_range range;
};
static struct ulong_range_list_entry *add_sub_uids = NULL, *del_sub_uids = NULL;
static struct ulong_range_list_entry *add_sub_gids = NULL, *del_sub_gids = NULL;
static int prepend_range(const char *str, struct ulong_range_list_entry **head)
{
struct ulong_range range;
struct ulong_range_list_entry *entry;
range = getulong_range(str);
if (range.first > range.last)
return 0;
entry = malloc(sizeof(*entry));
if (!entry) {
fprintf (stderr,
_("%s: failed to allocate memory: %s\n"),
Prog, strerror (errno));
return 0;
}
entry->next = *head;
entry->range = range;
*head = entry;
return 1;
}
#endif /* ENABLE_SUBIDS */
/*
* usage - display usage message and exit
*/
@@ -334,6 +423,12 @@ static /*@noreturn@*/void usage (int status)
(void) fputs (_(" -s, --shell SHELL new login shell for the user account\n"), usageout);
(void) fputs (_(" -u, --uid UID new UID for the user account\n"), usageout);
(void) fputs (_(" -U, --unlock unlock the user account\n"), usageout);
#ifdef ENABLE_SUBIDS
(void) fputs (_(" -v, --add-subuids FIRST-LAST add range of subordinate uids\n"), usageout);
(void) fputs (_(" -V, --del-subuids FIRST-LAST remove range of subordinate uids\n"), usageout);
(void) fputs (_(" -w, --add-subgids FIRST-LAST add range of subordinate gids\n"), usageout);
(void) fputs (_(" -W, --del-subgids FIRST-LAST remove range of subordinate gids\n"), usageout);
#endif /* ENABLE_SUBIDS */
#ifdef WITH_SELINUX
(void) fputs (_(" -Z, --selinux-user SEUSER new SELinux user mapping for the user account\n"), usageout);
#endif /* WITH_SELINUX */
@@ -590,6 +685,22 @@ static /*@noreturn@*/void fail_exit (int code)
/* continue */
}
}
#ifdef ENABLE_SUBIDS
if (sub_uid_locked) {
if (sub_uid_unlock () == 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) {
if (sub_gid_unlock () == 0) {
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ()));
/* continue */
}
}
#endif /* ENABLE_SUBIDS */
#ifdef WITH_AUDIT
audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
@@ -889,18 +1000,26 @@ static void process_flags (int argc, char **argv)
{"shell", required_argument, NULL, 's'},
{"uid", required_argument, NULL, 'u'},
{"unlock", no_argument, NULL, 'U'},
#ifdef ENABLE_SUBIDS
{"add-subuids", required_argument, NULL, 'v'},
{"del-subuids", required_argument, NULL, 'V'},
{"add-subgids", required_argument, NULL, 'w'},
{"del-subgids", required_argument, NULL, 'W'},
#endif /* ENABLE_SUBIDS */
#ifdef WITH_SELINUX
{"selinux-user", required_argument, NULL, 'Z'},
#endif /* WITH_SELINUX */
{NULL, 0, NULL, '\0'}
};
while ((c = getopt_long (argc, argv,
"ac:d:e:f:g:G:hl:Lmop:R:s:u:U"
#ifdef ENABLE_SUBIDS
"v:w:V:W:"
#endif /* ENABLE_SUBIDS */
#ifdef WITH_SELINUX
"ac:d:e:f:g:G:hl:Lmop:R:s:u:UZ:",
#else /* !WITH_SELINUX */
"ac:d:e:f:g:G:hl:Lmop:R:s:u:U",
#endif /* !WITH_SELINUX */
long_options, NULL)) != -1) {
"Z:"
#endif /* WITH_SELINUX */
, long_options, NULL)) != -1) {
switch (c) {
case 'a':
aflg = true;
@@ -1018,6 +1137,44 @@ static void process_flags (int argc, char **argv)
case 'U':
Uflg = true;
break;
#ifdef ENABLE_SUBIDS
case 'v':
if (prepend_range (optarg, &add_sub_uids) == 0) {
fprintf (stderr,
_("%s: invalid subordinate uid range '%s'\n"),
Prog, optarg);
exit(E_BAD_ARG);
}
vflg = true;
break;
case 'V':
if (prepend_range (optarg, &del_sub_uids) == 0) {
fprintf (stderr,
_("%s: invalid subordinate uid range '%s'\n"),
Prog, optarg);
exit(E_BAD_ARG);
}
Vflg = true;
break;
case 'w':
if (prepend_range (optarg, &add_sub_gids) == 0) {
fprintf (stderr,
_("%s: invalid subordinate gid range '%s'\n"),
Prog, optarg);
exit(E_BAD_ARG);
}
wflg = true;
break;
case 'W':
if (prepend_range (optarg, &del_sub_gids) == 0) {
fprintf (stderr,
_("%s: invalid subordinate gid range '%s'\n"),
Prog, optarg);
exit(E_BAD_ARG);
}
Wflg = true;
break;
#endif /* ENABLE_SUBIDS */
#ifdef WITH_SELINUX
case 'Z':
if (is_selinux_enabled () > 0) {
@@ -1170,6 +1327,9 @@ static void process_flags (int argc, char **argv)
if (!(Uflg || uflg || sflg || pflg || mflg || Lflg ||
lflg || Gflg || gflg || fflg || eflg || dflg || cflg
#ifdef ENABLE_SUBIDS
|| vflg || Vflg || wflg || Wflg
#endif /* ENABLE_SUBIDS */
#ifdef WITH_SELINUX
|| Zflg
#endif /* WITH_SELINUX */
@@ -1200,6 +1360,22 @@ static void process_flags (int argc, char **argv)
Prog, (unsigned long) user_newid);
exit (E_UID_IN_USE);
}
if ( (vflg || Vflg)
&& !is_sub_uid) {
fprintf (stderr,
_("%s: %s does not exist, you cannot use the flags %s or %s\n"),
Prog, sub_uid_dbname (), "-v", "-V");
exit (E_USAGE);
}
if ( (wflg || Wflg)
&& !is_sub_gid) {
fprintf (stderr,
_("%s: %s does not exist, you cannot use the flags %s or %s\n"),
Prog, sub_gid_dbname (), "-w", "-W");
exit (E_USAGE);
}
}
/*
@@ -1248,6 +1424,10 @@ static void close_files (void)
sgr_dbname ()));
fail_exit (E_GRP_UPDATE);
}
}
#endif
#ifdef SHADOWGRP
if (is_shadow_grp) {
if (sgr_unlock () == 0) {
fprintf (stderr,
_("%s: failed to unlock %s\n"),
@@ -1296,6 +1476,35 @@ static void close_files (void)
sgr_locked = false;
#endif
#ifdef ENABLE_SUBIDS
if (vflg || Vflg) {
if (sub_uid_close () == 0) {
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);
}
if (sub_uid_unlock () == 0) {
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ()));
/* continue */
}
sub_uid_locked = false;
}
if (wflg || Wflg) {
if (sub_gid_close () == 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);
}
if (sub_gid_unlock () == 0) {
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ());
SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ()));
/* continue */
}
sub_gid_locked = false;
}
#endif /* ENABLE_SUBIDS */
/*
* Close the DBM and/or flat files
*/
@@ -1375,6 +1584,38 @@ static void open_files (void)
}
#endif
}
#ifdef ENABLE_SUBIDS
if (vflg || Vflg) {
if (sub_uid_lock () == 0) {
fprintf (stderr,
_("%s: cannot lock %s; try again later.\n"),
Prog, sub_uid_dbname ());
fail_exit (E_SUB_UID_UPDATE);
}
sub_uid_locked = true;
if (sub_uid_open (O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sub_uid_dbname ());
fail_exit (E_SUB_UID_UPDATE);
}
}
if (wflg || Wflg) {
if (sub_gid_lock () == 0) {
fprintf (stderr,
_("%s: cannot lock %s; try again later.\n"),
Prog, sub_gid_dbname ());
fail_exit (E_SUB_GID_UPDATE);
}
sub_gid_locked = true;
if (sub_gid_open (O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sub_gid_dbname ());
fail_exit (E_SUB_GID_UPDATE);
}
}
#endif /* ENABLE_SUBIDS */
}
/*
@@ -1476,6 +1717,60 @@ static void usr_update (void)
fail_exit (E_PW_UPDATE);
}
}
#ifdef ENABLE_SUBIDS
if (Vflg) {
struct ulong_range_list_entry *ptr;
for (ptr = del_sub_uids; ptr != NULL; ptr = ptr->next) {
unsigned long count = ptr->range.last - ptr->range.first + 1;
if (sub_uid_remove(user_name, ptr->range.first, count) == 0) {
fprintf (stderr,
_("%s: failed to remove uid range %lu-%lu from '%s'\n"),
Prog, ptr->range.first, ptr->range.last,
sub_uid_dbname ());
fail_exit (E_SUB_UID_UPDATE);
}
}
}
if (vflg) {
struct ulong_range_list_entry *ptr;
for (ptr = add_sub_uids; ptr != NULL; ptr = ptr->next) {
unsigned long count = ptr->range.last - ptr->range.first + 1;
if (sub_uid_add(user_name, ptr->range.first, count) == 0) {
fprintf (stderr,
_("%s: failed to add uid range %lu-%lu from '%s'\n"),
Prog, ptr->range.first, ptr->range.last,
sub_uid_dbname ());
fail_exit (E_SUB_UID_UPDATE);
}
}
}
if (Wflg) {
struct ulong_range_list_entry *ptr;
for (ptr = del_sub_gids; ptr != NULL; ptr = ptr->next) {
unsigned long count = ptr->range.last - ptr->range.first + 1;
if (sub_gid_remove(user_name, ptr->range.first, count) == 0) {
fprintf (stderr,
_("%s: failed to remove gid range %lu-%lu from '%s'\n"),
Prog, ptr->range.first, ptr->range.last,
sub_gid_dbname ());
fail_exit (E_SUB_GID_UPDATE);
}
}
}
if (wflg) {
struct ulong_range_list_entry *ptr;
for (ptr = add_sub_gids; ptr != NULL; ptr = ptr->next) {
unsigned long count = ptr->range.last - ptr->range.first + 1;
if (sub_gid_add(user_name, ptr->range.first, count) == 0) {
fprintf (stderr,
_("%s: failed to add gid range %lu-%lu from '%s'\n"),
Prog, ptr->range.first, ptr->range.last,
sub_gid_dbname ());
fail_exit (E_SUB_GID_UPDATE);
}
}
}
#endif /* ENABLE_SUBIDS */
}
/*
@@ -1811,6 +2106,10 @@ int main (int argc, char **argv)
#ifdef SHADOWGRP
is_shadow_grp = sgr_file_present ();
#endif
#ifdef ENABLE_SUBIDS
is_sub_uid = sub_uid_file_present ();
is_sub_gid = sub_gid_file_present ();
#endif /* ENABLE_SUBIDS */
process_flags (argc, argv);
@@ -1818,7 +2117,11 @@ int main (int argc, char **argv)
* The home directory, the username and the user's UID should not
* be changed while the user is logged in.
*/
if ( (uflg || lflg || dflg)
if ( (uflg || lflg || dflg
#ifdef ENABLE_SUBIDS
|| Vflg || Wflg
#endif /* ENABLE_SUBIDS */
)
&& (user_busy (user_name, user_id) != 0)) {
exit (E_USER_BUSY);
}
@@ -1871,7 +2174,11 @@ int main (int argc, char **argv)
*/
open_files ();
if ( cflg || dflg || eflg || fflg || gflg || Lflg || lflg || pflg
|| sflg || uflg || Uflg) {
|| sflg || uflg || Uflg
#ifdef ENABLE_SUBIDS
|| vflg || Vflg || wflg || Wflg
#endif /* ENABLE_SUBIDS */
) {
usr_update ();
}
if (Gflg || lflg) {

View File

@@ -5,7 +5,7 @@
Copyright (c) 1997 , Guy Maor <maor@ece.utexas.edu>
Copyright (c) 1999 - 2000, Marek Michałkiewicz
Copyright (c) 2002 - 2006, Tomasz Kłoczko
Copyright (c) 2007 - 2011, Nicolas François
Copyright (c) 2007 - 2013, Nicolas François
All rights reserved.
This program is free software; you can redistribute it and/or modify
@@ -25,7 +25,7 @@
#include <config.h>
#ident "$Id: vipw.c 3654 2011-12-09 21:35:57Z nekral-guest $"
#ident "$Id$"
#include <errno.h>
#include <getopt.h>
@@ -180,7 +180,10 @@ static void vipwexit (const char *msg, int syserr, int ret)
if (0 != syserr) {
fprintf (stderr, ": %s", strerror (err));
}
(void) fputs ("\n", stderr);
if ( (NULL != msg)
|| (0 != syserr)) {
(void) fputs ("\n", stderr);
}
if (!quiet) {
fprintf (stdout, _("%s: %s is unchanged\n"), Prog,
filename);
@@ -297,14 +300,25 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
/* use the system() call to invoke the editor so that it accepts
command line args in the EDITOR and VISUAL environment vars */
char *buf;
int status;
buf = (char *) malloc (strlen (editor) + strlen (fileedit) + 2);
snprintf (buf, strlen (editor) + strlen (fileedit) + 2,
"%s %s", editor, fileedit);
if (system (buf) != 0) {
fprintf (stderr, "%s: %s: %s\n", Prog, editor,
"%s %s", editor, fileedit);
status = system (buf);
if (-1 == status) {
fprintf (stderr, _("%s: %s: %s\n"), Prog, editor,
strerror (errno));
exit (1);
} else if ( WIFEXITED (status)
&& (WEXITSTATUS (status) != 0)) {
fprintf (stderr, _("%s: %s returned with status %d\n"),
Prog, editor, WEXITSTATUS (status));
exit (WEXITSTATUS (status));
} else if (WIFSIGNALED (status)) {
fprintf (stderr, _("%s: %s killed by signal %d\n"),
Prog, editor, WTERMSIG (status));
exit (1);
} else {
exit (0);
}
@@ -323,10 +337,15 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
}
}
if ( (-1 == pid)
|| (WIFEXITED (status) == 0)
|| (WEXITSTATUS (status) != 0)) {
if (-1 == pid) {
vipwexit (editor, 1, 1);
} else if ( WIFEXITED (status)
&& (WEXITSTATUS (status) != 0)) {
vipwexit (NULL, 0, WEXITSTATUS (status));
} else if (WIFSIGNALED (status)) {
fprintf (stderr, _("%s: %s killed by signal %d\n"),
Prog, editor, WTERMSIG(status));
vipwexit (NULL, 0, 1);
}
if (stat (fileedit, &st2) != 0) {
@@ -480,6 +499,10 @@ int main (int argc, char **argv)
usage (E_USAGE);
}
}
if (optind != argc) {
usage (E_USAGE);
}
}
if (do_vipw) {