From eadfbd97c9fbf9beb7c6b358e44e0e1e4a5628ae Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Sun, 27 Jul 2014 16:16:22 +0200 Subject: UTIL: Prefer libcap-ng for privilege drop operations --- Makefile.am | 34 +++++++++++++++++++++++++--------- configure.ac | 2 ++ src/external/libcapng.m4 | 18 ++++++++++++++++++ src/tests/cwrap/Makefile.am | 2 ++ src/tests/cwrap/test_become_user.c | 8 ++++---- src/util/become_user.c | 32 ++++++++++++++++++++++++++++++-- 6 files changed, 81 insertions(+), 15 deletions(-) create mode 100644 src/external/libcapng.m4 diff --git a/Makefile.am b/Makefile.am index 93f67c06b..01f9280ce 100644 --- a/Makefile.am +++ b/Makefile.am @@ -394,6 +394,7 @@ AM_CPPFLAGS = \ $(OPENLDAP_CFLAGS) \ $(GLIB2_CFLAGS) \ $(JOURNALD_CFLAGS) \ + $(LIBCAPNG_CFLAGS) \ -DLIBDIR=\"$(libdir)\" \ -DVARDIR=\"$(localstatedir)\" \ -DSHLIBEXT=\"$(SHLIBEXT)\" \ @@ -461,7 +462,9 @@ SSSD_LIBS = \ $(DHASH_LIBS) \ $(SSS_CRYPT_LIBS) \ $(OPENLDAP_LIBS) \ - $(TDB_LIBS) + $(TDB_LIBS) \ + $(LIBCAPNG_LIBS) \ + $(NULL) PYTHON_BINDINGS_LIBS = \ $(TALLOC_LIBS) \ @@ -730,6 +733,7 @@ libsss_util_la_SOURCES = \ $(NULL) libsss_util_la_CFLAGS = \ $(AM_CFLAGS) \ + $(LIBCAPNG_CFLAGS) \ $(SYSTEMD_LOGIN_CFLAGS) \ $(NULL) libsss_util_la_LIBADD = \ @@ -1319,14 +1323,16 @@ krb5_utils_tests_SOURCES = \ krb5_utils_tests_CFLAGS = \ $(AM_CFLAGS) \ $(KRB5_CFLAGS) \ - $(CHECK_CFLAGS) + $(CHECK_CFLAGS) \ + $(NULL) krb5_utils_tests_LDADD = \ $(SSSD_LIBS)\ $(CARES_LIBS) \ $(KRB5_LIBS) \ $(CHECK_LIBS) \ $(SSSD_INTERNAL_LTLIBS) \ - libsss_test_common.la + libsss_test_common.la \ + $(NULL) check_and_open_tests_SOURCES = \ @@ -1602,14 +1608,16 @@ krb5_child_test_CFLAGS = \ $(AM_CFLAGS) \ -DKRB5_CHILD_DIR=\"$(builddir)\" \ $(KRB5_CFLAGS) \ - $(CHECK_CFLAGS) + $(CHECK_CFLAGS) \ + $(NULL) krb5_child_test_LDADD = \ $(SSSD_LIBS) \ $(CARES_LIBS) \ $(KRB5_LIBS) \ $(CHECK_LIBS) \ $(SSSD_INTERNAL_LTLIBS) \ - libsss_test_common.la + libsss_test_common.la \ + $(NULL) if BUILD_DBUS_TESTS @@ -2279,11 +2287,15 @@ libsss_krb5_common_la_SOURCES = \ src/util/become_user.c \ $(NULL) libsss_krb5_common_la_CFLAGS = \ - $(KRB5_CFLAGS) + $(KRB5_CFLAGS) \ + $(LIBCAPNG_CFLAGS) \ + $(NULL) libsss_krb5_common_la_LIBADD = \ $(KEYUTILS_LIBS) \ $(DHASH_LIBS) \ - $(KRB5_LIBS) + $(KRB5_LIBS) \ + $(LIBCAPNG_LIBS) \ + $(NULL) libsss_krb5_common_la_LDFLAGS = \ -avoid-version @@ -2471,14 +2483,18 @@ krb5_child_SOURCES = \ krb5_child_CFLAGS = \ $(AM_CFLAGS) \ $(POPT_CFLAGS) \ - $(KRB5_CFLAGS) + $(KRB5_CFLAGS) \ + $(LIBCAPNG_CFLAGS) \ + $(NULL) krb5_child_LDADD = \ libsss_debug.la \ $(TALLOC_LIBS) \ $(POPT_LIBS) \ $(DHASH_LIBS) \ $(KRB5_LIBS) \ - $(CLIENT_LIBS) + $(CLIENT_LIBS) \ + $(LIBCAPNG_LIBS) \ + $(NULL) ldap_child_SOURCES = \ src/providers/ldap/ldap_child.c \ diff --git a/configure.ac b/configure.ac index 2b0b3f945..f438b5ee8 100644 --- a/configure.ac +++ b/configure.ac @@ -173,6 +173,7 @@ m4_include([src/external/sasl.m4]) m4_include([src/external/configlib.m4]) m4_include([src/external/libnfsidmap.m4]) m4_include([src/external/cwrap.m4]) +m4_include([src/external/libcapng.m4]) if test x$build_config_lib = xyes; then m4_include([src/external/libaugeas.m4]) @@ -282,6 +283,7 @@ if test x$cryptolib = xlibcrypto; then fi AM_CHECK_INOTIFY +AM_CHECK_LIBCAP_NG AC_CACHE_CHECK([whether compiler supports __attribute__((destructor))], sss_client_cv_attribute_destructor, diff --git a/src/external/libcapng.m4 b/src/external/libcapng.m4 new file mode 100644 index 000000000..effe25cb5 --- /dev/null +++ b/src/external/libcapng.m4 @@ -0,0 +1,18 @@ +dnl A macro to check presence of libcap-ng on the system +AC_DEFUN([AM_CHECK_LIBCAP_NG], +[ + PKG_CHECK_EXISTS(libcap-ng, + dnl PKG_CHECK_EXISTS ACTION-IF-FOUND + [ PKG_CHECK_MODULES([LIBCAPNG], + [libcap-ng], + [ + have_libcap_ng="yes" + AC_DEFINE_UNQUOTED([HAVE_LIBCAPNG], 1, + [Use libcap-ng for privilege drop]) + ]) + ], + dnl PKG_CHECK_EXISTS ACTION-IF-NOT-FOUND + [AC_MSG_WARN([No libcap-ng library found, falling back to our own privilege drop ipmlementation])] + ) + AM_CONDITIONAL([HAVE_LIBCAPNG], [test x$have_libcap_ng = xyes]) +]) diff --git a/src/tests/cwrap/Makefile.am b/src/tests/cwrap/Makefile.am index 6966c2e65..ec0f3aa04 100644 --- a/src/tests/cwrap/Makefile.am +++ b/src/tests/cwrap/Makefile.am @@ -57,6 +57,7 @@ become_user_tests_CFLAGS = \ become_user_tests_LDADD = \ $(POPT_LIBS) \ $(CMOCKA_LIBS) \ + $(LIBCAPNG_LIBS) \ $(abs_top_builddir)/libsss_debug.la \ libsss_test_common.la \ $(NULL) @@ -95,6 +96,7 @@ server_tests_LDADD = \ $(CMOCKA_LIBS) \ $(LIBCAPNG_LIBS) \ $(UNICODE_LIBS) \ + $(LIBCAPNG_LIBS) \ $(SSSD_LIBS) \ $(abs_top_builddir)/libsss_debug.la \ $(abs_top_builddir)/libsss_crypt.la \ diff --git a/src/tests/cwrap/test_become_user.c b/src/tests/cwrap/test_become_user.c index 06d3ad425..f3898e52c 100644 --- a/src/tests/cwrap/test_become_user.c +++ b/src/tests/cwrap/test_become_user.c @@ -27,7 +27,7 @@ #include "util/util.h" #include "tests/cmocka/common_mock.h" -void test_become_user(void **state) +void test_become_user_int(void **state) { struct passwd *sssd; errno_t ret; @@ -43,7 +43,7 @@ void test_become_user(void **state) pid = fork(); if (pid == 0) { /* Change the UID in a child */ - ret = become_user(sssd->pw_uid, sssd->pw_gid); + ret = become_user_int(sssd->pw_uid, sssd->pw_gid); assert_int_equal(ret, EOK); /* Make sure we have the requested UID and GID now and there @@ -55,7 +55,7 @@ void test_become_user(void **state) assert_int_equal(getgid(), sssd->pw_gid); /* Another become_user is a no-op */ - ret = become_user(sssd->pw_uid, sssd->pw_gid); + ret = become_user_int(sssd->pw_uid, sssd->pw_gid); assert_int_equal(ret, EOK); assert_int_equal(getgroups(0, NULL), 0); @@ -127,7 +127,7 @@ int main(int argc, const char *argv[]) }; const UnitTest tests[] = { - unit_test(test_become_user), + unit_test(test_become_user_int), unit_test(test_switch_user), }; diff --git a/src/util/become_user.c b/src/util/become_user.c index b5f94f993..c8a0c77ee 100644 --- a/src/util/become_user.c +++ b/src/util/become_user.c @@ -25,7 +25,11 @@ #include "util/util.h" #include -errno_t become_user(uid_t uid, gid_t gid) +#ifdef HAVE_LIBCAPNG +#include +#endif + +static errno_t become_user_int(uid_t uid, gid_t gid) { uid_t cuid; int ret; @@ -40,7 +44,7 @@ errno_t become_user(uid_t uid, gid_t gid) return EOK; } - /* drop supplmentary groups first */ + /* drop supplementary groups first */ ret = setgroups(0, NULL); if (ret == -1) { ret = errno; @@ -71,6 +75,30 @@ errno_t become_user(uid_t uid, gid_t gid) return EOK; } +#ifdef HAVE_LIBCAPNG +static errno_t become_user_libcap(uid_t uid, gid_t gid) +{ + int ret; + + capng_clear(0); + ret = capng_change_id(uid, gid, CAPNG_DROP_SUPP_GRP); + if (ret != 0) { + DEBUG(SSSDBG_FATAL_FAILURE, "Cannot change UID: %d errno: %d\n", ret, errno); + } + + return ret; +} +#endif + +errno_t become_user(uid_t uid, gid_t gid) +{ +#ifdef HAVE_LIBCAPNG + return become_user_libcap(uid, gid); +#endif + + return become_user_int(uid, gid); +} + struct sss_creds { uid_t uid; gid_t gid; -- cgit