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