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 "runmodes.h"
44 
45 /** flag indicating if we'll be using caps */
46 extern bool sc_set_caps;
47 
48 /**
49  * \brief Drop the privileges of the main thread
50  */
51 void SCDropMainThreadCaps(uint32_t userid, uint32_t groupid)
52 {
53  if (!sc_set_caps)
54  return;
55 
56  capng_clear(CAPNG_SELECT_BOTH);
57 
58  switch (SCRunmodeGet()) {
59  case RUNMODE_PCAP_DEV:
60  case RUNMODE_AFP_DEV:
61  case RUNMODE_AFXDP_DEV:
62  capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
63  CAP_NET_RAW, /* needed for pcap live mode */
64  CAP_SYS_NICE,
65  CAP_NET_ADMIN,
66  -1);
67  break;
68  case RUNMODE_NFLOG:
69  case RUNMODE_NFQ:
70  capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
71  CAP_NET_ADMIN, /* needed for nflog and nfqueue inline mode */
72  CAP_SYS_NICE,
73  -1);
74  break;
75  }
76 
77  if (capng_change_id(userid, groupid, CAPNG_DROP_SUPP_GRP |
78  CAPNG_CLEAR_BOUNDING) < 0)
79  {
80  FatalError("capng_change_id for main thread"
81  " failed");
82  }
83 
84  SCLogInfo("dropped the caps for main thread");
85 }
86 
88 {
89 #if 0
90  capng_clear(CAPNG_SELECT_BOTH);
91  capng_apply(CAPNG_SELECT_BOTH);
92  if (tv->cap_flags & SC_CAP_IPC_LOCK) {
93  capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_IPC_LOCK);
94  capng_apply(CAPNG_SELECT_CAPS);
95  SCLogDebug("For thread \"%s\" CAP_IPC_LOCK has been set", tv->name);
96  }
97  if (tv->cap_flags & SC_CAP_NET_ADMIN) {
98  capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_ADMIN);
99  capng_apply(CAPNG_SELECT_CAPS);
100  SCLogDebug("For thread \"%s\" CAP_NET_ADMIN has been set", tv->name);
101  }
103  capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_BIND_SERVICE);
104  capng_apply(CAPNG_SELECT_CAPS);
105  SCLogDebug("For thread \"%s\" CAP_NET_BIND_SERVICE has been set", tv->name);
106  }
108  capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_BROADCAST);
109  capng_apply(CAPNG_SELECT_CAPS);
110  SCLogDebug("For thread \"%s\" CAP_NET_BROADCAST has been set", tv->name);
111  }
112  if (tv->cap_flags & SC_CAP_NET_RAW) {
113  capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_RAW);
114  capng_apply(CAPNG_SELECT_CAPS);
115  SCLogDebug("For thread \"%s\" CAP_NET_RAW has been set", tv->name);
116  }
117  if (tv->cap_flags & SC_CAP_SYS_ADMIN) {
118  capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_SYS_ADMIN);
119  capng_apply(CAPNG_SELECT_CAPS);
120  SCLogDebug("For thread \"%s\" CAP_SYS_ADMIN has been set", tv->name);
121  }
122  if (tv->cap_flags & SC_CAP_SYS_RAW_IO) {
123  capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_SYS_RAWIO);
124  capng_apply(CAPNG_SELECT_CAPS);
125  SCLogDebug("For thread \"%s\" CAP_SYS_RAWIO has been set", tv->name);
126  }
127 #endif
128 }
129 
130 #endif /* HAVE_LIBCAP_NG */
131 
132 /**
133  * \brief Function to get the user and group ID from the specified user name
134  *
135  * \param user_name pointer to the given user name
136  * \param uid pointer to the user id in which result will be stored
137  * \param gid pointer to the group id in which result will be stored
138  *
139  * \retval FatalError on a failure
140  */
141 void SCGetUserID(const char *user_name, const char *group_name, uint32_t *uid, uint32_t *gid)
142 {
143  uint32_t userid = 0;
144  uint32_t groupid = 0;
145  struct passwd *pw;
146 
147  if (user_name == NULL || strlen(user_name) == 0) {
148  FatalError("no user name was provided - ensure it is specified either in the configuration "
149  "file (run-as.user) or in command-line arguments (--user)");
150  }
151 
152  /* Get the user ID */
153  if (isdigit((unsigned char)user_name[0]) != 0) {
154  if (ByteExtractStringUint32(&userid, 10, 0, (const char *)user_name) < 0) {
155  FatalError("invalid user id value: '%s'", user_name);
156  }
157  pw = getpwuid(userid);
158  if (pw == NULL) {
159  FatalError("unable to get the user ID, "
160  "check if user exist!!");
161  }
162  } else {
163  pw = getpwnam(user_name);
164  if (pw == NULL) {
165  FatalError("unable to get the user ID, "
166  "check if user exist!!");
167  }
168  userid = pw->pw_uid;
169  }
170 
171  /* Get the group ID */
172  if (group_name != NULL) {
173  struct group *gp;
174 
175  if (isdigit((unsigned char)group_name[0]) != 0) {
176  if (ByteExtractStringUint32(&groupid, 10, 0, (const char *)group_name) < 0) {
177  FatalError("invalid group id: '%s'", group_name);
178  }
179  } else {
180  gp = getgrnam(group_name);
181  if (gp == NULL) {
182  FatalError("unable to get the group"
183  " ID, check if group exist!!");
184  }
185  groupid = gp->gr_gid;
186  }
187  } else {
188  groupid = pw->pw_gid;
189  }
190 
191  /* close the group database */
192  endgrent();
193  /* close the user database */
194  endpwent();
195 
196  *uid = userid;
197  *gid = groupid;
198 }
199 
200 /**
201  * \brief Function to get the group ID from the specified group name
202  *
203  * \param group_name pointer to the given group name
204  * \param gid pointer to the group id in which result will be stored
205  *
206  * \retval FatalError on a failure
207  */
208 void SCGetGroupID(const char *group_name, uint32_t *gid)
209 {
210  uint32_t grpid = 0;
211  struct group *gp;
212 
213  if (group_name == NULL || strlen(group_name) == 0) {
214  FatalError("no group name was provided - ensure it is specified either in the "
215  "configuration file (run-as.group) or in command-line arguments (--group)");
216  }
217 
218  /* Get the group ID */
219  if (isdigit((unsigned char)group_name[0]) != 0) {
220  if (ByteExtractStringUint32(&grpid, 10, 0, (const char *)group_name) < 0) {
221  FatalError("invalid group id: '%s'", group_name);
222  }
223  } else {
224  gp = getgrnam(group_name);
225  if (gp == NULL) {
226  FatalError("unable to get the group ID,"
227  " check if group exist!!");
228  }
229  grpid = gp->gr_gid;
230  }
231 
232  /* close the group database */
233  endgrent();
234 
235  *gid = grpid;
236 }
237 
238 #ifdef __OpenBSD__
239 int SCPledge(void)
240 {
241  int ret = pledge("stdio rpath wpath cpath fattr unix dns bpf", NULL);
242 
243  if (ret != 0) {
244  SCLogError("unable to pledge,"
245  " check permissions!! ret=%i errno=%i",
246  ret, errno);
247  exit(EXIT_FAILURE);
248  }
249 
250  return 0;
251 }
252 #endif /* __OpenBSD__ */
253 #endif /* OS_WIN32 */
RUNMODE_AFXDP_DEV
@ RUNMODE_AFXDP_DEV
Definition: runmodes.h:37
util-byte.h
SCRunmodeGet
int SCRunmodeGet(void)
Get the current run mode.
Definition: suricata.c:261
ThreadVars_::name
char name[16]
Definition: threadvars.h:64
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
RUNMODE_NFLOG
@ RUNMODE_NFLOG
Definition: runmodes.h:32
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:208
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
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:187
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
group
uint8_t group
Definition: app-layer-dnp3.h:0
suricata-common.h
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:31
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:141
suricata.h
RUNMODE_AFP_DEV
@ RUNMODE_AFP_DEV
Definition: runmodes.h:36
SC_CAP_NET_RAW
#define SC_CAP_NET_RAW
Definition: util-privs.h:32