Skip to content

Commit

Permalink
UTILS: add capabilities management helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
alexey-tikhonov committed Sep 13, 2023
1 parent d016385 commit 054ed59
Show file tree
Hide file tree
Showing 7 changed files with 237 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -1289,6 +1289,7 @@ libsss_util_la_SOURCES = \
src/util/well_known_sids.c \
src/util/string_utils.c \
src/util/become_user.c \
src/util/capabilities.c \
src/util/util_watchdog.c \
src/util/sss_ptr_hash.c \
src/util/files.c \
Expand All @@ -1305,6 +1306,7 @@ libsss_util_la_CFLAGS = \
libsss_util_la_LIBADD = \
$(LIBADD_TIMER) \
$(SSSD_LIBS) \
$(CAP_LIBS) \
$(SYSTEMD_LOGIN_LIBS) \
$(UNICODE_LIBS) \
$(PCRE_LIBS) \
Expand Down Expand Up @@ -4698,6 +4700,7 @@ krb5_child_LDADD = \
$(CLIENT_LIBS) \
$(SYSTEMD_LOGIN_LIBS) \
$(JANSSON_LIBS) \
$(CAP_LIBS) \
$(NULL)

ldap_child_SOURCES = \
Expand All @@ -4723,6 +4726,7 @@ ldap_child_LDADD = \
libsss_debug.la \
$(TALLOC_LIBS) \
$(POPT_LIBS) \
$(CAP_LIBS) \
$(DHASH_LIBS) \
$(KRB5_LIBS)

Expand Down
7 changes: 7 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,13 @@ AS_IF([test x$have_check = x], [
AC_CHECK_HEADERS([check.h],,AC_MSG_ERROR([Could not find CHECK headers]))
])

PKG_CHECK_MODULES([CAP], [libcap], [have_libcap=1], [have_libcap=])
AS_IF([test x$have_libcap = x], [
AC_MSG_ERROR([libcap is missing])
], [
AC_CHECK_HEADERS([sys/capability.h],,AC_MSG_ERROR([Could not find sys/capability.h headers]))
])

AC_PATH_PROG([DOXYGEN], [doxygen], [false])
AM_CONDITIONAL([HAVE_DOXYGEN], [test x$DOXYGEN != xfalse ])

Expand Down
2 changes: 2 additions & 0 deletions contrib/ci/deps.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ if [[ "$DISTRO_BRANCH" == -redhat-* ]]; then
krb5-server
krb5-workstation
libunistring-devel
libcap-devel
)

