Imported Upstream version 4.2
This commit is contained in:
35
src/.gitignore
vendored
Normal file
35
src/.gitignore
vendored
Normal 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
|
||||
@@ -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)
|
||||
|
||||
1099
src/Makefile.in
1099
src/Makefile.in
File diff suppressed because it is too large
Load Diff
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
2
src/id.c
2
src/id.c
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
/*
|
||||
|
||||
@@ -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
183
src/newgidmap.c
Normal 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;
|
||||
}
|
||||
12
src/newgrp.c
12
src/newgrp.c
@@ -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
183
src/newuidmap.c
Normal 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;
|
||||
}
|
||||
193
src/newusers.c
193
src/newusers.c
@@ -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 */
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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>
|
||||
|
||||
25
src/passwd.c
25
src/passwd.c
@@ -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 */
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
23
src/su.c
23
src/su.c
@@ -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. */
|
||||
|
||||
@@ -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>
|
||||
|
||||
164
src/useradd.c
164
src/useradd.c
@@ -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) {
|
||||
|
||||
133
src/userdel.c
133
src/userdel.c
@@ -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.
|
||||
|
||||
323
src/usermod.c
323
src/usermod.c
@@ -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) {
|
||||
|
||||
41
src/vipw.c
41
src/vipw.c
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user