diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:39:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:39:49 +0000 |
commit | a0aa2307322cd47bbf416810ac0292925e03be87 (patch) | |
tree | 37076262a026c4b48c8a0e84f44ff9187556ca35 /src/util-privs.c | |
parent | Initial commit. (diff) | |
download | suricata-a0aa2307322cd47bbf416810ac0292925e03be87.tar.xz suricata-a0aa2307322cd47bbf416810ac0292925e03be87.zip |
Adding upstream version 1:7.0.3.upstream/1%7.0.3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/util-privs.c')
-rw-r--r-- | src/util-privs.c | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/src/util-privs.c b/src/util-privs.c new file mode 100644 index 0000000..8210cc8 --- /dev/null +++ b/src/util-privs.c @@ -0,0 +1,262 @@ +/* Copyright (C) 2007-2010 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * 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 + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Gurvinder Singh <gurvindersinghdahiya@gmail.com> + * + * File to drop the engine capabilities using libcap-ng by + * Steve Grubb + */ + +#ifndef OS_WIN32 + +#include "suricata-common.h" +#include "util-debug.h" +#include "suricata.h" + +#include "util-privs.h" +#include "util-byte.h" + +#ifdef HAVE_LIBCAP_NG + +#include <cap-ng.h> +#ifdef HAVE_SYS_PRCTL_H +#include <sys/prctl.h> +#endif +#include "threadvars.h" +#include "util-cpu.h" +#include "runmodes.h" + +/** flag indicating if we'll be using caps */ +extern int sc_set_caps; + +/** our current runmode */ +extern int run_mode; + +/** + * \brief Drop the privileges of the main thread + */ +void SCDropMainThreadCaps(uint32_t userid, uint32_t groupid) +{ + if (sc_set_caps == FALSE) + return; + + capng_clear(CAPNG_SELECT_BOTH); + + switch (run_mode) { + case RUNMODE_PCAP_DEV: + case RUNMODE_AFP_DEV: + case RUNMODE_AFXDP_DEV: + capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, + CAP_NET_RAW, /* needed for pcap live mode */ + CAP_SYS_NICE, + CAP_NET_ADMIN, + -1); + break; + case RUNMODE_PFRING: + capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, + CAP_NET_ADMIN, CAP_NET_RAW, CAP_SYS_NICE, + -1); + break; + case RUNMODE_NFLOG: + case RUNMODE_NFQ: + capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, + CAP_NET_ADMIN, /* needed for nflog and nfqueue inline mode */ + CAP_SYS_NICE, + -1); + break; + } + + if (capng_change_id(userid, groupid, CAPNG_DROP_SUPP_GRP | + CAPNG_CLEAR_BOUNDING) < 0) + { + FatalError("capng_change_id for main thread" + " failed"); + } + + 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 FatalError on a failure + */ +void SCGetUserID(const char *user_name, const char *group_name, uint32_t *uid, uint32_t *gid) +{ + uint32_t userid = 0; + uint32_t groupid = 0; + struct passwd *pw; + + if (user_name == NULL || strlen(user_name) == 0) { + FatalError("no user name was provided - ensure it is specified either in the configuration " + "file (run-as.user) or in command-line arguments (--user)"); + } + + /* Get the user ID */ + if (isdigit((unsigned char)user_name[0]) != 0) { + if (ByteExtractStringUint32(&userid, 10, 0, (const char *)user_name) < 0) { + FatalError("invalid user id value: '%s'", user_name); + } + pw = getpwuid(userid); + if (pw == NULL) { + FatalError("unable to get the user ID, " + "check if user exist!!"); + } + } else { + pw = getpwnam(user_name); + if (pw == NULL) { + FatalError("unable to get the user ID, " + "check if user exist!!"); + } + userid = pw->pw_uid; + } + + /* Get the group ID */ + if (group_name != NULL) { + struct group *gp; + + if (isdigit((unsigned char)group_name[0]) != 0) { + if (ByteExtractStringUint32(&groupid, 10, 0, (const char *)group_name) < 0) { + FatalError("invalid group id: '%s'", group_name); + } + } else { + gp = getgrnam(group_name); + if (gp == NULL) { + FatalError("unable to get the group" + " ID, check if group exist!!"); + } + groupid = gp->gr_gid; + } + } else { + groupid = pw->pw_gid; + } + + /* close the group database */ + endgrent(); + /* close the user database */ + endpwent(); + + *uid = userid; + *gid = groupid; +} + +/** + * \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 FatalError on a failure + */ +void SCGetGroupID(const char *group_name, uint32_t *gid) +{ + uint32_t grpid = 0; + struct group *gp; + + if (group_name == NULL || strlen(group_name) == 0) { + FatalError("no group name was provided - ensure it is specified either in the " + "configuration file (run-as.group) or in command-line arguments (--group)"); + } + + /* Get the group ID */ + if (isdigit((unsigned char)group_name[0]) != 0) { + if (ByteExtractStringUint32(&grpid, 10, 0, (const char *)group_name) < 0) { + FatalError("invalid group id: '%s'", group_name); + } + } else { + gp = getgrnam(group_name); + if (gp == NULL) { + FatalError("unable to get the group ID," + " check if group exist!!"); + } + grpid = gp->gr_gid; + } + + /* close the group database */ + endgrent(); + + *gid = grpid; +} + +#ifdef __OpenBSD__ +int SCPledge(void) +{ + int ret = pledge("stdio rpath wpath cpath fattr unix dns bpf", NULL); + + if (ret != 0) { + SCLogError("unable to pledge," + " check permissions!! ret=%i errno=%i", + ret, errno); + exit(EXIT_FAILURE); + } + + return 0; +} +#endif /* __OpenBSD__ */ +#endif /* OS_WIN32 */ |