suricata
util-privs.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2010 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Gurvinder Singh <gurvindersinghdahiya@gmail.com>
22  *
23  * File to drop the engine capabilities using libcap-ng by
24  * Steve Grubb
25  */
26 
27 #ifndef OS_WIN32
28 
29 #include "suricata-common.h"
30 #include "util-debug.h"
31 #include "suricata.h"
32 
33 #include "util-privs.h"
34 #include "util-byte.h"
35 
36 #ifdef HAVE_LIBCAP_NG
37 
38 #include <cap-ng.h>
39 #ifdef HAVE_SYS_PRCTL_H
40 #include <sys/prctl.h>
41 #endif
42 #include "threadvars.h"
43 #include "util-cpu.h"
44 #include "runmodes.h"
45 
46 /** flag indicating if we'll be using caps */
47 extern bool sc_set_caps;
48 
49 /** our current runmode */
50 extern int run_mode;
51 
52 /**
53  * \brief Drop the privileges of the main thread
54  */
55 void SCDropMainThreadCaps(uint32_t userid, uint32_t groupid)
56 {
57  if (!sc_set_caps)
58  return;
59 
60  capng_clear(CAPNG_SELECT_BOTH);
61 
62  switch (run_mode) {
63  case RUNMODE_PCAP_DEV:
64  case RUNMODE_AFP_DEV:
65  case RUNMODE_AFXDP_DEV:
66  capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
67  CAP_NET_RAW, /* needed for pcap live mode */
68  CAP_SYS_NICE,
69  CAP_NET_ADMIN,
70  -1);
71  break;
72  case RUNMODE_PFRING:
73  capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
74  CAP_NET_ADMIN, CAP_NET_RAW, CAP_SYS_NICE,
75  -1);
76  break;
77  case RUNMODE_NFLOG:
78  case RUNMODE_NFQ:
79  capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
80  CAP_NET_ADMIN, /* needed for nflog and nfqueue inline mode */
81  CAP_SYS_NICE,
82  -1);
83  break;
84  }
85 
86  if (capng_change_id(userid, groupid, CAPNG_DROP_SUPP_GRP |
87  CAPNG_CLEAR_BOUNDING) < 0)
88  {
89  FatalError("capng_change_id for main thread"
90  " failed");
91  }
92 
93  SCLogInfo("dropped the caps for main thread");
94 }
95 
97 {
98 #if 0
99  capng_clear(CAPNG_SELECT_BOTH);
100  capng_apply(CAPNG_SELECT_BOTH);
101  if (tv->cap_flags & SC_CAP_IPC_LOCK) {
102  capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_IPC_LOCK);
103  capng_apply(CAPNG_SELECT_CAPS);
104  SCLogDebug("For thread \"%s\" CAP_IPC_LOCK has been set", tv->name);
105  }
106  if (tv->cap_flags & SC_CAP_NET_ADMIN) {
107  capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_ADMIN);
108  capng_apply(CAPNG_SELECT_CAPS);
109  SCLogDebug("For thread \"%s\" CAP_NET_ADMIN has been set", tv->name);
110  }
112  capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_BIND_SERVICE);
113  capng_apply(CAPNG_SELECT_CAPS);
114  SCLogDebug("For thread \"%s\" CAP_NET_BIND_SERVICE has been set", tv->name);
115  }
117  capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_BROADCAST);
118  capng_apply(CAPNG_SELECT_CAPS);
119  SCLogDebug("For thread \"%s\" CAP_NET_BROADCAST has been set", tv->name);
120  }
121  if (tv->cap_flags & SC_CAP_NET_RAW) {
122  capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_RAW);
123  capng_apply(CAPNG_SELECT_CAPS);
124  SCLogDebug("For thread \"%s\" CAP_NET_RAW has been set", tv->name);
125  }
126  if (tv->cap_flags & SC_CAP_SYS_ADMIN) {
127  capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_SYS_ADMIN);
128  capng_apply(CAPNG_SELECT_CAPS);
129  SCLogDebug("For thread \"%s\" CAP_SYS_ADMIN has been set", tv->name);
130  }
131  if (tv->cap_flags & SC_CAP_SYS_RAW_IO) {
132  capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_SYS_RAWIO);
133  capng_apply(CAPNG_SELECT_CAPS);
134  SCLogDebug("For thread \"%s\" CAP_SYS_RAWIO has been set", tv->name);
135  }
136 #endif
137 }
138 
139 #endif /* HAVE_LIBCAP_NG */
140 
141 /**
142  * \brief Function to get the user and group ID from the specified user name
143  *
144  * \param user_name pointer to the given user name
145  * \param uid pointer to the user id in which result will be stored
146  * \param gid pointer to the group id in which result will be stored
147  *
148  * \retval FatalError on a failure
149  */
150 void SCGetUserID(const char *user_name, const char *group_name, uint32_t *uid, uint32_t *gid)
151 {
152  uint32_t userid = 0;
153  uint32_t groupid = 0;
154  struct passwd *pw;
155 
156  if (user_name == NULL || strlen(user_name) == 0) {
157  FatalError("no user name was provided - ensure it is specified either in the configuration "
158  "file (run-as.user) or in command-line arguments (--user)");
159  }
160 
161  /* Get the user ID */
162  if (isdigit((unsigned char)user_name[0]) != 0) {
163  if (ByteExtractStringUint32(&userid, 10, 0, (const char *)user_name) < 0) {
164  FatalError("invalid user id value: '%s'", user_name);
165  }
166  pw = getpwuid(userid);
167  if (pw == NULL) {
168  FatalError("unable to get the user ID, "
169  "check if user exist!!");
170  }
171  } else {
172  pw = getpwnam(user_name);
173  if (pw == NULL) {
174  FatalError("unable to get the user ID, "
175  "check if user exist!!");
176  }
177  userid = pw->pw_uid;
178  }
179 
180  /* Get the group ID */
181  if (group_name != NULL) {
182  struct group *gp;
183 
184  if (isdigit((unsigned char)group_name[0]) != 0) {
185  if (ByteExtractStringUint32(&groupid, 10, 0, (const char *)group_name) < 0) {
186  FatalError("invalid group id: '%s'", group_name);
187  }
188  } else {
189  gp = getgrnam(group_name);
190  if (gp == NULL) {
191  FatalError("unable to get the group"
192  " ID, check if group exist!!");
193  }
194  groupid = gp->gr_gid;
195  }
196  } else {
197  groupid = pw->pw_gid;
198  }
199 
200  /* close the group database */
201  endgrent();
202  /* close the user database */
203  endpwent();
204 
205  *uid = userid;
206  *gid = groupid;
207 }
208 
209 /**
210  * \brief Function to get the group ID from the specified group name
211  *
212  * \param group_name pointer to the given group name
213  * \param gid pointer to the group id in which result will be stored
214  *
215  * \retval FatalError on a failure
216  */
217 void SCGetGroupID(const char *group_name, uint32_t *gid)
218 {
219  uint32_t grpid = 0;
220  struct group *gp;
221 
222  if (group_name == NULL || strlen(group_name) == 0) {
223  FatalError("no group name was provided - ensure it is specified either in the "
224  "configuration file (run-as.group) or in command-line arguments (--group)");
225  }
226 
227  /* Get the group ID */
228  if (isdigit((unsigned char)group_name[0]) != 0) {
229  if (ByteExtractStringUint32(&grpid, 10, 0, (const char *)group_name) < 0) {
230  FatalError("invalid group id: '%s'", group_name);
231  }
232  } else {
233  gp = getgrnam(group_name);
234  if (gp == NULL) {
235  FatalError("unable to get the group ID,"
236  " check if group exist!!");
237  }
238  grpid = gp->gr_gid;
239  }
240 
241  /* close the group database */
242  endgrent();
243 
244  *gid = grpid;
245 }
246 
247 #ifdef __OpenBSD__
248 int SCPledge(void)
249 {
250  int ret = pledge("stdio rpath wpath cpath fattr unix dns bpf", NULL);
251 
252  if (ret != 0) {
253  SCLogError("unable to pledge,"
254  " check permissions!! ret=%i errno=%i",
255  ret, errno);
256  exit(EXIT_FAILURE);
257  }
258 
259  return 0;
260 }
261 #endif /* __OpenBSD__ */
262 #endif /* OS_WIN32 */
RUNMODE_AFXDP_DEV
@ RUNMODE_AFXDP_DEV
Definition: runmodes.h:38
util-byte.h
ThreadVars_::name
char name[16]
Definition: threadvars.h:64
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
RUNMODE_NFLOG
@ RUNMODE_NFLOG
Definition: runmodes.h:33
RUNMODE_PCAP_DEV
@ RUNMODE_PCAP_DEV
Definition: runmodes.h:29
SCPledge
#define SCPledge(...)
Definition: util-privs.h:99
SCGetGroupID
void SCGetGroupID(const char *group_name, uint32_t *gid)
Function to get the group ID from the specified group name.
Definition: util-privs.c:217
util-privs.h
ByteExtractStringUint32
int ByteExtractStringUint32(uint32_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:239
SCDropCaps
#define SCDropCaps(...)
Definition: util-privs.h:89
SC_CAP_NET_BROADCAST
#define SC_CAP_NET_BROADCAST
Definition: util-privs.h:34
ThreadVars_::cap_flags
uint8_t cap_flags
Definition: threadvars.h:80
SC_CAP_NET_BIND_SERVICE
#define SC_CAP_NET_BIND_SERVICE
Definition: util-privs.h:33
util-debug.h
util-cpu.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
SC_CAP_IPC_LOCK
#define SC_CAP_IPC_LOCK
Definition: util-privs.h:30
SC_CAP_NET_ADMIN
#define SC_CAP_NET_ADMIN
Definition: util-privs.h:31
sc_set_caps
bool sc_set_caps
Definition: suricata.c:192
SC_CAP_SYS_ADMIN
#define SC_CAP_SYS_ADMIN
Definition: util-privs.h:28
SCDropMainThreadCaps
#define SCDropMainThreadCaps(...)
Definition: util-privs.h:90
runmodes.h
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:224
SC_CAP_SYS_RAW_IO
#define SC_CAP_SYS_RAW_IO
Definition: util-privs.h:29
RUNMODE_PFRING
@ RUNMODE_PFRING
Definition: runmodes.h:31
group
uint8_t group
Definition: app-layer-dnp3.h:0
suricata-common.h
run_mode
int run_mode
Definition: suricata.c:175
FatalError
#define FatalError(...)
Definition: util-debug.h:502
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
threadvars.h
RUNMODE_NFQ
@ RUNMODE_NFQ
Definition: runmodes.h:32
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
SCGetUserID
void SCGetUserID(const char *user_name, const char *group_name, uint32_t *uid, uint32_t *gid)
Function to get the user and group ID from the specified user name.
Definition: util-privs.c:150
suricata.h
RUNMODE_AFP_DEV
@ RUNMODE_AFP_DEV
Definition: runmodes.h:37
SC_CAP_NET_RAW
#define SC_CAP_NET_RAW
Definition: util-privs.h:32