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 int 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 == FALSE)
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 upon success it return 0
149  */
150 int 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  /* Get the user ID */
157  if (isdigit((unsigned char)user_name[0]) != 0) {
158  if (ByteExtractStringUint32(&userid, 10, 0, (const char *)user_name) < 0) {
159  FatalError("invalid user id value: '%s'", user_name);
160  }
161  pw = getpwuid(userid);
162  if (pw == NULL) {
163  FatalError("unable to get the user ID, "
164  "check if user exist!!");
165  }
166  } else {
167  pw = getpwnam(user_name);
168  if (pw == NULL) {
169  FatalError("unable to get the user ID, "
170  "check if user exist!!");
171  }
172  userid = pw->pw_uid;
173  }
174 
175  /* Get the group ID */
176  if (group_name != NULL) {
177  struct group *gp;
178 
179  if (isdigit((unsigned char)group_name[0]) != 0) {
180  if (ByteExtractStringUint32(&groupid, 10, 0, (const char *)group_name) < 0) {
181  FatalError("invalid group id: '%s'", group_name);
182  }
183  } else {
184  gp = getgrnam(group_name);
185  if (gp == NULL) {
186  FatalError("unable to get the group"
187  " ID, check if group exist!!");
188  }
189  groupid = gp->gr_gid;
190  }
191  } else {
192  groupid = pw->pw_gid;
193  }
194 
195  /* close the group database */
196  endgrent();
197  /* close the user database */
198  endpwent();
199 
200  *uid = userid;
201  *gid = groupid;
202 
203  return 0;
204 }
205 
206 /**
207  * \brief Function to get the group ID from the specified group name
208  *
209  * \param group_name pointer to the given group name
210  * \param gid pointer to the group id in which result will be stored
211  *
212  * \retval upon success it return 0
213  */
214 int SCGetGroupID(const char *group_name, uint32_t *gid)
215 {
216  uint32_t grpid = 0;
217  struct group *gp;
218 
219  /* Get the group ID */
220  if (isdigit((unsigned char)group_name[0]) != 0) {
221  if (ByteExtractStringUint32(&grpid, 10, 0, (const char *)group_name) < 0) {
222  FatalError("invalid group id: '%s'", group_name);
223  }
224  } else {
225  gp = getgrnam(group_name);
226  if (gp == NULL) {
227  FatalError("unable to get the group ID,"
228  " check if group exist!!");
229  }
230  grpid = gp->gr_gid;
231  }
232 
233  /* close the group database */
234  endgrent();
235 
236  *gid = grpid;
237 
238  return 0;
239 }
240 
241 #ifdef __OpenBSD__
242 int SCPledge(void)
243 {
244  int ret = pledge("stdio rpath wpath cpath fattr unix dns bpf", NULL);
245 
246  if (ret != 0) {
247  SCLogError("unable to pledge,"
248  " check permissions!! ret=%i errno=%i",
249  ret, errno);
250  exit(EXIT_FAILURE);
251  }
252 
253  return 0;
254 }
255 #endif /* __OpenBSD__ */
256 #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
SCGetUserID
int 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
RUNMODE_PCAP_DEV
@ RUNMODE_PCAP_DEV
Definition: runmodes.h:29
SCPledge
#define SCPledge(...)
Definition: util-privs.h:99
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
SCGetGroupID
int SCGetGroupID(const char *group_name, uint32_t *gid)
Function to get the group ID from the specified group name.
Definition: util-privs.c:214
FALSE
#define FALSE
Definition: suricata-common.h:34
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
suricata.h
sc_set_caps
int sc_set_caps
Definition: suricata.c:192
RUNMODE_AFP_DEV
@ RUNMODE_AFP_DEV
Definition: runmodes.h:37
SC_CAP_NET_RAW
#define SC_CAP_NET_RAW
Definition: util-privs.h:32