Libcap-ng support by Gurvinder Singh and myself. Basic support for per thread caps is added, but not activated as it doesn't seem to work yet. Work around for incompatibility between libnet 1.1 and libcap-ng added.

remotes/origin/master-1.0.x
Victor Julien 15 years ago
parent e0c2c86342
commit 070ed778b8

@ -12,6 +12,9 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `cap-ng' library (-lcap-ng). */
#undef HAVE_LIBCAP_NG
/* Define to 1 if you have the `cuda' library (-lcuda). */
#undef HAVE_LIBCUDA

@ -698,6 +698,42 @@ AC_CHECK_HEADER(pcap.h,,[AC_ERROR(pcap.h not found ...)])
fi
fi
# Check for libcap-ng
AC_ARG_WITH(libcap_ng_includes,
[ --with-libcap_ng-includes=DIR libcap_ng include directory],
[with_libcap-ng_includes="$withval"],[with_libcap_ng_includes=no])
AC_ARG_WITH(libcap_ng_libraries,
[ --with-libcap_ng-libraries=DIR libcap_ng library directory],
[with_libcap_ng_libraries="$withval"],[with_libcap_ng_libraries="no"])
if test "$with_libcap_ng_includes" != "no"; then
CPPFLAGS="${CPPFLAGS} -I${with_libcap_ng_includes}"
fi
if test "$with_libcap_ng_libraries" != "no"; then
LDFLAGS="${LDFLAGS} -L${with_libcap_ng_libraries}"
fi
AC_CHECK_HEADER(cap-ng.h,,LIBCAP_NG="no")
if test "$LIBCAP_NG" != "no"; then
LIBCAP_NG=""
AC_CHECK_LIB(cap-ng,capng_clear,,LIBCAP_NG="no")
fi
if test "$LIBCAP_NG" != "no"; then
CFLAGS="${CFLAGS} -DHAVE_LIBCAP_NG"
fi
if test "$LIBCAP_NG" = "no"; then
echo
echo " WARNING! libcap-ng library not found, go get it"
echo " from http://people.redhat.com/sgrubb/libcap-ng/"
echo " or check your package manager."
echo
echo " Suricata will be built without support for dropping privs."
echo
fi
AC_SUBST(CFLAGS)
AC_SUBST(LDFLAGS)

@ -155,6 +155,7 @@ util-strlcatu.c \
util-strlcpyu.c \
util-cuda.c util-cuda.h \
util-cuda-handlers.c util-cuda-handlers.h \
util-privs.c util-privs.h \
tm-modules.c tm-modules.h \
tm-queues.c tm-queues.h \
tm-queuehandlers.c tm-queuehandlers.h \

@ -28,6 +28,7 @@
#include "output.h"
#include "alert-debuglog.h"
#include "util-privs.h"
#define DEFAULT_LOG_FILENAME "alert-debug.log"
@ -48,6 +49,7 @@ void TmModuleAlertDebugLogRegister (void) {
tmm_modules[TMM_ALERTDEBUGLOG].ThreadExitPrintStats = AlertDebugLogExitPrintStats;
tmm_modules[TMM_ALERTDEBUGLOG].ThreadDeinit = AlertDebugLogThreadDeinit;
tmm_modules[TMM_ALERTDEBUGLOG].RegisterTests = NULL;
tmm_modules[TMM_ALERTDEBUGLOG].cap_flags = 0;
OutputRegisterModule(MODULE_NAME, "alert-debug", AlertDebugLogInitCtx);
}

@ -37,6 +37,7 @@
#include "util-mpm-b2g-cuda.h"
#include "util-cuda-handlers.h"
#include "util-privs.h"
#define DEFAULT_LOG_FILENAME "fast.log"
@ -59,6 +60,7 @@ void TmModuleAlertFastLogRegister (void) {
tmm_modules[TMM_ALERTFASTLOG].ThreadExitPrintStats = AlertFastLogExitPrintStats;
tmm_modules[TMM_ALERTFASTLOG].ThreadDeinit = AlertFastLogThreadDeinit;
tmm_modules[TMM_ALERTFASTLOG].RegisterTests = AlertFastLogRegisterTests;
tmm_modules[TMM_ALERTFASTLOG].cap_flags = 0;
OutputRegisterModule(MODULE_NAME, "fast", AlertFastLogInitCtx);
}

