Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ PKG_CHECK_MODULES([LIBPCRE], [libpcre], HAVE_LIBPCRE=yes; AC_DEFINE(HAVE_LIBPCRE
fi
])

PKG_CHECK_MODULES([LIBCAP], [libcap], HAVE_LIBCAP=yes; AC_DEFINE(HAVE_LIBCAP, 1),
[AC_LIB_HAVE_LINKFLAGS(pcre,, [#include <sys/capability.h>], [cap_get_proc();])
if test x$ac_cv_libcap = xyes; then
AC_SUBST([LIBCAP_LIBS], [$LIBCAP])
fi
])

AC_ARG_ENABLE([dns],
[AS_HELP_STRING([--disable-dns], [Disable DNS resolution])],
[dns="$withval"], [dns=yes])
Expand Down
2 changes: 1 addition & 1 deletion src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ sniproxy_SOURCES = sniproxy.c \
tls.c \
tls.h

sniproxy_LDADD = $(LIBEV_LIBS) $(LIBPCRE_LIBS) $(LIBUDNS_LIBS)
sniproxy_LDADD = $(LIBEV_LIBS) $(LIBPCRE_LIBS) $(LIBUDNS_LIBS) $(LIBCAP_LIBS)
57 changes: 57 additions & 0 deletions src/sniproxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
#ifdef HAVE_LIBCAP
#include <sys/prctl.h>
#include <sys/capability.h>
#endif
#include <signal.h>
#include <errno.h>
#include <ev.h>
Expand Down Expand Up @@ -235,6 +239,30 @@ drop_perms(const char *username, const char *groupname) {
gid = group->gr_gid;
}

#ifdef HAVE_LIBCAP
cap_t caps;
cap_value_t cap_list[1];

/* add permitted flag to capability needed for IP_TRANSPARENT */
if (CAP_IS_SUPPORTED(CAP_NET_RAW)) {
caps = cap_get_proc();
if (caps == NULL)
fatal("cap_get_proc(): %s", strerror(errno));

cap_list[0] = CAP_NET_RAW;
if (cap_set_flag(caps, CAP_PERMITTED, 1, cap_list, CAP_SET) == -1)
fatal("cap_set_flags(): %s", strerror(errno));

if (cap_set_proc(caps) == -1)
fatal("cap_set_proc(): %s", strerror(errno));

cap_free(caps);

/* keep capabilities after setuid */
prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
}
#endif

/* drop any supplementary groups */
if (setgroups(1, &gid) < 0)
fatal("setgroups(): %s", strerror(errno));
Expand All @@ -245,6 +273,35 @@ drop_perms(const char *username, const char *groupname) {

if (setuid(user->pw_uid) < 0)
fatal("setuid(): %s", strerror(errno));

#ifdef HAVE_LIBCAP
/* enable capability needed for IP_TRANSPARENT */
if (CAP_IS_SUPPORTED(CAP_NET_RAW)) {
caps = cap_get_proc();
if (caps == NULL)
fatal("cap_get_proc(): %s", strerror(errno));

/* remove every capability from the list */
cap_clear(caps);
cap_list[0] = CAP_NET_RAW;
/* take back capability */
if (cap_set_flag(caps, CAP_PERMITTED, 1, cap_list, CAP_SET) == -1)
fatal("cap_set_flags(): %s", strerror(errno));
/* take back capability */
if (cap_set_flag(caps, CAP_EFFECTIVE, 1, cap_list, CAP_SET) == -1)
fatal("cap_set_flags(): %s", strerror(errno));

if (cap_set_proc(caps) == -1)
fatal("back cap_set_proc(): %s", strerror(errno));
/* from now on it the new capability list is active,
* no other capabilities may be enabled */

cap_free(caps);

/* disable keeping capabilities across setuid */
prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0);
}
#endif
}

static void
Expand Down