if [[ "$DISTRO_BRANCH" == -redhat-fedora-31* ||
Expand Down Expand Up @@ -183,6 +184,7 @@ if [[ "$DISTRO_BRANCH" == -debian-* ]]; then
libp11-kit-dev
bc
libunistring-dev
libcap-dev
)

DEPS_INTGCHECK_SATISFIED=true
Expand Down
1 change: 1 addition & 0 deletions contrib/sssd.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ BuildRequires: gettext-devel
# required for p11_child smartcard tests
BuildRequires: gnutls-utils
BuildRequires: jansson-devel
BuildRequires: libcap-devel
BuildRequires: libcurl-devel
BuildRequires: libjose-devel
BuildRequires: keyutils-libs-devel
Expand Down
208 changes: 208 additions & 0 deletions src/util/capabilities.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
/*
SSSD
Capabilities management helpers
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "config.h"
#include <sys/prctl.h>
#include <linux/securebits.h>
#include <sys/capability.h>

#include "util/util.h"


typedef struct _cap_description
{
cap_value_t val;
const char *name;
} cap_description;

#define _CAP_DESCR(cap) {cap, #cap}

static cap_description _all_caps[] =
{
_CAP_DESCR(CAP_AUDIT_CONTROL),
_CAP_DESCR(CAP_AUDIT_READ),
_CAP_DESCR(CAP_AUDIT_WRITE),
_CAP_DESCR(CAP_BLOCK_SUSPEND),
_CAP_DESCR(CAP_BPF),
_CAP_DESCR(CAP_CHECKPOINT_RESTORE),
_CAP_DESCR(CAP_CHOWN),
_CAP_DESCR(CAP_DAC_OVERRIDE),
_CAP_DESCR(CAP_DAC_READ_SEARCH),
_CAP_DESCR(CAP_FOWNER),
_CAP_DESCR(CAP_FSETID),
_CAP_DESCR(CAP_IPC_LOCK),
_CAP_DESCR(CAP_IPC_OWNER),
_CAP_DESCR(CAP_KILL),
_CAP_DESCR(CAP_LEASE),
_CAP_DESCR(CAP_LINUX_IMMUTABLE),
_CAP_DESCR(CAP_MAC_ADMIN),
_CAP_DESCR(CAP_MAC_OVERRIDE),
_CAP_DESCR(CAP_MKNOD),
_CAP_DESCR(CAP_NET_ADMIN),
_CAP_DESCR(CAP_NET_BIND_SERVICE),
_CAP_DESCR(CAP_NET_BROADCAST),
_CAP_DESCR(CAP_NET_RAW),
_CAP_DESCR(CAP_PERFMON),
_CAP_DESCR(CAP_SETGID),
_CAP_DESCR(CAP_SETFCAP),
_CAP_DESCR(CAP_SETPCAP),
_CAP_DESCR(CAP_SETUID),
_CAP_DESCR(CAP_SYS_ADMIN),
_CAP_DESCR(CAP_SYS_BOOT),
_CAP_DESCR(CAP_SYS_CHROOT),
_CAP_DESCR(CAP_SYS_MODULE),
_CAP_DESCR(CAP_SYS_NICE),
_CAP_DESCR(CAP_SYS_PACCT),
_CAP_DESCR(CAP_SYS_PTRACE),
_CAP_DESCR(CAP_SYS_RAWIO),
_CAP_DESCR(CAP_SYS_RESOURCE),
_CAP_DESCR(CAP_SYS_TIME),
_CAP_DESCR(CAP_SYS_TTY_CONFIG),
_CAP_DESCR(CAP_SYSLOG),
_CAP_DESCR(CAP_WAKE_ALARM)
};

static const char *cap_flag_to_str(cap_flag_value_t flag)
{
if (flag == CAP_SET) {
return "*1*";
}
return " 0 ";
}

errno_t sss_log_caps_to_str(bool only_non_zero, char **_str)
{
int ret;
char *str = NULL;
size_t i;
cap_t caps;
cap_flag_value_t effective, permitted, bounding;

caps = cap_get_proc();
if (caps == NULL) {
ret = errno;
DEBUG(SSSDBG_TRACE_FUNC, "cap_get_proc() failed: %d ('%s')\n",
ret, strerror(ret));
return ret;
}

for (i = 0; i < sizeof(_all_caps)/sizeof(cap_description); ++i) {
if (!CAP_IS_SUPPORTED(_all_caps[i].val)) {
continue;
}
ret = cap_get_flag(caps, _all_caps[i].val, CAP_EFFECTIVE, &effective);
if (ret == -1) {
ret = errno;
DEBUG(SSSDBG_TRACE_FUNC,
"cap_get_flag(CAP_EFFECTIVE) failed: %d ('%s')\n",
ret, strerror(ret));
goto done;
}
ret = cap_get_flag(caps, _all_caps[i].val, CAP_PERMITTED, &permitted);
if (ret == -1) {
ret = errno;
DEBUG(SSSDBG_TRACE_FUNC,
"cap_get_flag(CAP_PERMITTED) failed: %d ('%s')\n",
ret, strerror(ret));
goto done;
}
ret = cap_get_bound(_all_caps[i].val);
if (ret == 1) {
bounding = CAP_SET;
} else if (ret == 0) {
bounding = CAP_CLEAR;
} else {
ret = errno;
DEBUG(SSSDBG_TRACE_FUNC, "cap_get_bound failed: %d ('%s')\n",
ret, strerror(ret));
goto done;
}

if (only_non_zero && (effective == CAP_CLEAR) &&
(permitted == CAP_CLEAR) && (bounding == CAP_CLEAR)) {
continue;
}

str = talloc_asprintf_append(str,
" %25s: effective = %s, permitted = %s, bounding = %s\n",
_all_caps[i].name, cap_flag_to_str(effective),
cap_flag_to_str(permitted), cap_flag_to_str(bounding));
if (str == NULL) {
ret = ENOMEM;
goto done;
}
}

ret = 0;

done:
if (ret == 0) {
*_str = str;
} else {
talloc_free(str);
}

if (cap_free(caps) == -1) {
DEBUG(SSSDBG_TRACE_FUNC, "cap_free() failed\n");
}

return ret;
}

errno_t sss_drop_cap(cap_value_t cap)
{
int ret;

cap_t caps = cap_get_proc();
if (caps == NULL) {
ret = errno;
DEBUG(SSSDBG_TRACE_FUNC, "cap_get_proc() failed: %d ('%s')\n",
ret, strerror(ret));
return ret;
}
if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap, CAP_CLEAR) == -1) {
ret = errno;
DEBUG(SSSDBG_TRACE_FUNC,
"cap_set_flag(CAP_EFFECTIVE) failed: %d ('%s')\n",
ret, strerror(ret));
goto done;
}
if (cap_set_flag(caps, CAP_PERMITTED, 1, &cap, CAP_CLEAR) == -1) {
ret = errno;
DEBUG(SSSDBG_TRACE_FUNC,
"cap_set_flag(CAP_PERMITTED) failed: %d ('%s')\n",
ret, strerror(ret));
goto done;
}
if (cap_set_proc(caps) == -1) {
ret = errno;
DEBUG(SSSDBG_TRACE_FUNC, "cap_set_proc() failed: %d ('%s')\n",
ret, strerror(ret));
goto done;
}

ret = 0;

done:
if (cap_free(caps) == -1) {
DEBUG(SSSDBG_TRACE_FUNC, "cap_free() failed\n");
}

return ret;
}
12 changes: 12 additions & 0 deletions src/util/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,18 @@ int server_setup(const char *name, bool is_responder,

void server_loop(struct main_context *main_ctx)
{
char *caps;
int ret;

ret = sss_log_caps_to_str(true, &caps);
if (ret != 0) {
DEBUG(SSSDBG_IMPORTANT_INFO, "Failed to log current capabilities\n");
} else {
DEBUG(SSSDBG_IMPORTANT_INFO,
"Entering main loop with following capabilities:\n%s", caps);
talloc_free(caps);
}

/* wait for events - this is where the server sits for most of its
life */
tevent_loop_wait(main_ctx->event_ctx);
Expand Down
3 changes: 3 additions & 0 deletions src/util/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <netinet/in.h>
#include <limits.h>
#include <sys/un.h>
#include <sys/capability.h>

#include <talloc.h>
#include <tevent.h>
Expand Down Expand Up @@ -750,6 +751,8 @@ errno_t switch_creds(TALLOC_CTX *mem_ctx,
int num_gids, gid_t *gids,
struct sss_creds **saved_creds);
errno_t restore_creds(struct sss_creds *saved_creds);
errno_t sss_log_caps_to_str(bool only_non_zero, char **_str);
errno_t sss_drop_cap(cap_value_t cap);

/* from sss_semanage.c */
/* Please note that libsemange relies on files and directories created with
Expand Down

0 comments on commit 054ed59

Please sign in to comment.