@ -38,6 +38,7 @@
#include "util-error.h"
#include "output.h"
#include "util-privs.h"
#ifndef PRELUDE
/** Handle the case where no PRELUDE support is compiled in.
@ -117,6 +118,7 @@ void TmModuleAlertPreludeRegister (void) {
tmm_modules[TMM_ALERTPRELUDE].Func = AlertPrelude;
tmm_modules[TMM_ALERTPRELUDE].ThreadDeinit = AlertPreludeThreadDeinit;
tmm_modules[TMM_ALERTPRELUDE].RegisterTests = AlertPreludeRegisterTests;
tmm_modules[TMM_ALERTPRELUDE].cap_flags = 0;
OutputRegisterModule("AlertPrelude", "alert-prelude", AlertPreludeInitCtx);
}

@ -29,6 +29,7 @@
#include "output.h"
#include "alert-unified-alert.h"
#include "util-privs.h"
#define DEFAULT_LOG_FILENAME "unified.alert"
@ -53,6 +54,7 @@ void TmModuleAlertUnifiedAlertRegister (void) {
tmm_modules[TMM_ALERTUNIFIEDALERT].Func = AlertUnifiedAlert;
tmm_modules[TMM_ALERTUNIFIEDALERT].ThreadDeinit = AlertUnifiedAlertThreadDeinit;
tmm_modules[TMM_ALERTUNIFIEDALERT].RegisterTests = AlertUnifiedAlertRegisterTests;
tmm_modules[TMM_ALERTUNIFIEDALERT].cap_flags = 0;
OutputRegisterModule(MODULE_NAME, "unified-alert", AlertUnifiedAlertInitCtx);
}

@ -30,6 +30,7 @@
#include "output.h"
#include "alert-unified-log.h"
#include "util-privs.h"
#define DEFAULT_LOG_FILENAME "unified.log"
@ -54,6 +55,7 @@ void TmModuleAlertUnifiedLogRegister (void) {
tmm_modules[TMM_ALERTUNIFIEDLOG].Func = AlertUnifiedLog;
tmm_modules[TMM_ALERTUNIFIEDLOG].ThreadDeinit = AlertUnifiedLogThreadDeinit;
tmm_modules[TMM_ALERTUNIFIEDLOG].RegisterTests = AlertUnifiedLogRegisterTests;
tmm_modules[TMM_ALERTUNIFIEDLOG].cap_flags = 0;
OutputRegisterModule(MODULE_NAME, "unified-log", AlertUnifiedLogInitCtx);

@ -25,6 +25,7 @@
#include "output.h"
#include "alert-unified2-alert.h"
#include "util-privs.h"
#ifndef IPPROTO_SCTP
#define IPPROTO_SCTP 132
@ -138,6 +139,7 @@ void TmModuleUnified2AlertRegister (void) {
tmm_modules[TMM_ALERTUNIFIED2ALERT].Func = Unified2Alert;
tmm_modules[TMM_ALERTUNIFIED2ALERT].ThreadDeinit = Unified2AlertThreadDeinit;
tmm_modules[TMM_ALERTUNIFIED2ALERT].RegisterTests = Unified2RegisterTests;
tmm_modules[TMM_ALERTUNIFIED2ALERT].cap_flags = 0;
OutputRegisterModule(MODULE_NAME, "unified2-alert", Unified2AlertInitCtx);
}

@ -12,6 +12,7 @@
#include "util-time.h"
#include "util-unittest.h"
#include "util-debug.h"
#include "util-privs.h"
/** \todo Get the default log directory from some global resource. */
#define SC_PERF_DEFAULT_LOG_FILENAME "stats.log"
@ -356,6 +357,11 @@ static void *SCPerfMgmtThread(void *arg)
/* Set the thread name */
SCSetThreadName(tv_local->name);
/* Set the threads capability */
tv_local->cap_flags = 0;
SCDropCaps(tv_local);
if (sc_perf_op_ctx == NULL) {
SCLogError(SC_ERR_PERF_STATS_NOT_INIT, "Perf Counter API not init"
"SCPerfInitCounterApi() has to be called first");
@ -403,6 +409,11 @@ static void *SCPerfWakeupThread(void *arg)
/* Set the thread name */
SCSetThreadName(tv_local->name);
/* Set the threads capability */
tv_local->cap_flags = 0;
SCDropCaps(tv_local);
if (sc_perf_op_ctx == NULL) {
SCLogError(SC_ERR_PERF_STATS_NOT_INIT, "Perf Counter API not init"
"SCPerfInitCounterApi() has to be called first");
@ -1657,10 +1668,8 @@ void SCPerfReleasePCA(SCPerfCounterArray *pca)
return;
}
/*----------------------------------Unit_Tests--------------------------------*/
static int SCPerfTestCounterReg01()
{
SCPerfContext pctx;

@ -30,6 +30,8 @@
#include "detect-parse.h"
#include "detect-engine-iponly.h"
extern int sc_set_caps;
static pcre *config_pcre = NULL;
static pcre *option_pcre = NULL;
static pcre_extra *config_pcre_extra = NULL;
@ -506,6 +508,28 @@ int SigParsePort(Signature *s, const char *portstr, char flag)
return 0;
}
/** \retval 1 valid
* \retval 0 invalid
*/
static int SigParseActionRejectValidate(void) {
#ifdef HAVE_LIBNET11
#ifdef HAVE_LIBCAP_NG
if (sc_set_caps == TRUE) {
SCLogError(SC_ERR_LIBNET11_INCOMPATIBLE_WITH_LIBCAP_NG, "Libnet 1.1 is "
"incompatible with POSIX based capabilities with privs dropping. "
"For rejects to work, run as root/super user.");
return 0;
}
#endif
#else /* no libnet 1.1 */
SCLogError(SC_ERR_LIBNET_REQUIRED_FOR_ACTION, "Libnet 1.1.x is "
"required for action \"%s\" but is not compiled into Suricata",
action);
return 0;
#endif
return 1;
}
/**
* \brief Parses the action that has been used by the Signature and allots it
* to its Signatue instance.
@ -527,30 +551,26 @@ int SigParseAction(Signature *s, const char *action) {
} else if (strcasecmp(action, "pass") == 0) {
s->action = ACTION_PASS;
return 0;
#ifdef HAVE_LIBNET11
} else if (strcasecmp(action, "reject") == 0) {
if (!(SigParseActionRejectValidate()))
return -1;
s->action = ACTION_REJECT;
return 0;
} else if (strcasecmp(action, "rejectsrc") == 0) {
if (!(SigParseActionRejectValidate()))
return -1;
s->action = ACTION_REJECT;
return 0;
} else if (strcasecmp(action, "rejectdst") == 0) {
if (!(SigParseActionRejectValidate()))
return -1;
s->action = ACTION_REJECT_DST;
return 0;
} else if (strcasecmp(action, "rejectboth") == 0) {
if (!(SigParseActionRejectValidate()))
return -1;
s->action = ACTION_REJECT_BOTH;
return 0;
#else
} else if (strcasecmp(action, "reject") == 0 ||
strcasecmp(action, "rejectsrc") == 0 ||
strcasecmp(action, "rejectdst") == 0 ||
strcasecmp(action, "rejectboth") == 0)
{
SCLogError(SC_ERR_LIBNET_REQUIRED_FOR_ACTION, "Libnet 1.1.x is "
"required for action \"%s\" but is not compiled into Suricata",
action);
return -1;
#endif /* HAVE_LIBNET11 */
} else {
SCLogError(SC_ERR_INVALID_ACTION,"An invalid action \"%s\" was given",action);
return -1;
@ -639,7 +659,7 @@ int SigParse(DetectEngineCtx *de_ctx, Signature *s, char *sigstr, uint8_t addrs_
int ret = SigParseBasics(s, sigstr, &basics, addrs_direction);
if (ret < 0) {
printf("SigParseBasics failed\n");
SCLogDebug("SigParseBasics failed");
SCReturnInt(-1);
}

@ -114,6 +114,7 @@
#include "util-cuda-handlers.h"
#include "util-mpm-b2g-cuda.h"
#include "util-cuda.h"
#include "util-privs.h"
SigMatch *SigMatchAlloc(void);
void DetectExitPrintStats(ThreadVars *tv, void *data);
@ -133,6 +134,7 @@ void TmModuleDetectRegister (void) {
tmm_modules[TMM_DETECT].ThreadExitPrintStats = DetectExitPrintStats;
tmm_modules[TMM_DETECT].ThreadDeinit = DetectThreadDeinit;
tmm_modules[TMM_DETECT].RegisterTests = SigRegisterTests;
tmm_modules[TMM_DETECT].cap_flags = 0;
}
void DetectExitPrintStats(ThreadVars *tv, void *data) {

@ -33,6 +33,7 @@
#include "util-byte.h"
#include "util-debug.h"
#include "util-privs.h"
//#define FLOW_DEFAULT_HASHSIZE 262144
#define FLOW_DEFAULT_HASHSIZE 65536
@ -651,6 +652,10 @@ void *FlowManagerThread(void *td)
SCSetThreadName(th_v->name);
SCLogDebug("%s started...", th_v->name);
/* Set the threads capability */
th_v->cap_flags = 0;
SCDropCaps(th_v);
TmThreadsSetFlag(th_v, THV_INIT_DONE);
while (1)
{

@ -25,6 +25,7 @@
#include "app-layer-htp.h"
#include <htp/dslib.h>
#include "app-layer.h"
#include "util-privs.h"
#define DEFAULT_LOG_FILENAME "http.log"
@ -46,6 +47,7 @@ void TmModuleLogHttpLogRegister (void) {
tmm_modules[TMM_LOGHTTPLOG].ThreadExitPrintStats = LogHttpLogExitPrintStats;
tmm_modules[TMM_LOGHTTPLOG].ThreadDeinit = LogHttpLogThreadDeinit;
tmm_modules[TMM_LOGHTTPLOG].RegisterTests = NULL;
tmm_modules[TMM_LOGHTTPLOG].cap_flags = 0;
OutputRegisterModule(MODULE_NAME, "http-log", LogHttpLogInitCtx);
}

@ -31,6 +31,10 @@
#ifdef HAVE_LIBNET11
/** set to true in main if we're setting caps. We need it here if we're using
* reject rules as libnet 1.1 is not compatible with caps. */
extern int sc_set_caps;
#include <libnet.h>

@ -24,6 +24,7 @@
#include "respond-reject-libnet11.h"
#include "util-debug.h"
#include "util-privs.h"
int RejectSendIPv4TCP(ThreadVars *, Packet *, void *);
int RejectSendIPv4ICMP(ThreadVars *, Packet *, void *);
@ -37,6 +38,7 @@ void TmModuleRespondRejectRegister (void) {
tmm_modules[TMM_RESPONDREJECT].Func = RespondRejectFunc;
tmm_modules[TMM_RESPONDREJECT].ThreadDeinit = NULL;
tmm_modules[TMM_RESPONDREJECT].RegisterTests = NULL;
tmm_modules[TMM_RESPONDREJECT].cap_flags = 0; /* libnet is not compat with caps */
}
TmEcode RespondRejectFunc(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) {

@ -127,6 +127,7 @@ static void SetupOutputs(ThreadVars *tv)
{
RunModeOutput *output;
TAILQ_FOREACH(output, &RunModeOutputs, entries) {
tv->cap_flags |= output->tm_module->cap_flags;
TmVarSlotSetFuncAppend(tv, output->tm_module, output->output_ctx);
}
}

@ -16,6 +16,7 @@
#include "source-ipfw.h"
#include "util-debug.h"
#include "conf.h"
#include "util-privs.h"
#define IPFW_ACCEPT 0
#define IPFW_DROP 1
@ -40,6 +41,8 @@ void TmModuleReceiveIPFWRegister (void) {
tmm_modules[TMM_RECEIVEIPFW].ThreadExitPrintStats = NULL;
tmm_modules[TMM_RECEIVEIPFW].ThreadDeinit = NULL;
tmm_modules[TMM_RECEIVEIPFW].RegisterTests = NULL;
tmm_modules[TMM_RECEIVEIPFW].cap_flags = SC_CAP_NET_ADMIN | SC_CAP_NET_RAW |
SC_CAP_NET_BIND_SERVICE | SC_CAP_NET_BROADCAST; /** \todo untested */
}
void TmModuleVerdictIPFWRegister (void) {
@ -49,6 +52,8 @@ void TmModuleVerdictIPFWRegister (void) {
tmm_modules[TMM_VERDICTIPFW].ThreadExitPrintStats = NULL;
tmm_modules[TMM_VERDICTIPFW].ThreadDeinit = NULL;
tmm_modules[TMM_VERDICTIPFW].RegisterTests = NULL;
tmm_modules[TMM_VERDICTIPFW].cap_flags = SC_CAP_NET_ADMIN | SC_CAP_NET_RAW |
SC_CAP_NET_BIND_SERVICE; /** \todo untested */
}
void TmModuleDecodeIPFWRegister (void) {
@ -58,6 +63,7 @@ void TmModuleDecodeIPFWRegister (void) {
tmm_modules[TMM_DECODEIPFW].ThreadExitPrintStats = NULL;
tmm_modules[TMM_DECODEIPFW].ThreadDeinit = NULL;
tmm_modules[TMM_DECODEIPFW].RegisterTests = NULL;
tmm_modules[TMM_DECODEIPFW].cap_flags = 0;
}
TmEcode NoIPFWSupportExit(ThreadVars *tv, void *initdata, void **data) {

@ -28,6 +28,7 @@
#include "util-debug.h"
#include "util-error.h"
#include "util-byte.h"
#include "util-privs.h"
#ifndef NFQ
/** Handle the case where no NFQ support is compiled in.
@ -43,6 +44,7 @@ void TmModuleReceiveNFQRegister (void) {
tmm_modules[TMM_RECEIVENFQ].ThreadExitPrintStats = NULL;
tmm_modules[TMM_RECEIVENFQ].ThreadDeinit = NULL;
tmm_modules[TMM_RECEIVENFQ].RegisterTests = NULL;
tmm_modules[TMM_RECEIVENFQ].cap_flags = SC_CAP_NET_ADMIN;
}
void TmModuleVerdictNFQRegister (void) {
@ -52,6 +54,7 @@ void TmModuleVerdictNFQRegister (void) {
tmm_modules[TMM_VERDICTNFQ].ThreadExitPrintStats = NULL;
tmm_modules[TMM_VERDICTNFQ].ThreadDeinit = NULL;
tmm_modules[TMM_VERDICTNFQ].RegisterTests = NULL;
tmm_modules[TMM_VERDICTNFQ].cap_flags = SC_CAP_NET_ADMIN;
}
void TmModuleDecodeNFQRegister (void) {
@ -61,6 +64,7 @@ void TmModuleDecodeNFQRegister (void) {
tmm_modules[TMM_DECODENFQ].ThreadExitPrintStats = NULL;
tmm_modules[TMM_DECODENFQ].ThreadDeinit = NULL;
tmm_modules[TMM_DECODENFQ].RegisterTests = NULL;
tmm_modules[TMM_DECODENFQ].cap_flags = 0;
}
TmEcode NoNFQSupportExit(ThreadVars *tv, void *initdata, void **data)

@ -25,6 +25,7 @@
#include "util-debug.h"
#include "conf.h"
#include "util-error.h"
#include "util-privs.h"
extern int max_pending_packets;
@ -66,6 +67,7 @@ void TmModuleReceivePcapFileRegister (void) {
tmm_modules[TMM_RECEIVEPCAPFILE].ThreadExitPrintStats = ReceivePcapFileThreadExitStats;
tmm_modules[TMM_RECEIVEPCAPFILE].ThreadDeinit = NULL;
tmm_modules[TMM_RECEIVEPCAPFILE].RegisterTests = NULL;
tmm_modules[TMM_RECEIVEPCAPFILE].cap_flags = 0;
}
void TmModuleDecodePcapFileRegister (void) {
@ -75,6 +77,7 @@ void TmModuleDecodePcapFileRegister (void) {
tmm_modules[TMM_DECODEPCAPFILE].ThreadExitPrintStats = NULL;
tmm_modules[TMM_DECODEPCAPFILE].ThreadDeinit = NULL;
tmm_modules[TMM_DECODEPCAPFILE].RegisterTests = NULL;
tmm_modules[TMM_DECODEPCAPFILE].cap_flags = 0;
}
void PcapFileCallback(char *user, struct pcap_pkthdr *h, u_char *pkt) {

@ -19,6 +19,7 @@
#include "conf.h"
#include "util-debug.h"
#include "util-error.h"
#include "util-privs.h"
extern int max_pending_packets;
@ -63,6 +64,7 @@ void TmModuleReceivePcapRegister (void) {
tmm_modules[TMM_RECEIVEPCAP].ThreadExitPrintStats = ReceivePcapThreadExitStats;
tmm_modules[TMM_RECEIVEPCAP].ThreadDeinit = NULL;
tmm_modules[TMM_RECEIVEPCAP].RegisterTests = NULL;
tmm_modules[TMM_RECEIVEPCAP].cap_flags = SC_CAP_NET_RAW;
}
/**
@ -76,6 +78,7 @@ void TmModuleDecodePcapRegister (void) {
tmm_modules[TMM_DECODEPCAP].ThreadExitPrintStats = NULL;
tmm_modules[TMM_DECODEPCAP].ThreadDeinit = NULL;
tmm_modules[TMM_DECODEPCAP].RegisterTests = NULL;
tmm_modules[TMM_DECODEPCAP].cap_flags = 0;
}
/**

@ -16,6 +16,7 @@
#include "tm-threads.h"
#include "source-pfring.h"
#include "util-debug.h"
#include "util-privs.h"
TmEcode ReceivePfring(ThreadVars *, Packet *, void *, PacketQueue *);
TmEcode ReceivePfringThreadInit(ThreadVars *, void *, void **);
@ -39,6 +40,8 @@ void TmModuleReceivePfringRegister (void) {
tmm_modules[TMM_RECEIVEPFRING].ThreadExitPrintStats = NULL;
tmm_modules[TMM_RECEIVEPFRING].ThreadDeinit = NULL;
tmm_modules[TMM_RECEIVEPFRING].RegisterTests = NULL;
tmm_modules[TMM_RECEIVEPFRING].cap_flags = SC_CAP_NET_ADMIN | SC_CAP_NET_RAW |
SC_CAP_NET_BIND_SERVICE | SC_CAP_NET_BROADCAST;
}
void TmModuleDecodePfringRegister (void) {
@ -48,6 +51,7 @@ void TmModuleDecodePfringRegister (void) {
tmm_modules[TMM_DECODEPFRING].ThreadExitPrintStats = NULL;
tmm_modules[TMM_DECODEPFRING].ThreadDeinit = NULL;
tmm_modules[TMM_DECODEPFRING].RegisterTests = NULL;
tmm_modules[TMM_DECODEPFRING].cap_flags = 0;
}
/**

@ -36,6 +36,7 @@
#include "app-layer-parser.h"
#include "util-host-os-info.h"
#include "util-privs.h"
//#define DEBUG
@ -93,6 +94,7 @@ void TmModuleStreamTcpRegister (void)
tmm_modules[TMM_STREAMTCP].ThreadExitPrintStats = StreamTcpExitPrintStats;
tmm_modules[TMM_STREAMTCP].ThreadDeinit = StreamTcpThreadDeinit;
tmm_modules[TMM_STREAMTCP].RegisterTests = StreamTcpRegisterTests;
tmm_modules[TMM_STREAMTCP].cap_flags = 0;
}
void StreamTcpIncrMemuse(uint32_t size) {

@ -103,6 +103,7 @@
#include "util-cuda-handlers.h"
#include "output.h"
#include "util-privs.h"
/*
* we put this here, because we only use it here in main.
@ -122,12 +123,15 @@ volatile sig_atomic_t sigterm_count = 0;
static uint8_t sigflags = 0;
/* Run mode selected */
/** Run mode selected */
int run_mode = MODE_UNKNOWN;
/* Maximum packets to simultaneously process. */
/** Maximum packets to simultaneously process. */
intmax_t max_pending_packets;
/** set caps or not */
int sc_set_caps;
int RunmodeIsUnittests(void) {
if (run_mode == MODE_UNITTEST)
return 1;
@ -401,10 +405,18 @@ int main(int argc, char **argv)
int dump_config = 0;
int list_unittests = 0;
int daemon = 0;
char *user_name = NULL;
char *group_name = NULL;
uint8_t do_setuid = FALSE;
uint8_t do_setgid = FALSE;
uint32_t userid = 0;
uint32_t groupid = 0;
char *log_dir;
struct stat buf;
sc_set_caps = FALSE;
#ifdef OS_WIN32
WSADATA wsaData;
if (0 != WSAStartup(MAKEWORD(2, 2), &wsaData)) {
@ -431,6 +443,8 @@ int main(int argc, char **argv)
{"pidfile", required_argument, 0, 0},
{"init-errors-fatal", 0, 0, 0},
{"fatal-unittests", 0, 0, 0},
{"user", required_argument, 0, 0},
{"group", required_argument, 0, 0},
{NULL, 0, NULL, 0}
};
@ -489,6 +503,26 @@ int main(int argc, char **argv)
fprintf(stderr, "ERROR: Unit tests not enabled. Make sure to pass --enable-unittests to configure when building.\n");
exit(EXIT_FAILURE);
#endif /* UNITTESTS */
}
else if(strcmp((long_opts[option_index]).name, "user") == 0) {
#ifndef HAVE_LIBCAP_NG
SCLogError(SC_ERR_LIBCAP_NG_REQUIRED, "libcap-ng is required to"
" drop privileges, but it was not compiled into Suricata.");
exit(EXIT_FAILURE);
#else
user_name = optarg;
do_setuid = TRUE;
#endif /* HAVE_LIBCAP_NG */
}
else if(strcmp((long_opts[option_index]).name, "group") == 0) {
#ifndef HAVE_LIBCAP_NG
SCLogError(SC_ERR_LIBCAP_NG_REQUIRED, "libcap-ng is required to"
" drop privileges, but it was not compiled into Suricata.");
exit(EXIT_FAILURE);
#else
group_name = optarg;
do_setgid = TRUE;
#endif /* HAVE_LIBCAP_NG */
}
break;
case 'c':
@ -834,6 +868,24 @@ int main(int argc, char **argv)
SignalHandlerSetup(SIGHUP, SignalHandlerSighup);
#endif /* OS_WIN32 */
/* Get the suricata user ID to given user ID */
if (do_setuid == TRUE) {
if (SCGetUserID(user_name, group_name, &userid, &groupid) != 0) {
SCLogError(SC_ERR_UID_FAILED, "failed in getting user ID");
exit(EXIT_FAILURE);
}
sc_set_caps = TRUE;
/* Get the suricata group ID to given group ID */
} else if (do_setgid == TRUE) {
if (SCGetGroupID(group_name, &groupid) != 0) {
SCLogError(SC_ERR_GID_FAILED, "failed in getting group ID");
exit(EXIT_FAILURE);
}
sc_set_caps = TRUE;
}
/* pre allocate packets */
SCLogDebug("preallocating packets... packet size %" PRIuMAX "", (uintmax_t)sizeof(Packet));
int i = 0;
@ -875,7 +927,11 @@ int main(int argc, char **argv)
memset(&start_time, 0, sizeof(start_time));
gettimeofday(&start_time, NULL);
SCDropMainThreadCaps(userid, groupid);
RunModeInitializeOutputs();
/* run the selected runmode */
if (run_mode == MODE_PCAP_DEV) {
//RunModeIdsPcap3(de_ctx, pcap_dev);
//RunModeIdsPcap2(de_ctx, pcap_dev);

@ -66,6 +66,8 @@ typedef struct ThreadVars_ {
SCMutex *m;
SCCondT *cond;
uint8_t cap_flags; /**< Flags to indicate the capabilities of all the
TmModules resgitered under this thread */
struct ThreadVars_ *next;
struct ThreadVars_ *prev;
} ThreadVars;

@ -21,6 +21,9 @@ typedef struct TmModule_ {
TmEcode (*Func)(ThreadVars *, Packet *, void *, PacketQueue *);
void (*RegisterTests)(void);
uint8_t cap_flags; /**< Flags to indicate the capability requierment of
the given TmModule */
} TmModule;
enum {

@ -19,6 +19,7 @@
#include "util-debug.h"
#include <pthread.h>
#include <unistd.h>
#include "util-privs.h"
#ifdef OS_FREEBSD
#include <sched.h>
@ -131,6 +132,9 @@ void *TmThreadsSlot1NoIn(void *td) {
/* Set the thread name */
SCSetThreadName(tv->name);
/* Drop the capabilities for this thread */
SCDropCaps(tv);
if (tv->thread_setup_flags != 0)
TmThreadSetupOptions(tv);
@ -198,6 +202,9 @@ void *TmThreadsSlot1NoOut(void *td) {
/* Set the thread name */
SCSetThreadName(tv->name);
/* Drop the capabilities for this thread */
SCDropCaps(tv);
if (tv->thread_setup_flags != 0)
TmThreadSetupOptions(tv);
@ -258,6 +265,9 @@ void *TmThreadsSlot1NoInOut(void *td) {
/* Set the thread name */
SCSetThreadName(tv->name);
/* Drop the capabilities for this thread */
SCDropCaps(tv);
if (tv->thread_setup_flags != 0)
TmThreadSetupOptions(tv);
@ -322,6 +332,9 @@ void *TmThreadsSlot1(void *td) {
/* Set the thread name */
SCSetThreadName(tv->name);
/* Drop the capabilities for this thread */
SCDropCaps(tv);
if (tv->thread_setup_flags != 0)
TmThreadSetupOptions(tv);
@ -442,6 +455,9 @@ void *TmThreadsSlotVar(void *td) {
/* Set the thread name */
SCSetThreadName(tv->name);
/* Drop the capabilities for this thread */
SCDropCaps(tv);
if (tv->thread_setup_flags != 0)
TmThreadSetupOptions(tv);
@ -571,6 +587,7 @@ void Tm1SlotSetFunc(ThreadVars *tv, TmModule *tm, void *data) {
s1->s.SlotFunc = tm->Func;
s1->s.SlotThreadExitPrintStats = tm->ThreadExitPrintStats;
s1->s.SlotThreadDeinit = tm->ThreadDeinit;
tv->cap_flags |= tm->cap_flags;
}
void TmVarSlotSetFuncAppend(ThreadVars *tv, TmModule *tm, void *data) {
@ -586,6 +603,7 @@ void TmVarSlotSetFuncAppend(ThreadVars *tv, TmModule *tm, void *data) {
slot->SlotFunc = tm->Func;
slot->SlotThreadExitPrintStats = tm->ThreadExitPrintStats;
slot->SlotThreadDeinit = tm->ThreadDeinit;
tv->cap_flags |= tm->cap_flags;
if (s->s == NULL) {
s->s = slot;

@ -146,6 +146,11 @@ const char * SCErrorToString(SCError err)
CASE_CODE (SC_ERR_PIDFILE_OPEN);
CASE_CODE (SC_ERR_PIDFILE_WRITE);
CASE_CODE (SC_ERR_PIDFILE_DAEMON);
CASE_CODE (SC_ERR_UID_FAILED);
CASE_CODE (SC_ERR_GID_FAILED);
CASE_CODE (SC_ERR_CHANGING_CAPS_FAILED);
CASE_CODE (SC_ERR_LIBCAP_NG_REQUIRED);
CASE_CODE (SC_ERR_LIBNET11_INCOMPATIBLE_WITH_LIBCAP_NG);
default:
return "UNKNOWN_ERROR";

@ -162,6 +162,11 @@ typedef enum {
SC_ERR_PIDFILE_OPEN,
SC_ERR_PIDFILE_WRITE,
SC_ERR_PIDFILE_DAEMON,
SC_ERR_UID_FAILED,
SC_ERR_GID_FAILED,
SC_ERR_CHANGING_CAPS_FAILED,
SC_ERR_LIBCAP_NG_REQUIRED,
SC_ERR_LIBNET11_INCOMPATIBLE_WITH_LIBCAP_NG,
} SCError;

@ -0,0 +1,205 @@
/* Copyright (c) 2010 Open Infomation Security Foundation */
/**
* \file
* \author Gurvinder Singh <gurvindersinghdahiya@gmail.com>
*
* \brief File to drop the engine capabilities using libcap-ng by
* Steve Grubb
*/
#include <grp.h>
#include <pwd.h>
#include "util-debug.h"
#include "suricata-common.h"
#ifdef HAVE_LIBCAP_NG
#include <cap-ng.h>
#include <sys/prctl.h>
#include "threadvars.h"
#include "util-cpu.h"
#include "util-privs.h"
/** flag indicating if we'll be using caps */
extern int sc_set_caps;
/**
* \brief Drop all the previliges of the given thread
*/
void SCDropAllCaps()
{
capng_clear(CAPNG_SELECT_BOTH);
if (capng_apply(CAPNG_SELECT_BOTH) < 0) {
SCLogError(SC_ERR_CHANGING_CAPS_FAILED, "failed in dropping the caps");
exit(EXIT_FAILURE);
}
}
/**
* \brief Drop the previliges of the main thread
*/
void SCDropMainThreadCaps(uint32_t userid, uint32_t groupid)
{
if (sc_set_caps == FALSE)
return;
capng_clear(CAPNG_SELECT_BOTH);
capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
CAP_NET_RAW, /* needed for pcap live mode */
#ifdef NFQ
CAP_NET_ADMIN, /* needed for nfqueue inline mode */
#endif
-1);
if (capng_change_id(userid, groupid, CAPNG_DROP_SUPP_GRP |
CAPNG_CLEAR_BOUNDING) < 0)
{
SCLogError(SC_ERR_CHANGING_CAPS_FAILED, "capng_change_id for main thread"
" failed");
exit(EXIT_FAILURE);
}
SCLogInfo("dropped the caps for main thread");
}
void SCDropCaps(ThreadVars *tv) {
#if 0
capng_clear(CAPNG_SELECT_BOTH);
capng_apply(CAPNG_SELECT_BOTH);
if (tv->cap_flags & SC_CAP_IPC_LOCK) {
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_IPC_LOCK);
capng_apply(CAPNG_SELECT_CAPS);
SCLogDebug("For thread \"%s\" CAP_IPC_LOCK has been set", tv->name);
}
if (tv->cap_flags & SC_CAP_NET_ADMIN) {
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_ADMIN);
capng_apply(CAPNG_SELECT_CAPS);
SCLogDebug("For thread \"%s\" CAP_NET_ADMIN has been set", tv->name);
}
if (tv->cap_flags & SC_CAP_NET_BIND_SERVICE) {
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_BIND_SERVICE);
capng_apply(CAPNG_SELECT_CAPS);
SCLogDebug("For thread \"%s\" CAP_NET_BIND_SERVICE has been set", tv->name);
}
if (tv->cap_flags & SC_CAP_NET_BROADCAST) {
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_BROADCAST);
capng_apply(CAPNG_SELECT_CAPS);
SCLogDebug("For thread \"%s\" CAP_NET_BROADCAST has been set", tv->name);
}
if (tv->cap_flags & SC_CAP_NET_RAW) {
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_RAW);
capng_apply(CAPNG_SELECT_CAPS);
SCLogDebug("For thread \"%s\" CAP_NET_RAW has been set", tv->name);
}
if (tv->cap_flags & SC_CAP_SYS_ADMIN) {
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_SYS_ADMIN);
capng_apply(CAPNG_SELECT_CAPS);
SCLogDebug("For thread \"%s\" CAP_SYS_ADMIN has been set", tv->name);
}
if (tv->cap_flags & SC_CAP_SYS_RAW_IO) {
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_SYS_RAWIO);
capng_apply(CAPNG_SELECT_CAPS);
SCLogDebug("For thread \"%s\" CAP_SYS_RAWIO has been set", tv->name);
}
#endif
}
#endif /* HAVE_LIBCAP_NG */
/**
* \brief Function to get the user and group ID from the specified user name
*
* \param user_name pointer to the given user name
* \param uid pointer to the user id in which result will be stored
* \param gid pointer to the group id in which result will be stored
*
* \retval upon success it return 0
*/
int SCGetUserID(char *user_name, char *group_name, uint32_t *uid, uint32_t *gid)
{
uint32_t userid = 0;
uint32_t groupid = 0;
struct passwd *pw;
/* Get the user ID */
if (isdigit(user_name[0]) != 0) {
userid = atoi(user_name);
pw = getpwuid(userid);
if (pw == NULL) {
SCLogError(SC_ERR_UID_FAILED, "unable to get the user ID, "
"check if user exist!!");
exit(EXIT_FAILURE);
}
} else {
pw = getpwnam(user_name);
if (pw == NULL) {
SCLogError(SC_ERR_UID_FAILED, "unable to get the user ID, "
"check if user exist!!");
exit(EXIT_FAILURE);
}
userid = pw->pw_uid;
}
/* Get the group ID */
if (group_name != NULL) {
struct group *gp;
if (isdigit(group_name[0]) != 0) {
groupid = atoi(group_name);
} else {
gp = getgrnam(group_name);
if (gp == NULL) {
SCLogError(SC_ERR_GID_FAILED, "unable to get the group"
" ID, check if group exist!!");
exit(EXIT_FAILURE);
}
groupid = gp->gr_gid;
}
} else {
groupid = pw->pw_gid;
}
/* close the group database */
endgrent();
/* close the user database */
endpwent();
*uid = userid;
*gid = groupid;
return 0;
}
/**
* \brief Function to get the group ID from the specified group name
*
* \param group_name pointer to the given group name
* \param gid pointer to the group id in which result will be stored
*
* \retval upon success it return 0
*/
int SCGetGroupID(char *group_name, uint32_t *gid)
{
uint32_t grpid = 0;
struct group *gp;
/* Get the group ID */
if (isdigit(group_name[0]) != 0) {
grpid = atoi(group_name);
} else {
gp = getgrnam(group_name);
if (gp == NULL) {
SCLogError(SC_ERR_GID_FAILED, "unable to get the group ID,"
" check if group exist!!");
exit(EXIT_FAILURE);
}
grpid = gp->gr_gid;
}
/* close the group database */
endgrent();
*gid = grpid;
return 0;
}

@ -0,0 +1,82 @@
/* Copyright (c) 2010 Open Infomation Security Foundation */
/**
* \author Gurvinder Singh <gurvindersinghdahiya@gmail.com>
*
*/
#ifndef _UTIL_PRIVS_H
#define _UTIL_PRIVS_H
#define SC_CAP_NONE 0x01
#define SC_CAP_SYS_ADMIN 0x02
#define SC_CAP_SYS_RAW_IO 0x04
#define SC_CAP_IPC_LOCK 0x08
#define SC_CAP_NET_ADMIN 0x10
#define SC_CAP_NET_RAW 0x20
#define SC_CAP_NET_BIND_SERVICE 0x40
#define SC_CAP_NET_BROADCAST 0x80
#ifndef HAVE_LIBCAP_NG
#define SCDropCaps(...)
#define SCDropMainThreadCaps(...)
#else
#include "threadvars.h"
#include "util-debug.h"
#include <cap-ng.h>
/**Drop the previliges of the given thread tv, based on the thread cap_flags
* which implies the capability requirement of the given thread. Initially all
* caps are dropped and later, the required caps are set for the given thread
*/
void SCDropCaps(ThreadVars *tv);
/*
#define SCDropCaps(tv) ({ \
capng_clear(CAPNG_SELECT_BOTH); \
capng_apply(CAPNG_SELECT_BOTH); \
if (tv->cap_flags & SC_CAP_IPC_LOCK) { \
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_IPC_LOCK); \
capng_apply(CAPNG_SELECT_CAPS); \
SCLogDebug("For thread \"%s\" CAP_IPC_LOCK has been set", tv->name); \
} \
if (tv->cap_flags & SC_CAP_NET_ADMIN) { \
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_ADMIN); \
capng_apply(CAPNG_SELECT_CAPS); \
SCLogDebug("For thread \"%s\" CAP_NET_ADMIN has been set", tv->name); \
} \
if (tv->cap_flags & SC_CAP_NET_BIND_SERVICE) { \
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_BIND_SERVICE); \
capng_apply(CAPNG_SELECT_CAPS); \
SCLogDebug("For thread \"%s\" CAP_NET_BIND_SERVICE has been set", tv->name); \
} \
if (tv->cap_flags & SC_CAP_NET_BROADCAST) { \
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_BROADCAST); \
capng_apply(CAPNG_SELECT_CAPS); \
SCLogDebug("For thread \"%s\" CAP_NET_BROADCAST has been set", tv->name); \
} \
if (tv->cap_flags & SC_CAP_NET_RAW) { \
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_RAW); \
capng_apply(CAPNG_SELECT_CAPS); \
SCLogDebug("For thread \"%s\" CAP_NET_RAW has been set", tv->name); \
} \
if (tv->cap_flags & SC_CAP_SYS_ADMIN) { \
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_SYS_ADMIN); \
capng_apply(CAPNG_SELECT_CAPS); \
SCLogDebug("For thread \"%s\" CAP_SYS_ADMIN has been set", tv->name); \
} \
if (tv->cap_flags & SC_CAP_SYS_RAW_IO) { \
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_SYS_RAWIO); \
capng_apply(CAPNG_SELECT_CAPS); \
SCLogDebug("For thread \"%s\" CAP_SYS_RAWIO has been set", tv->name); \
} \
})
*/
void SCDropMainThreadCaps(uint32_t , uint32_t );
#endif /* HAVE_LIBCAP_NG */
int SCGetUserID(char *, char *, uint32_t *, uint32_t *);
int SCGetGroupID(char *, uint32_t *);
#endif /* _UTIL_PRIVS_H */
Loading…
Cancel
Save