2010-01-30 Paweł Hajdan, Jr. <phajdan.jr@gentoo.org>
* NEWS: Add support for TCB. * lib/tcbfuncs.h, lib/tcbfuncs.c, lib/Makefile.am: New library to support TCB. * lib/prototypes, libmisc/copydir.c (remove_tree): Add boolean parameter remove_root. * configure.in: Add conditional WITH_TCB. * src/userdel.c, src/usermod.c: Add support for TCB. Update call to remove_tree(). * src/pwconv.c, src/pwunconv.c: Should not be used with TCB enabled. * src/vipw.c: Add support for TCB. Update call to remove_tree(). * src/useradd.c: Add support for TCB. Open the shadow file outside of open_files(). * src/chage.c: Add support for TCB. * src/Makefile.am: Install passwd sgid shadow when TCB is enabled. * lib/getdefs.c, man/vipw.8.xml, man/login.defs.5.xml, man/login.defs/TCB_AUTH_GROUP.xml, man/login.defs/USE_TCB.xml, man/login.defs/TCB_SYMLINKS.xml, man/generate_mans.mak, man/generate_mans.deps, man/Makefile.am: New configuration parameters: TCB_AUTH_GROUP, TCB_SYMLINKS, USE_TCB. * lib/shadowio.c, lib/commonio.c: Add support for TCB.
This commit is contained in:
@@ -5,6 +5,7 @@ EXTRA_DIST = \
|
||||
ubindir = ${prefix}/bin
|
||||
usbindir = ${prefix}/sbin
|
||||
suidperms = 4755
|
||||
sgidperms = 2755
|
||||
|
||||
INCLUDES = \
|
||||
-I${top_srcdir}/lib \
|
||||
@@ -53,7 +54,13 @@ if ACCT_TOOLS_SETUID
|
||||
suidubins += chage chgpasswd chpasswd groupadd groupdel groupmod newusers useradd userdel usermod
|
||||
endif
|
||||
|
||||
if WITH_TCB
|
||||
suidubins -= passwd
|
||||
shadowsgidubins = passwd
|
||||
endif
|
||||
|
||||
LDADD = $(INTLLIBS) \
|
||||
$(LIBTCB) \
|
||||
$(top_builddir)/libmisc/libmisc.a \
|
||||
$(top_builddir)/lib/libshadow.la
|
||||
AM_CPPFLAGS = -DLOCALEDIR=\"$(datadir)/locale\"
|
||||
@@ -114,3 +121,9 @@ install-am: all-am
|
||||
for i in $(suidubins); do \
|
||||
chmod -f $(suidperms) $(DESTDIR)$(ubindir)/$$i; \
|
||||
done
|
||||
if WITH_TCB
|
||||
for i in $(shadowsgidubins); do \
|
||||
chown root:shadow $(DESTDIR)$(ubindir)/$$i; \
|
||||
chmod -f $(sgidperms) $(DESTDIR)$(ubindir)/$$i; \
|
||||
done
|
||||
endif
|
||||
|
@@ -56,6 +56,9 @@
|
||||
#include "defines.h"
|
||||
#include "pwio.h"
|
||||
#include "shadowio.h"
|
||||
#ifdef WITH_TCB
|
||||
#include "tcbfuncs.h"
|
||||
#endif
|
||||
/*@-exitarg@*/
|
||||
#include "exitcodes.h"
|
||||
|
||||
@@ -853,6 +856,10 @@ int main (int argc, char **argv)
|
||||
}
|
||||
|
||||
STRFCPY (user_name, pw->pw_name);
|
||||
#ifdef WITH_TCB
|
||||
if (!shadowtcb_set_user(pw->pw_name))
|
||||
fail_exit(E_NOPERM);
|
||||
#endif
|
||||
user_uid = pw->pw_uid;
|
||||
|
||||
sp = spw_locate (argv[optind]);
|
||||
|
@@ -133,6 +133,11 @@ int main (int argc, char **argv)
|
||||
|
||||
OPENLOG ("pwconv");
|
||||
|
||||
if (getdef_bool("USE_TCB")) {
|
||||
fprintf(stderr, _("%s: can't work with tcb enabled\n"), Prog);
|
||||
fail_exit(E_FAILURE);
|
||||
}
|
||||
|
||||
if (pw_lock () == 0) {
|
||||
fprintf (stderr,
|
||||
_("%s: cannot lock %s; try again later.\n"),
|
||||
|
@@ -93,6 +93,11 @@ int main (int argc, char **argv)
|
||||
|
||||
OPENLOG ("pwunconv");
|
||||
|
||||
if (getdef_bool("USE_TCB")) {
|
||||
fprintf(stderr, _("%s: can't work with tcb enabled\n"), Prog);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!spw_file_present ()) {
|
||||
/* shadow not installed, do nothing */
|
||||
exit (0);
|
||||
|
@@ -65,6 +65,9 @@
|
||||
#include "sgroupio.h"
|
||||
#endif
|
||||
#include "shadowio.h"
|
||||
#ifdef WITH_TCB
|
||||
#include "tcbfuncs.h"
|
||||
#endif
|
||||
|
||||
#ifndef SKEL_DIR
|
||||
#define SKEL_DIR "/etc/skel"
|
||||
@@ -192,6 +195,7 @@ static void grp_update (void);
|
||||
static void process_flags (int argc, char **argv);
|
||||
static void close_files (void);
|
||||
static void open_files (void);
|
||||
static void open_shadow (void);
|
||||
static void faillog_reset (uid_t);
|
||||
static void lastlog_reset (uid_t);
|
||||
static void usr_update (void);
|
||||
@@ -1429,21 +1433,8 @@ static void open_files (void)
|
||||
fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ());
|
||||
fail_exit (E_PW_UPDATE);
|
||||
}
|
||||
if (is_shadow_pwd) {
|
||||
if (spw_lock () == 0) {
|
||||
fprintf (stderr,
|
||||
_("%s: cannot lock %s; try again later.\n"),
|
||||
Prog, spw_dbname ());
|
||||
fail_exit (E_PW_UPDATE);
|
||||
}
|
||||
spw_locked = true;
|
||||
if (spw_open (O_RDWR) == 0) {
|
||||
fprintf (stderr,
|
||||
_("%s: cannot open %s\n"),
|
||||
Prog, spw_dbname ());
|
||||
fail_exit (E_PW_UPDATE);
|
||||
}
|
||||
}
|
||||
|
||||
/* shadow file will be opened by open_shadow(); */
|
||||
|
||||
/*
|
||||
* Lock and open the group file.
|
||||
@@ -1478,6 +1469,25 @@ static void open_files (void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void open_shadow (void)
|
||||
{
|
||||
if (!is_shadow_pwd)
|
||||
return;
|
||||
if (!spw_lock ()) {
|
||||
fprintf(stderr,
|
||||
_("%s: cannot lock shadow password file\n"),
|
||||
Prog);
|
||||
fail_exit(E_PW_UPDATE);
|
||||
}
|
||||
spw_locked = true;
|
||||
if (!spw_open (O_RDWR)) {
|
||||
fprintf(stderr,
|
||||
_("%s: cannot open shadow password file\n"),
|
||||
Prog);
|
||||
fail_exit(E_PW_UPDATE);
|
||||
}
|
||||
}
|
||||
|
||||
static char *empty_list = NULL;
|
||||
|
||||
/*
|
||||
@@ -1990,6 +2000,16 @@ int main (int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_TCB
|
||||
if (getdef_bool("USE_TCB")) {
|
||||
if (!shadowtcb_create(user_name, user_id)) {
|
||||
fprintf(stderr, "Failed to create tcb directory for %s\n", user_name);
|
||||
fail_exit (E_UID_IN_USE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
open_shadow();
|
||||
|
||||
/* do we have to add a group for that user? This is why we need to
|
||||
* open the group files in the open_files() function --gafton */
|
||||
if (Uflg) {
|
||||
|
@@ -59,6 +59,10 @@
|
||||
#ifdef SHADOWGRP
|
||||
#include "sgroupio.h"
|
||||
#endif
|
||||
#ifdef WITH_TCB
|
||||
#include <tcb.h>
|
||||
#include "tcbfuncs.h"
|
||||
#endif
|
||||
/*@-exitarg@*/
|
||||
#include "exitcodes.h"
|
||||
|
||||
@@ -107,6 +111,9 @@ static bool path_prefix (const char *, const char *);
|
||||
#endif
|
||||
static int is_owner (uid_t, const char *);
|
||||
static int remove_mailbox (void);
|
||||
#ifdef WITH_TCB
|
||||
static int remove_tcbdir (const char *user_name, uid_t user_id);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* usage - display usage message and exit
|
||||
@@ -731,6 +738,49 @@ static int remove_mailbox (void)
|
||||
return errors;
|
||||
}
|
||||
|
||||
#ifdef WITH_TCB
|
||||
static int remove_tcbdir (const char *user_name, uid_t user_id)
|
||||
{
|
||||
char *buf;
|
||||
int ret = 0;
|
||||
|
||||
if (!getdef_bool("USE_TCB"))
|
||||
return 0;
|
||||
|
||||
buf = malloc(strlen(TCB_DIR) + strlen(user_name) + 2);
|
||||
if (!buf) {
|
||||
fprintf(stderr, "Can't allocate memory, "
|
||||
"tcb entry for %s not removed.\n",
|
||||
user_name);
|
||||
return 1;
|
||||
}
|
||||
snprintf(buf, strlen(TCB_DIR) + strlen(user_name) + 2,
|
||||
TCB_DIR "/%s", user_name);
|
||||
if (!shadowtcb_drop_priv()) {
|
||||
perror("shadowtcb_drop_priv");
|
||||
free(buf);
|
||||
return 1;
|
||||
}
|
||||
/* Only remove directory contents with dropped privileges.
|
||||
* We will regain them and remove the user's tcb directory afterwards.
|
||||
*/
|
||||
if (remove_tree(buf, false)) {
|
||||
perror("remove_tree");
|
||||
shadowtcb_gain_priv();
|
||||
free(buf);
|
||||
return 1;
|
||||
}
|
||||
shadowtcb_gain_priv();
|
||||
free(buf);
|
||||
if (!shadowtcb_remove(user_name)) {
|
||||
fprintf(stderr, "Cannot remove tcb files for %s: %s\n",
|
||||
user_name, strerror(errno));
|
||||
ret = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* main - userdel command
|
||||
*/
|
||||
@@ -851,6 +901,10 @@ int main (int argc, char **argv)
|
||||
user_id = pwd->pw_uid;
|
||||
user_home = xstrdup (pwd->pw_dir);
|
||||
}
|
||||
#ifdef WITH_TCB
|
||||
if (!shadowtcb_set_user(user_name))
|
||||
exit (E_NOTFOUND);
|
||||
#endif
|
||||
#ifdef USE_NIS
|
||||
|
||||
/*
|
||||
@@ -951,7 +1005,7 @@ int main (int argc, char **argv)
|
||||
#endif
|
||||
|
||||
if (rflg) {
|
||||
if (remove_tree (user_home) != 0) {
|
||||
if (remove_tree (user_home, true) != 0) {
|
||||
fprintf (stderr,
|
||||
_("%s: error removing directory %s\n"),
|
||||
Prog, user_home);
|
||||
@@ -996,6 +1050,10 @@ int main (int argc, char **argv)
|
||||
user_cancel (user_name);
|
||||
close_files ();
|
||||
|
||||
#ifdef WITH_TCB
|
||||
errors += remove_tcbdir(user_name, user_id);
|
||||
#endif
|
||||
|
||||
nscd_flush_cache ("passwd");
|
||||
nscd_flush_cache ("group");
|
||||
|
||||
|
@@ -63,6 +63,9 @@
|
||||
#include "sgroupio.h"
|
||||
#endif
|
||||
#include "shadowio.h"
|
||||
#ifdef WITH_TCB
|
||||
#include "tcbfuncs.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* exit status values
|
||||
@@ -1438,7 +1441,7 @@ static void move_home (void)
|
||||
if (copy_tree (user_home, user_newhome,
|
||||
uflg ? (long int)user_newid : -1,
|
||||
gflg ? (long int)user_newgid : -1) == 0) {
|
||||
if (remove_tree (user_home) != 0) {
|
||||
if (remove_tree (user_home, true) != 0) {
|
||||
fprintf (stderr,
|
||||
_("%s: warning: failed to completely remove old home directory %s"),
|
||||
Prog, user_home);
|
||||
@@ -1456,7 +1459,7 @@ static void move_home (void)
|
||||
|
||||
/* TODO: do some cleanup if the copy
|
||||
* was started */
|
||||
(void) remove_tree (user_newhome);
|
||||
(void) remove_tree (user_newhome, true);
|
||||
}
|
||||
fprintf (stderr,
|
||||
_("%s: cannot rename directory %s to %s\n"),
|
||||
@@ -1655,7 +1658,7 @@ static void move_mailbox (void)
|
||||
return;
|
||||
}
|
||||
if (uflg) {
|
||||
if (fchown (fd, user_newid, (gid_t) - 1) < 0) {
|
||||
if (fchown (fd, user_newid, (gid_t) -1) < 0) {
|
||||
perror (_("failed to change mailbox owner"));
|
||||
}
|
||||
#ifdef WITH_AUDIT
|
||||
@@ -1770,6 +1773,11 @@ int main (int argc, char **argv)
|
||||
#endif /* USE_PAM */
|
||||
#endif /* ACCT_TOOLS_SETUID */
|
||||
|
||||
#ifdef WITH_TCB
|
||||
if (!shadowtcb_set_user(user_name))
|
||||
exit(E_PW_UPDATE);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Do the hard stuff - open the files, change the user entries,
|
||||
* change the home directory, then close and update the files.
|
||||
@@ -1784,6 +1792,13 @@ int main (int argc, char **argv)
|
||||
}
|
||||
close_files ();
|
||||
|
||||
#ifdef WITH_TCB
|
||||
if ((user_newname || user_newid != -1) &&
|
||||
!shadowtcb_move(user_newname, user_newid)) {
|
||||
exit(E_PW_UPDATE);
|
||||
}
|
||||
#endif
|
||||
|
||||
nscd_flush_cache ("passwd");
|
||||
nscd_flush_cache ("group");
|
||||
|
||||
|
108
src/vipw.c
108
src/vipw.c
@@ -48,6 +48,10 @@
|
||||
#include "shadowio.h"
|
||||
/*@-exitarg@*/
|
||||
#include "exitcodes.h"
|
||||
#ifdef WITH_TCB
|
||||
#include <tcb.h>
|
||||
#include "tcbfuncs.h"
|
||||
#endif
|
||||
|
||||
#define MSG_WARN_EDIT_OTHER_FILE _( \
|
||||
"You have modified %s.\n"\
|
||||
@@ -62,6 +66,8 @@ static bool filelocked = false;
|
||||
static bool createedit = false;
|
||||
static int (*unlock) (void);
|
||||
static bool quiet = false;
|
||||
static const char *user = NULL;
|
||||
static bool tcb_mode = false;
|
||||
|
||||
/* local function prototypes */
|
||||
static void usage (int status);
|
||||
@@ -83,6 +89,9 @@ static void usage (int status)
|
||||
" -p, --passwd edit passwd database\n"
|
||||
" -q, --quiet quiet mode\n"
|
||||
" -s, --shadow edit shadow or gshadow database\n"
|
||||
#ifdef WITH_TCB
|
||||
" -u, --user which user's tcb shadow file to edit\n"
|
||||
#endif
|
||||
"\n"), (E_SUCCESS != status) ? stderr : stdout);
|
||||
exit (status);
|
||||
}
|
||||
@@ -175,6 +184,8 @@ static void vipwexit (const char *msg, int syserr, int ret)
|
||||
#define DEFAULT_EDITOR "vi"
|
||||
#endif
|
||||
|
||||
#define SHADOWTCB_SCRATCHDIR ":tmp"
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
@@ -187,9 +198,23 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
|
||||
int status;
|
||||
FILE *f;
|
||||
char filebackup[1024], fileedit[1024];
|
||||
char *to_rename;
|
||||
|
||||
snprintf (filebackup, sizeof filebackup, "%s-", file);
|
||||
snprintf (fileedit, sizeof fileedit, "%s.edit", file);
|
||||
#ifdef WITH_TCB
|
||||
if (tcb_mode) {
|
||||
if (mkdir(TCB_DIR "/" SHADOWTCB_SCRATCHDIR, 0700) && errno != EEXIST)
|
||||
vipwexit (_("failed to create scratch directory"), errno, 1);
|
||||
if (!shadowtcb_drop_priv())
|
||||
vipwexit (_("failed to drop privileges"), errno, 1);
|
||||
snprintf(fileedit, sizeof fileedit,
|
||||
TCB_DIR "/" SHADOWTCB_SCRATCHDIR "/.vipw.shadow.%s", user);
|
||||
} else {
|
||||
#endif
|
||||
snprintf (fileedit, sizeof fileedit, "%s.edit", file);
|
||||
#ifdef WITH_TCB
|
||||
}
|
||||
#endif
|
||||
unlock = file_unlock;
|
||||
filename = file;
|
||||
fileeditname = fileedit;
|
||||
@@ -212,11 +237,19 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
|
||||
vipwexit (_("setfscreatecon () failed"), errno, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef WITH_TCB
|
||||
if (tcb_mode && !shadowtcb_gain_priv())
|
||||
vipwexit (_("failed to gain privileges"), errno, 1);
|
||||
#endif
|
||||
if (file_lock () == 0) {
|
||||
vipwexit (_("Couldn't lock file"), errno, 5);
|
||||
}
|
||||
filelocked = true;
|
||||
#ifdef WITH_TCB
|
||||
if (tcb_mode && !shadowtcb_drop_priv())
|
||||
vipwexit (_("failed to drop privileges"), errno, 1);
|
||||
#endif
|
||||
|
||||
/* edited copy has same owners, perm */
|
||||
if (stat (file, &st1) != 0) {
|
||||
@@ -226,6 +259,10 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
|
||||
if (NULL == f) {
|
||||
vipwexit (file, 1, 1);
|
||||
}
|
||||
#ifdef WITH_TCB
|
||||
if (tcb_mode && !shadowtcb_gain_priv())
|
||||
vipwexit (_("failed to gain privileges"), errno, 1);
|
||||
#endif
|
||||
if (create_backup_file (f, fileedit, &st1) != 0) {
|
||||
vipwexit (_("Couldn't make backup"), errno, 1);
|
||||
}
|
||||
@@ -300,15 +337,49 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
|
||||
* without saving). Use pwck or grpck to do the check. --marekm
|
||||
*/
|
||||
createedit = false;
|
||||
#ifdef WITH_TCB
|
||||
if (tcb_mode) {
|
||||
if (!(f = fopen(fileedit, "r")))
|
||||
vipwexit (_("failed to open scratch file"), errno, 1);
|
||||
if (unlink(fileedit))
|
||||
vipwexit (_("failed to unlink scratch file"), errno, 1);
|
||||
if (!shadowtcb_drop_priv())
|
||||
vipwexit (_("failed to drop privileges"), errno, 1);
|
||||
if (stat(file, &st1))
|
||||
vipwexit (_("failed to stat edited file"), errno, 1);
|
||||
to_rename = malloc(strlen(file) + 2);
|
||||
if (!to_rename)
|
||||
vipwexit (_("failed to allocate memory"), errno, 1);
|
||||
snprintf(to_rename, strlen(file) + 2, "%s+", file);
|
||||
if (create_backup_file(f, to_rename, &st1)) {
|
||||
free(to_rename);
|
||||
vipwexit (_("failed to create backup file"), errno, 1);
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
to_rename = fileedit;
|
||||
#ifdef WITH_TCB
|
||||
}
|
||||
#endif
|
||||
unlink (filebackup);
|
||||
link (file, filebackup);
|
||||
if (rename (fileedit, file) == -1) {
|
||||
if (rename (to_rename, file) == -1) {
|
||||
fprintf (stderr,
|
||||
_("%s: can't restore %s: %s (your changes are in %s)\n"),
|
||||
progname, file, strerror (errno), fileedit);
|
||||
progname, file, strerror (errno), to_rename);
|
||||
if (tcb_mode)
|
||||
free(to_rename);
|
||||
vipwexit (0, 0, 1);
|
||||
}
|
||||
|
||||
#ifdef WITH_TCB
|
||||
if (tcb_mode) {
|
||||
free(to_rename);
|
||||
if (!shadowtcb_gain_priv())
|
||||
vipwexit (_("failed to gain privileges"), errno, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((*file_unlock) () == 0) {
|
||||
fprintf (stderr, _("%s: failed to unlock %s\n"), progname, fileeditname);
|
||||
SYSLOG ((LOG_ERR, "failed to unlock %s", fileeditname));
|
||||
@@ -343,11 +414,18 @@ int main (int argc, char **argv)
|
||||
{"passwd", no_argument, NULL, 'p'},
|
||||
{"quiet", no_argument, NULL, 'q'},
|
||||
{"shadow", no_argument, NULL, 's'},
|
||||
#ifdef WITH_TCB
|
||||
{"user", required_argument, NULL, 'u'},
|
||||
#endif
|
||||
{NULL, 0, NULL, '\0'}
|
||||
};
|
||||
while ((c =
|
||||
getopt_long (argc, argv, "ghpqs",
|
||||
long_options, NULL)) != -1) {
|
||||
while ((c = getopt_long (argc, argv,
|
||||
#ifdef WITH_TCB
|
||||
"ghpqsu:",
|
||||
#else
|
||||
"ghpqs",
|
||||
#endif
|
||||
long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'g':
|
||||
do_vipw = false;
|
||||
@@ -364,6 +442,9 @@ int main (int argc, char **argv)
|
||||
case 's':
|
||||
editshadow = true;
|
||||
break;
|
||||
case 'u':
|
||||
user = optarg;
|
||||
break;
|
||||
default:
|
||||
usage (E_USAGE);
|
||||
}
|
||||
@@ -372,9 +453,20 @@ int main (int argc, char **argv)
|
||||
|
||||
if (do_vipw) {
|
||||
if (editshadow) {
|
||||
vipwedit (SHADOW_FILE, spw_lock, spw_unlock);
|
||||
#ifdef WITH_TCB
|
||||
if (getdef_bool("USE_TCB") && user) {
|
||||
if (!shadowtcb_set_user(user)) {
|
||||
fprintf (stderr,
|
||||
_("%s: failed to find tcb directory for %s\n"),
|
||||
progname, user);
|
||||
return E_SHADOW_NOTFOUND;
|
||||
}
|
||||
tcb_mode = true;
|
||||
}
|
||||
#endif
|
||||
vipwedit (spw_dbname (), spw_lock, spw_unlock);
|
||||
printf (MSG_WARN_EDIT_OTHER_FILE,
|
||||
SHADOW_FILE,
|
||||
spw_dbname (),
|
||||
PASSWD_FILE,
|
||||
"vipw");
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user