[Pkg-shadow-commits] r3095 - in upstream/trunk: . lib libmisc man man/login.defs.d src
Nicolas FRANÇOIS
nekral-guest at alioth.debian.org
Thu Mar 4 18:11:15 UTC 2010
Author: nekral-guest
Date: 2010-03-04 18:11:13 +0000 (Thu, 04 Mar 2010)
New Revision: 3095
Added:
upstream/trunk/lib/tcbfuncs.c
upstream/trunk/lib/tcbfuncs.h
upstream/trunk/man/login.defs.d/TCB_AUTH_GROUP.xml
upstream/trunk/man/login.defs.d/TCB_SYMLINKS.xml
upstream/trunk/man/login.defs.d/USE_TCB.xml
Modified:
upstream/trunk/ChangeLog
upstream/trunk/NEWS
upstream/trunk/configure.in
upstream/trunk/lib/Makefile.am
upstream/trunk/lib/commonio.c
upstream/trunk/lib/getdef.c
upstream/trunk/lib/prototypes.h
upstream/trunk/lib/shadowio.c
upstream/trunk/libmisc/copydir.c
upstream/trunk/man/Makefile.am
upstream/trunk/man/generate_mans.deps
upstream/trunk/man/generate_mans.mak
upstream/trunk/man/login.defs.5.xml
upstream/trunk/man/vipw.8.xml
upstream/trunk/src/Makefile.am
upstream/trunk/src/chage.c
upstream/trunk/src/pwconv.c
upstream/trunk/src/pwunconv.c
upstream/trunk/src/useradd.c
upstream/trunk/src/userdel.c
upstream/trunk/src/usermod.c
upstream/trunk/src/vipw.c
Log:
2010-01-30 Pawe?\197?\130 Hajdan, Jr. <phajdan.jr at 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.
Modified: upstream/trunk/ChangeLog
===================================================================
--- upstream/trunk/ChangeLog 2010-01-24 17:30:36 UTC (rev 3094)
+++ upstream/trunk/ChangeLog 2010-03-04 18:11:13 UTC (rev 3095)
@@ -1,9 +1,32 @@
-2009-01-24 Nicolas François <nicolas.francois at centraliens.net>
+2010-01-30 Paweł Hajdan, Jr. <phajdan.jr at 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.
+
+2010-01-24 Nicolas François <nicolas.francois at centraliens.net>
+
* libmisc/env.c: Fix sanitize_env() noslash support. This fixes
Alioth#311740.
-2009-01-24 Nicolas François <nicolas.francois at centraliens.net>
+2010-01-24 Nicolas François <nicolas.francois at centraliens.net>
* src/su.c: Do not sanitize the environment. This breaks
--preserve-environment. This sanitation was disabled on Debian
@@ -12,11 +35,11 @@
Unixes will handle setuid executables properly. This fixes
Alioth#312287.
-2009-01-24 Nicolas François <nicolas.francois at centraliens.net>
+2010-01-24 Nicolas François <nicolas.francois at centraliens.net>
* libmisc/setupenv.c: Fix typo from 2009-11-01.
-2009-01-24 Paweł Hajdan, Jr. <phajdan.jr at gentoo.org>
+2010-01-24 Paweł Hajdan, Jr. <phajdan.jr at gentoo.org>
* configure.in: Add support for TCB in configure.in. Actual TCB
support will follow.
Modified: upstream/trunk/NEWS
===================================================================
--- upstream/trunk/NEWS 2010-01-24 17:30:36 UTC (rev 3094)
+++ upstream/trunk/NEWS 2010-03-04 18:11:13 UTC (rev 3095)
@@ -5,6 +5,7 @@
- general
* report usage error to stderr, but report usage help to stdout (and return
zero) when explicitly requested (e.g. with --help).
+ * initial support for tcb (http://openwall.com/tcb/).
- groupmod
* Fixed groupmod when configured with --enable-account-tools-setuid.
Modified: upstream/trunk/configure.in
===================================================================
--- upstream/trunk/configure.in 2010-01-24 17:30:36 UTC (rev 3094)
+++ upstream/trunk/configure.in 2010-03-04 18:11:13 UTC (rev 3095)
@@ -405,6 +405,7 @@
with_tcb="no"
fi
fi
+AM_CONDITIONAL(WITH_TCB, test x$with_tcb = xyes)
AC_SUBST(LIBPAM)
if test "$with_libpam" != "no"; then
Modified: upstream/trunk/lib/Makefile.am
===================================================================
--- upstream/trunk/lib/Makefile.am 2010-01-24 17:30:36 UTC (rev 3094)
+++ upstream/trunk/lib/Makefile.am 2010-03-04 18:11:13 UTC (rev 3095)
@@ -49,6 +49,10 @@
shadowmem.c \
utent.c
+if WITH_TCB
+libshadow_la_SOURCES += tcbfuncs.c tcbfuncs.h
+endif
+
# These files are unneeded for some reason, listed in
# order of appearance:
#
Modified: upstream/trunk/lib/commonio.c
===================================================================
--- upstream/trunk/lib/commonio.c 2010-01-24 17:30:36 UTC (rev 3094)
+++ upstream/trunk/lib/commonio.c 2010-03-04 18:11:13 UTC (rev 3095)
@@ -48,6 +48,9 @@
#ifdef WITH_SELINUX
#include <selinux/selinux.h>
#endif
+#ifdef WITH_TCB
+#include <tcb.h>
+#endif
#include "prototypes.h"
#include "commonio.h"
@@ -533,6 +536,7 @@
void *eptr = NULL;
int flags = mode;
size_t buflen;
+ int fd;
int saved_errno;
mode &= ~O_CREAT;
@@ -553,7 +557,24 @@
db->cursor = NULL;
db->changed = false;
- db->fp = fopen (db->filename, db->readonly ? "r" : "r+");
+ fd = open(db->filename, (db->readonly ? O_RDONLY : O_RDWR) |
+ O_NOCTTY | O_NONBLOCK | O_NOFOLLOW);
+ saved_errno = errno;
+ db->fp = NULL;
+ if (fd >= 0) {
+#ifdef WITH_TCB
+ if (tcb_is_suspect(fd)) {
+ close(fd);
+ errno = EINVAL;
+ return 0;
+ }
+#endif
+ db->fp = fdopen(fd, db->readonly ? "r" : "r+");
+ saved_errno = errno;
+ if (!db->fp)
+ close(fd);
+ }
+ errno = saved_errno;
/*
* If O_CREAT was specified and the file didn't exist, it will be
Modified: upstream/trunk/lib/getdef.c
===================================================================
--- upstream/trunk/lib/getdef.c 2010-01-24 17:30:36 UTC (rev 3094)
+++ upstream/trunk/lib/getdef.c 2010-03-04 18:11:13 UTC (rev 3095)
@@ -124,6 +124,11 @@
{"SYSLOG_SG_ENAB", NULL},
{"SYSLOG_SU_ENAB", NULL},
#endif
+#ifdef WITH_TCB
+ {"TCB_AUTH_GROUP", NULL},
+ {"TCB_SYMLINKS", NULL},
+ {"USE_TCB", NULL},
+#endif
{NULL, NULL}
};
Modified: upstream/trunk/lib/prototypes.h
===================================================================
--- upstream/trunk/lib/prototypes.h 2010-01-24 17:30:36 UTC (rev 3094)
+++ upstream/trunk/lib/prototypes.h 2010-03-04 18:11:13 UTC (rev 3095)
@@ -117,7 +117,7 @@
/* copydir.c */
extern int copy_tree (const char *src_root, const char *dst_root,
long int uid, long int gid);
-extern int remove_tree (const char *root);
+extern int remove_tree (const char *root, bool remove_root);
#ifdef WITH_SELINUX
extern int selinux_file_context (const char *dst_name);
Modified: upstream/trunk/lib/shadowio.c
===================================================================
--- upstream/trunk/lib/shadowio.c 2010-01-24 17:30:36 UTC (rev 3094)
+++ upstream/trunk/lib/shadowio.c 2010-03-04 18:11:13 UTC (rev 3095)
@@ -41,6 +41,10 @@
#include <stdio.h>
#include "commonio.h"
#include "shadowio.h"
+#ifdef WITH_TCB
+#include <tcb.h>
+#include "tcbfuncs.h"
+#endif
static /*@null@*/ /*@only@*/void *shadow_dup (const void *ent)
{
@@ -120,12 +124,40 @@
int spw_lock (void)
{
- return commonio_lock (&shadow_db);
+#ifdef WITH_TCB
+ int retval = 0;
+
+ if (!getdef_bool("USE_TCB"))
+#endif
+ return commonio_lock (&shadow_db);
+#ifdef WITH_TCB
+ if (!shadowtcb_drop_priv())
+ return 0;
+ if (lckpwdf_tcb(shadow_db.filename) == 0) {
+ shadow_db.locked = 1;
+ retval = 1;
+ }
+ if (!shadowtcb_gain_priv())
+ return 0;
+ return retval;
+#endif
}
int spw_open (int mode)
{
- return commonio_open (&shadow_db, mode);
+ int retval = 0;
+#ifdef WITH_TCB
+ int use_tcb = getdef_bool("USE_TCB");
+
+ if (use_tcb && !shadowtcb_drop_priv() != 0)
+ return 0;
+#endif
+ retval = commonio_open (&shadow_db, mode);
+#ifdef WITH_TCB
+ if (use_tcb && !shadowtcb_gain_priv() != 0)
+ return 0;
+#endif
+ return retval;
}
/*@observer@*/ /*@null@*/const struct spwd *spw_locate (const char *name)
@@ -155,12 +187,40 @@
int spw_close (void)
{
- return commonio_close (&shadow_db);
+ int retval = 0;
+#ifdef WITH_TCB
+ int use_tcb = getdef_bool("USE_TCB");
+
+ if (use_tcb && !shadowtcb_drop_priv() != 0)
+ return 0;
+#endif
+ retval = commonio_close (&shadow_db);
+#ifdef WITH_TCB
+ if (use_tcb && !shadowtcb_gain_priv() != 0)
+ return 0;
+#endif
+ return retval;
}
int spw_unlock (void)
{
- return commonio_unlock (&shadow_db);
+#ifdef WITH_TCB
+ int retval = 0;
+
+ if (!getdef_bool("USE_TCB"))
+#endif
+ return commonio_unlock (&shadow_db);
+#ifdef WITH_TCB
+ if (!shadowtcb_drop_priv())
+ return 0;
+ if (ulckpwdf_tcb() == 0) {
+ shadow_db.locked = 0;
+ retval = 1;
+ }
+ if (!shadowtcb_gain_priv())
+ return 0;
+ return retval;
+#endif
}
struct commonio_entry *__spw_get_head (void)
@@ -176,5 +236,9 @@
/* Sort with respect to passwd ordering. */
int spw_sort ()
{
+#ifdef WITH_TCB
+ if (getdef_bool("USE_TCB"))
+ return 0;
+#endif
return commonio_sort_wrt (&shadow_db, __pw_get_db ());
}
Added: upstream/trunk/lib/tcbfuncs.c
===================================================================
--- upstream/trunk/lib/tcbfuncs.c (rev 0)
+++ upstream/trunk/lib/tcbfuncs.c 2010-03-04 18:11:13 UTC (rev 3095)
@@ -0,0 +1,501 @@
+/*
+ * Copyright (c) 2001 Rafal Wojtczuk, Solar Designer
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * 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.
+ */
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <tcb.h>
+#include <unistd.h>
+
+#include "config.h"
+
+#include "defines.h"
+#include "getdef.h"
+
+#define SHADOWTCB_HASH_BY 1000
+#define SHADOWTCB_LOCK_SUFFIX ".lock"
+
+static char *stored_tcb_user = NULL;
+
+int shadowtcb_drop_priv()
+{
+ if (!getdef_bool("USE_TCB"))
+ return 1;
+
+ if (stored_tcb_user)
+ return !tcb_drop_priv(stored_tcb_user);
+
+ return 0;
+}
+
+int shadowtcb_gain_priv()
+{
+ if (!getdef_bool("USE_TCB"))
+ return 1;
+ return !tcb_gain_priv();
+}
+
+/* In case something goes wrong, we return immediately, not polluting the
+ * code with free(). All errors are fatal, so the application is expected
+ * to exit soon.
+ */
+#define OUT_OF_MEMORY do { \
+ fprintf(stderr, "Out of memory.\n"); \
+ fflush(stderr); \
+ return 0; \
+} while(0)
+
+/* Returns user's tcb directory path relative to TCB_DIR. */
+static char *shadowtcb_path_rel(const char *name, uid_t uid)
+{
+ char *ret;
+
+ if (!getdef_bool("TCB_SYMLINKS") || uid < SHADOWTCB_HASH_BY) {
+ asprintf(&ret, "%s", name);
+ } else if (uid < SHADOWTCB_HASH_BY * SHADOWTCB_HASH_BY) {
+ asprintf(&ret, ":%dK/%s", uid / SHADOWTCB_HASH_BY, name);
+ } else {
+ asprintf(&ret, ":%dM/:%dK/%s",
+ uid / (SHADOWTCB_HASH_BY * SHADOWTCB_HASH_BY),
+ (uid % (SHADOWTCB_HASH_BY * SHADOWTCB_HASH_BY)) / SHADOWTCB_HASH_BY,
+ name);
+ }
+ if (!ret) {
+ OUT_OF_MEMORY;
+ }
+ return ret;
+}
+
+static char *shadowtcb_path_rel_existing(const char *name)
+{
+ char *path, *rval;
+ struct stat st;
+ char link[8192];
+ int ret;
+
+ asprintf(&path, TCB_DIR "/%s", name);
+ if (!path) {
+ OUT_OF_MEMORY;
+ }
+ if (lstat(path, &st)) {
+ fprintf(stderr, "Cannot stat %s: %s\n", path, strerror(errno));
+ free(path);
+ return NULL;
+ }
+ if (S_ISDIR(st.st_mode)) {
+ free(path);
+ rval = strdup(name);
+ if (!rval) {
+ OUT_OF_MEMORY;
+ }
+ return rval;
+ }
+ if (!S_ISLNK(st.st_mode)) {
+ fprintf(stderr, "%s is neither a directory, nor a symlink.\n", path);
+ free(path);
+ return NULL;
+ }
+ ret = readlink(path, link, sizeof(link) - 1);
+ free(path);
+ if (ret == -1) {
+ perror("readlink");
+ return NULL;
+ }
+ if (ret >= sizeof(link) - 1) {
+ link[sizeof(link) - 1] = '\0';
+ fprintf(stderr, "Suspiciously long symlink: %s\n", link);
+ return NULL;
+ }
+ link[ret] = '\0';
+ rval = strdup(link);
+ if (!rval) {
+ OUT_OF_MEMORY;
+ }
+ return rval;
+}
+
+static char *shadowtcb_path(const char *name, uid_t uid)
+{
+ char *ret, *rel;
+
+ if (!(rel = shadowtcb_path_rel(name, uid)))
+ return 0;
+ asprintf(&ret, TCB_DIR "/%s", rel);
+ free(rel);
+ if (!ret) {
+ OUT_OF_MEMORY;
+ }
+ return ret;
+}
+
+static char *shadowtcb_path_existing(const char *name)
+{
+ char *ret, *rel;
+
+ if (!(rel = shadowtcb_path_rel_existing(name)))
+ return 0;
+ asprintf(&ret, TCB_DIR "/%s", rel);
+ free(rel);
+ if (!ret) {
+ OUT_OF_MEMORY;
+ }
+ return ret;
+}
+
+static int mkdir_leading(const char *name, uid_t uid)
+{
+ char *ind, *dir, *ptr, *path = shadowtcb_path_rel(name, uid);
+ struct stat st;
+
+ if (!path)
+ return 0;
+ ptr = path;
+ if (stat(TCB_DIR, &st)) {
+ perror("stat");
+ goto out_free_path;
+ }
+ while ((ind = strchr(ptr, '/'))) {
+ *ind = 0;
+ asprintf(&dir, TCB_DIR "/%s", path);
+ if (!dir) {
+ OUT_OF_MEMORY;
+ }
+ if (mkdir(dir, 0700) && errno != EEXIST) {
+ perror("mkdir");
+ goto out_free_dir;
+ }
+ if (chown(dir, 0, st.st_gid)) {
+ perror("chown");
+ goto out_free_dir;
+ }
+ if (chmod(dir, 0711)) {
+ perror("chmod");
+ goto out_free_dir;
+ }
+ free(dir);
+ *ind = '/';
+ ptr = ind + 1;
+ }
+ free(path);
+ return 1;
+out_free_dir:
+ free(dir);
+out_free_path:
+ free(path);
+ return 0;
+}
+
+static int unlink_suffs(const char *user)
+{
+ static char *suffs[] = { "+", "-", SHADOWTCB_LOCK_SUFFIX };
+ char *tmp;
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ asprintf(&tmp, TCB_FMT "%s", user, suffs[i]);
+ if (!tmp) {
+ OUT_OF_MEMORY;
+ }
+ if (unlink(tmp) && errno != ENOENT) {
+ fprintf(stderr, "unlink: %s: %s\n", tmp,
+ strerror(errno));
+ free(tmp);
+ return 0;
+ }
+ free(tmp);
+ }
+
+ return 1;
+}
+
+/* path should be a relative existing tcb directory */
+static int rmdir_leading(char *path)
+{
+ char *ind, *dir;
+ int ret = 1;
+ while ((ind = strrchr(path, '/'))) {
+ *ind = 0;
+ asprintf(&dir, TCB_DIR "/%s", path);
+ if (!dir) {
+ OUT_OF_MEMORY;
+ }
+ if (rmdir(dir)) {
+ if (errno != ENOTEMPTY) {
+ perror("rmdir");
+ ret = 0;
+ }
+ free(dir);
+ break;
+ }
+ free(dir);
+ }
+ return ret;
+}
+
+static int move_dir(const char *user_newname, uid_t user_newid)
+{
+ char *olddir = NULL, *newdir = NULL;
+ char *real_old_dir = NULL, *real_new_dir = NULL;
+ char *real_old_dir_rel = NULL, *real_new_dir_rel = NULL;
+ uid_t old_uid, the_newid;
+ struct stat oldmode;
+ int ret = 0;
+
+ asprintf(&olddir, TCB_DIR "/%s", stored_tcb_user);
+ if (!olddir)
+ goto out_free_nomem;
+ if (stat(olddir, &oldmode)) {
+ perror("stat");
+ goto out_free;
+ }
+ old_uid = oldmode.st_uid;
+ the_newid = (user_newid == -1) ? old_uid : user_newid;
+ if (!(real_old_dir = shadowtcb_path_existing(stored_tcb_user)))
+ goto out_free;
+ if (!(real_new_dir = shadowtcb_path(user_newname, the_newid)))
+ goto out_free;
+ if (!strcmp(real_old_dir, real_new_dir)) {
+ ret = 1;
+ goto out_free;
+ }
+ if (!(real_old_dir_rel = shadowtcb_path_rel_existing(stored_tcb_user)))
+ goto out_free;
+ if (!mkdir_leading(user_newname, the_newid))
+ goto out_free;
+ if (rename(real_old_dir, real_new_dir)) {
+ perror("rename");
+ goto out_free;
+ }
+ if (!rmdir_leading(real_old_dir_rel))
+ goto out_free;
+ if (unlink(olddir) && errno != ENOENT) {
+ perror("unlink");
+ goto out_free;
+ }
+ asprintf(&newdir, TCB_DIR "/%s", user_newname);
+ if (!newdir)
+ goto out_free_nomem;
+ if (!(real_new_dir_rel = shadowtcb_path_rel(user_newname, the_newid)))
+ goto out_free;
+ if (strcmp(real_new_dir, newdir) && symlink(real_new_dir_rel, newdir)) {
+ perror("symlink");
+ goto out_free;
+ }
+ ret = 1;
+ goto out_free;
+out_free_nomem:
+ fprintf(stderr, "Out of memory\n");
+ fflush(stderr);
+out_free:
+ free(olddir);
+ free(newdir);
+ free(real_old_dir);
+ free(real_new_dir);
+ free(real_old_dir_rel);
+ free(real_new_dir_rel);
+ return ret;
+}
+
+int shadowtcb_set_user(const char* name)
+{
+ char *buf;
+ int retval;
+
+ if (!getdef_bool("USE_TCB"))
+ return 1;
+
+ if (stored_tcb_user)
+ free(stored_tcb_user);
+
+ stored_tcb_user = strdup(name);
+ if (!stored_tcb_user) {
+ OUT_OF_MEMORY;
+ }
+ asprintf(&buf, TCB_FMT, name);
+ if (!buf) {
+ OUT_OF_MEMORY;
+ }
+
+ retval = spw_setdbname(buf);
+ free(buf);
+ return retval;
+}
+
+/* tcb directory must be empty before shadowtcb_remove is called. */
+int shadowtcb_remove(const char *name)
+{
+ int ret = 1;
+ char *path = shadowtcb_path_existing(name);
+ char *rel = shadowtcb_path_rel_existing(name);
+ if (!path || !rel || rmdir(path))
+ return 0;
+ if (!rmdir_leading(rel))
+ return 0;
+ free(path);
+ free(rel);
+ asprintf(&path, TCB_DIR "/%s", name);
+ if (!path) {
+ OUT_OF_MEMORY;
+ }
+ if (unlink(path) && errno != ENOENT)
+ ret = 0;
+ free(path);
+ return ret;
+}
+
+int shadowtcb_move(const char *user_newname, uid_t user_newid)
+{
+ struct stat dirmode, filemode;
+ char *tcbdir, *shadow;
+ int ret = 0;
+
+ if (!getdef_bool("USE_TCB"))
+ return 1;
+ if (!user_newname)
+ user_newname = stored_tcb_user;
+ if (!move_dir(user_newname, user_newid))
+ return 0;
+ if (user_newid == -1)
+ return 1;
+ asprintf(&tcbdir, TCB_DIR "/%s", user_newname);
+ asprintf(&shadow, TCB_FMT, user_newname);
+ if (!tcbdir || !shadow) {
+ OUT_OF_MEMORY;
+ }
+ if (stat(tcbdir, &dirmode)) {
+ perror("stat");
+ goto out_free;
+ }
+ if (chown(tcbdir, 0, 0)) {
+ perror("chown");
+ goto out_free;
+ }
+ if (chmod(tcbdir, 0700)) {
+ perror("chmod");
+ goto out_free;
+ }
+ if (lstat(shadow, &filemode)) {
+ if (errno != ENOENT) {
+ perror("lstat");
+ goto out_free;
+ }
+ fprintf(stderr,
+ "Warning, user %s has no tcb shadow file.\n",
+ user_newname);
+ } else {
+ if (!S_ISREG(filemode.st_mode) ||
+ filemode.st_nlink != 1) {
+ fprintf(stderr,
+ "Emergency: %s's tcb shadow is not a regular file"
+ " with st_nlink=1.\n"
+ "The account is left locked.\n",
+ user_newname);
+ goto out_free;
+ }
+ if (chown(shadow, user_newid, filemode.st_gid)) {
+ perror("chown");
+ goto out_free;
+ }
+ if (chmod(shadow, filemode.st_mode & 07777)) {
+ perror("chmod");
+ goto out_free;
+ }
+ }
+ if (!unlink_suffs(user_newname))
+ goto out_free;
+ if (chown(tcbdir, user_newid, dirmode.st_gid)) {
+ perror("chown");
+ goto out_free;
+ }
+ ret = 1;
+out_free:
+ free(tcbdir);
+ free(shadow);
+ return ret;
+}
+
+int shadowtcb_create(const char *name, uid_t uid)
+{
+ char *dir, *shadow;
+ struct stat tcbdir_stat;
+ gid_t shadowgid, authgid;
+ struct group *gr;
+ int fd, ret = 0;
+
+ if (!getdef_bool("USE_TCB"))
+ return 1;
+ if (stat(TCB_DIR, &tcbdir_stat)) {
+ perror("stat");
+ return 0;
+ }
+ shadowgid = tcbdir_stat.st_gid;
+ if (getdef_bool("TCB_AUTH_GROUP") &&
+ (gr = getgrnam("auth"))) {
+ authgid = gr->gr_gid;
+ } else {
+ authgid = shadowgid;
+ }
+
+ asprintf(&dir, TCB_DIR "/%s", name);
+ asprintf(&shadow, TCB_FMT, name);
+ if (!dir || !shadow) {
+ OUT_OF_MEMORY;
+ }
+ if (mkdir(dir, 0700)) {
+ fprintf(stderr, "mkdir: %s: %s\n", dir, strerror(errno));
+ goto out_free;
+ return 0;
+ }
+ fd = open(shadow, O_RDWR | O_CREAT | O_TRUNC, 0600);
+ if (fd < 0) {
+ perror("open");
+ goto out_free;
+ }
+ close(fd);
+ if (chown(shadow, 0, authgid)) {
+ perror("chown");
+ goto out_free;
+ }
+ if (chmod(shadow, authgid == shadowgid ? 0600 : 0640)) {
+ perror("chmod");
+ goto out_free;
+ }
+ if (chown(dir, 0, authgid)) {
+ perror("chown");
+ goto out_free;
+ }
+ if (chmod(dir, authgid == shadowgid ? 02700 : 02710)) {
+ perror("chmod");
+ goto out_free;
+ }
+ if (!shadowtcb_set_user(name) || !shadowtcb_move(NULL, uid))
+ goto out_free;
+ ret = 1;
+out_free:
+ free(dir);
+ free(shadow);
+ return ret;
+}
Added: upstream/trunk/lib/tcbfuncs.h
===================================================================
--- upstream/trunk/lib/tcbfuncs.h (rev 0)
+++ upstream/trunk/lib/tcbfuncs.h 2010-03-04 18:11:13 UTC (rev 3095)
@@ -0,0 +1,13 @@
+#ifndef _TCBFUNCS_H
+#define _TCBFUNCS_H
+
+#include <sys/types.h>
+
+extern int shadowtcb_drop_priv();
+extern int shadowtcb_gain_priv();
+extern int shadowtcb_set_user(const char *name);
+extern int shadowtcb_remove(const char *name);
+extern int shadowtcb_move(const char *user_newname, uid_t user_newid);
+extern int shadowtcb_create(const char *name, uid_t uid);
+
+#endif
Modified: upstream/trunk/libmisc/copydir.c
===================================================================
--- upstream/trunk/libmisc/copydir.c 2010-01-24 17:30:36 UTC (rev 3094)
+++ upstream/trunk/libmisc/copydir.c 2010-03-04 18:11:13 UTC (rev 3095)
@@ -668,7 +668,7 @@
* At the end, it deletes the root directory itself.
*/
-int remove_tree (const char *root)
+int remove_tree (const char *root, bool remove_root)
{
char *new_name = NULL;
int err = 0;
@@ -721,7 +721,7 @@
/*
* Recursively delete this directory.
*/
- if (remove_tree (new_name) != 0) {
+ if (remove_tree (new_name, true) != 0) {
err = -1;
break;
}
@@ -740,7 +740,7 @@
}
(void) closedir (dir);
- if (0 == err) {
+ if (remove_root && 0 == err) {
if (rmdir (root) != 0) {
err = -1;
}
Modified: upstream/trunk/man/Makefile.am
===================================================================
--- upstream/trunk/man/Makefile.am 2010-01-24 17:30:36 UTC (rev 3094)
+++ upstream/trunk/man/Makefile.am 2010-03-04 18:11:13 UTC (rev 3095)
@@ -149,6 +149,8 @@
SU_WHEEL_ONLY.xml \
SYSLOG_SG_ENAB.xml \
SYSLOG_SU_ENAB.xml \
+ TCB_AUTH_GROUP.xml \
+ TCB_SYMLINKS.xml \
TTYGROUP.xml \
TTYTYPE_FILE.xml \
UID_MAX.xml \
@@ -156,6 +158,7 @@
UMASK.xml \
USERDEL_CMD.xml \
USERGROUPS_ENAB.xml \
+ USE_TCB.xml \
SYS_GID_MAX.xml \
SYS_UID_MAX.xml
Modified: upstream/trunk/man/generate_mans.deps
===================================================================
--- upstream/trunk/man/generate_mans.deps 2010-01-24 17:30:36 UTC (rev 3094)
+++ upstream/trunk/man/generate_mans.deps 2010-03-04 18:11:13 UTC (rev 3095)
@@ -105,6 +105,8 @@
login.defs.5: login.defs.d/SYSLOG_SG_ENAB.xml
login.defs.5: login.defs.d/SYSLOG_SU_ENAB.xml
login.defs.5: login.defs.d/SYS_UID_MAX.xml
+login.defs.5: login.defs.d/TCB_AUTH_GROUP.xml
+login.defs.5: login.defs.d/TCB_SYMLINKS.xml
login.defs.5: login.defs.d/TTYGROUP.xml
login.defs.5: login.defs.d/TTYTYPE_FILE.xml
login.defs.5: login.defs.d/UID_MAX.xml
@@ -112,6 +114,7 @@
login.defs.5: login.defs.d/UMASK.xml
login.defs.5: login.defs.d/USERDEL_CMD.xml
login.defs.5: login.defs.d/USERGROUPS_ENAB.xml
+login.defs.5: login.defs.d/USE_TCB.xml
newgrp.1: login.defs.d/SYSLOG_SG_ENAB.xml
newusers.8: login.defs.d/ENCRYPT_METHOD.xml
newusers.8: login.defs.d/GID_MAX.xml
Modified: upstream/trunk/man/generate_mans.mak
===================================================================
--- upstream/trunk/man/generate_mans.mak 2010-01-24 17:30:36 UTC (rev 3094)
+++ upstream/trunk/man/generate_mans.mak 2010-03-04 18:11:13 UTC (rev 3095)
@@ -8,6 +8,11 @@
else
SHADOWGRP_COND=no_gshadow
endif
+if WITH_TCB
+TCB_COND=tcb
+else
+TCB_COND=no_tcb
+endif
if USE_SHA_CRYPT
SHA_CRYPT_COND=sha_crypt
@@ -20,7 +25,7 @@
%: %.xml-config Makefile config.xml
if ENABLE_REGENERATE_MAN
- $(XSLTPROC) --stringparam profile.condition "$(PAM_COND);$(SHADOWGRP_COND);$(SHA_CRYPT_COND)" \
+ $(XSLTPROC) --stringparam profile.condition "$(PAM_COND);$(SHADOWGRP_COND);$(TCB_COND);$(SHA_CRYPT_COND)" \
-nonet http://docbook.sourceforge.net/release/xsl/current/manpages/profile-docbook.xsl $<
else
@echo you need to run configure with --enable-man to generate man pages
Modified: upstream/trunk/man/login.defs.5.xml
===================================================================
--- upstream/trunk/man/login.defs.5.xml 2010-01-24 17:30:36 UTC (rev 3094)
+++ upstream/trunk/man/login.defs.5.xml 2010-03-04 18:11:13 UTC (rev 3095)
@@ -82,6 +82,8 @@
<!ENTITY SYSLOG_SG_ENAB SYSTEM "login.defs.d/SYSLOG_SG_ENAB.xml">
<!ENTITY SYSLOG_SU_ENAB SYSTEM "login.defs.d/SYSLOG_SU_ENAB.xml">
<!ENTITY SYS_UID_MAX SYSTEM "login.defs.d/SYS_UID_MAX.xml">
+<!ENTITY TCB_AUTH_GROUP SYSTEM "login.defs.d/TCB_AUTH_GROUP.xml">
+<!ENTITY TCB_SYMLINKS SYSTEM "login.defs.d/TCB_SYMLINKS.xml">
<!ENTITY TTYGROUP SYSTEM "login.defs.d/TTYGROUP.xml">
<!ENTITY TTYTYPE_FILE SYSTEM "login.defs.d/TTYTYPE_FILE.xml">
<!ENTITY UID_MAX SYSTEM "login.defs.d/UID_MAX.xml">
@@ -89,6 +91,7 @@
<!ENTITY UMASK SYSTEM "login.defs.d/UMASK.xml">
<!ENTITY USERDEL_CMD SYSTEM "login.defs.d/USERDEL_CMD.xml">
<!ENTITY USERGROUPS_ENAB SYSTEM "login.defs.d/USERGROUPS_ENAB.xml">
+<!ENTITY USE_TCB SYSTEM "login.defs.d/USE_TCB.xml">
]>
<refentry id='login.defs.5'>
@@ -195,6 +198,8 @@
&SYS_UID_MAX; <!-- documents also SYS_UID_MIN -->
&SYSLOG_SG_ENAB;
&SYSLOG_SU_ENAB;
+ &TCB_AUTH_GROUP;
+ &TCB_SYMLINKS;
&TTYGROUP;
&TTYTYPE_FILE;
&UID_MAX; <!-- documents also UID_MIN -->
@@ -202,6 +207,7 @@
&UMASK;
&USERDEL_CMD;
&USERGROUPS_ENAB;
+ &USE_TCB;
</variablelist>
</refsect1>
@@ -381,16 +387,27 @@
<listitem>
<para>
PASS_MAX_DAYS PASS_MIN_DAYS PASS_WARN_AGE
+ <phrase condition="tcb">USE_TCB</phrase>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>pwconv</term>
<listitem>
- <para>PASS_MAX_DAYS PASS_MIN_DAYS PASS_WARN_AGE</para>
+ <para>
+ PASS_MAX_DAYS PASS_MIN_DAYS PASS_WARN_AGE
+ <phrase condition="tcb">USE_TCB</phrase>
+ </para>
</listitem>
</varlistentry>
- <!-- pwunconv: no variables -->
+ <varlistentry condition="tcb">
+ <term>pwunconv</term>
+ <listitem>
+ <para>
+ <phrase condition="tcb">USE_TCB</phrase>
+ </para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term>su</term>
<listitem>
@@ -427,6 +444,7 @@
PASS_MAX_DAYS PASS_MIN_DAYS PASS_WARN_AGE
SYS_GID_MAX SYS_GID_MIN SYS_UID_MAX SYS_UID_MIN UID_MAX UID_MIN
UMASK
+ <phrase condition="tcb">TCB_AUTH_GROUP TCB_SYMLINK USE_TCB</phrase>
</para>
</listitem>
</varlistentry>
@@ -436,6 +454,7 @@
<para>
MAIL_DIR MAIL_FILE MAX_MEMBERS_PER_GROUP USERDEL_CMD
USERGROUPS_ENAB
+ <phrase condition="tcb">USE_TCB</phrase>
</para>
</listitem>
</varlistentry>
@@ -444,10 +463,18 @@
<listitem>
<para>
MAIL_DIR MAIL_FILE MAX_MEMBERS_PER_GROUP
+ <phrase condition="tcb">USE_TCB</phrase>
</para>
</listitem>
</varlistentry>
- <!-- vipw / vigr: no variables (MAX_MEMBERS_PER_GROUP linked but not used) -->
+ <varlistentry condition="tcb">
+ <term>vipw</term>
+ <listitem>
+ <para>
+ <phrase condition="tcb">USE_TCB</phrase>
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
Added: upstream/trunk/man/login.defs.d/TCB_AUTH_GROUP.xml
===================================================================
--- upstream/trunk/man/login.defs.d/TCB_AUTH_GROUP.xml (rev 0)
+++ upstream/trunk/man/login.defs.d/TCB_AUTH_GROUP.xml 2010-03-04 18:11:13 UTC (rev 3095)
@@ -0,0 +1,37 @@
+<!--
+ Copyright (c) 2010, Pawel Hajdan
+ 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.
+-->
+<varlistentry condition="tcb">
+ <term><option>TCB_AUTH_GROUP</option> (boolean)</term>
+ <listitem>
+ <para>
+ If <replaceable>yes</replaceable>, newly created tcb shadow files
+ will be group owned by the <replaceable>auth</replaceable> group.
+ </para>
+ </listitem>
+</varlistentry>
Added: upstream/trunk/man/login.defs.d/TCB_SYMLINKS.xml
===================================================================
--- upstream/trunk/man/login.defs.d/TCB_SYMLINKS.xml (rev 0)
+++ upstream/trunk/man/login.defs.d/TCB_SYMLINKS.xml 2010-03-04 18:11:13 UTC (rev 3095)
@@ -0,0 +1,53 @@
+<!--
+ Copyright (c) 2010, Pawel Hajdan
+ 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.
+-->
+<varlistentry condition="tcb">
+ <term><option>TCB_SYMLINKS</option> (boolean)</term>
+ <listitem>
+ <para>
+ If <replaceable>yes</replaceable>, the location of the user tcb
+ directory to be created will not be automatically set to /etc/tcb/user,
+ but will be computed depending on the UID of the user, according to
+ the following algorithm:
+ <programlisting>
+if ( UID is less than 1000) {
+ use /etc/tcb/user
+} else if ( UID is less than 1000000) {
+ kilos = UID / 1000
+ use /etc/tcb/:kilos/user
+ make symlink /etc/tcb/user to the above directory
+} else {
+ megas = UID / 1000000
+ kilos = ( UID / megas * 1000000 ) / 1000
+ use /etc/tcb/:megas/:kilos/user
+ make symlink /etc/tcb/user to the above directory
+}
+ </programlisting>
+ </para>
+ </listitem>
+</varlistentry>
Added: upstream/trunk/man/login.defs.d/USE_TCB.xml
===================================================================
--- upstream/trunk/man/login.defs.d/USE_TCB.xml (rev 0)
+++ upstream/trunk/man/login.defs.d/USE_TCB.xml 2010-03-04 18:11:13 UTC (rev 3095)
@@ -0,0 +1,38 @@
+<!--
+ Copyright (c) 2010, Pawel Hajdan
+ 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.
+-->
+<varlistentry condition="tcb">
+ <term><option>USE_TCB</option> (boolean)</term>
+ <listitem>
+ <para>
+ If <replaceable>yes</replaceable>, the <citerefentry>
+ <refentrytitle>tcb</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ password shadowing scheme will be used.
+ </para>
+ </listitem>
+</varlistentry>
Modified: upstream/trunk/man/vipw.8.xml
===================================================================
--- upstream/trunk/man/vipw.8.xml 2010-01-24 17:30:36 UTC (rev 3094)
+++ upstream/trunk/man/vipw.8.xml 2010-03-04 18:11:13 UTC (rev 3095)
@@ -117,6 +117,12 @@
<para>Edit shadow or gshadow database.</para>
</listitem>
</varlistentry>
+ <varlistentry condition="tcb">
+ <term><option>-u</option>, <option>--user</option></term>
+ <listitem>
+ <para>Indicates which user's tcb shadow file to edit.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
@@ -165,6 +171,9 @@
<citerefentry>
<refentrytitle>passwd</refentrytitle><manvolnum>5</manvolnum>
</citerefentry>,
+ <citerefentry condition="tcb">
+ <refentrytitle>tcb</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>,
<citerefentry>
<refentrytitle>shadow</refentrytitle><manvolnum>5</manvolnum>
</citerefentry>.
Modified: upstream/trunk/src/Makefile.am
===================================================================
--- upstream/trunk/src/Makefile.am 2010-01-24 17:30:36 UTC (rev 3094)
+++ upstream/trunk/src/Makefile.am 2010-03-04 18:11:13 UTC (rev 3095)
@@ -5,6 +5,7 @@
ubindir = ${prefix}/bin
usbindir = ${prefix}/sbin
suidperms = 4755
+sgidperms = 2755
INCLUDES = \
-I${top_srcdir}/lib \
@@ -53,7 +54,13 @@
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 @@
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
Modified: upstream/trunk/src/chage.c
===================================================================
--- upstream/trunk/src/chage.c 2010-01-24 17:30:36 UTC (rev 3094)
+++ upstream/trunk/src/chage.c 2010-03-04 18:11:13 UTC (rev 3095)
@@ -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 @@
}
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]);
Modified: upstream/trunk/src/pwconv.c
===================================================================
--- upstream/trunk/src/pwconv.c 2010-01-24 17:30:36 UTC (rev 3094)
+++ upstream/trunk/src/pwconv.c 2010-03-04 18:11:13 UTC (rev 3095)
@@ -133,6 +133,11 @@
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"),
Modified: upstream/trunk/src/pwunconv.c
===================================================================
--- upstream/trunk/src/pwunconv.c 2010-01-24 17:30:36 UTC (rev 3094)
+++ upstream/trunk/src/pwunconv.c 2010-03-04 18:11:13 UTC (rev 3095)
@@ -93,6 +93,11 @@
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);
Modified: upstream/trunk/src/useradd.c
===================================================================
--- upstream/trunk/src/useradd.c 2010-01-24 17:30:36 UTC (rev 3094)
+++ upstream/trunk/src/useradd.c 2010-03-04 18:11:13 UTC (rev 3095)
@@ -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 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,22 +1433,9 @@
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 @@
#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 @@
}
}
+#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) {
Modified: upstream/trunk/src/userdel.c
===================================================================
--- upstream/trunk/src/userdel.c 2010-01-24 17:30:36 UTC (rev 3094)
+++ upstream/trunk/src/userdel.c 2010-03-04 18:11:13 UTC (rev 3095)
@@ -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 @@
#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 @@
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 @@
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 @@
#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 @@
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");
Modified: upstream/trunk/src/usermod.c
===================================================================
--- upstream/trunk/src/usermod.c 2010-01-24 17:30:36 UTC (rev 3094)
+++ upstream/trunk/src/usermod.c 2010-03-04 18:11:13 UTC (rev 3095)
@@ -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 @@
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 @@
/* 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 @@
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 @@
#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 @@
}
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");
Modified: upstream/trunk/src/vipw.c
===================================================================
--- upstream/trunk/src/vipw.c 2010-01-24 17:30:36 UTC (rev 3094)
+++ upstream/trunk/src/vipw.c 2010-03-04 18:11:13 UTC (rev 3095)
@@ -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 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 @@
" -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 @@
#define DEFAULT_EDITOR "vi"
#endif
+#define SHADOWTCB_SCRATCHDIR ":tmp"
+
/*
*
*/
@@ -187,9 +198,23 @@
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;
@@ -213,10 +238,18 @@
}
}
#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 @@
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 @@
* 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 @@
{"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 @@
case 's':
editshadow = true;
break;
+ case 'u':
+ user = optarg;
+ break;
default:
usage (E_USAGE);
}
@@ -372,9 +453,20 @@
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 {
More information about the Pkg-shadow-commits
mailing list