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 previliges 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  capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
66  CAP_NET_RAW, /* needed for pcap live mode */
67  CAP_SYS_NICE,
68  CAP_NET_ADMIN,
69  -1);
70  break;
71  case RUNMODE_PFRING:
72  capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
73  CAP_NET_ADMIN, CAP_NET_RAW, CAP_SYS_NICE,
74  -1);
75  break;
76  case RUNMODE_NFLOG:
77  case RUNMODE_NFQ:
78  capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
79  CAP_NET_ADMIN, /* needed for nflog and nfqueue inline mode */
80  CAP_SYS_NICE,
81  -1);
82  break;
83  }
84 
85  if (capng_change_id(userid, groupid, CAPNG_DROP_SUPP_GRP |
86  CAPNG_CLEAR_BOUNDING) < 0)
87  {
88  SCLogError(SC_ERR_CHANGING_CAPS_FAILED, "capng_change_id for main thread"
89  " failed");
90  exit(EXIT_FAILURE);
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(SC_ERR_UID_FAILED, "invalid user id value: '%s'", user_name);
160  }
161  pw = getpwuid(userid);
162  if (pw == NULL) {
163  SCLogError(SC_ERR_UID_FAILED, "unable to get the user ID, "
164  "check if user exist!!");
165  exit(EXIT_FAILURE);
166  }
167  } else {
168  pw = getpwnam(user_name);
169  if (pw == NULL) {
170  SCLogError(SC_ERR_UID_FAILED, "unable to get the user ID, "
171  "check if user exist!!");
172  exit(EXIT_FAILURE);
173  }
174  userid = pw->pw_uid;
175  }
176 
177  /* Get the group ID */
178  if (group_name != NULL) {
179  struct group *gp;
180 
181  if (isdigit((unsigned char)group_name[0]) != 0) {
182  if (ByteExtractStringUint32(&groupid, 10, 0, (const char *)group_name) < 0) {
183  FatalError(SC_ERR_GID_FAILED, "invalid group id: '%s'", group_name);
184  }
185  } else {
186  gp = getgrnam(group_name);
187  if (gp == NULL) {
188  SCLogError(SC_ERR_GID_FAILED, "unable to get the group"
189  " ID, check if group exist!!");
190  exit(EXIT_FAILURE);
191  }
192  groupid = gp->gr_gid;
193  }
194  } else {
195  groupid = pw->pw_gid;
196  }
197 
198  /* close the group database */
199  endgrent();
200  /* close the user database */
201  endpwent();
202 
203  *uid = userid;
204  *gid = groupid;
205 
206  return 0;
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 upon success it return 0
216  */
217 int SCGetGroupID(const char *group_name, uint32_t *gid)
218 {
219  uint32_t grpid = 0;
220  struct group *gp;
221 
222  /* Get the group ID */
223  if (isdigit((unsigned char)group_name[0]) != 0) {
224  if (ByteExtractStringUint32(&grpid, 10, 0, (const char *)group_name) < 0) {
225  FatalError(SC_ERR_GID_FAILED, "invalid group id: '%s'", group_name);
226  }
227  } else {
228  gp = getgrnam(group_name);
229  if (gp == NULL) {
230  SCLogError(SC_ERR_GID_FAILED, "unable to get the group ID,"
231  " check if group exist!!");
232  exit(EXIT_FAILURE);
233  }
234  grpid = gp->gr_gid;
235  }
236 
237  /* close the group database */
238  endgrent();
239 
240  *gid = grpid;
241 
242  return 0;
243 }
244 
245 #ifdef __OpenBSD__
246 int SCPledge(void)
247 {
248  int ret = pledge("stdio rpath wpath cpath fattr unix dns bpf", NULL);
249 
250  if (ret != 0) {
251  SCLogError(SC_ERR_PLEDGE_FAILED, "unable to pledge,"
252  " check permissions!! ret=%i errno=%i", ret, errno);
253  exit(EXIT_FAILURE);
254  }
255 
256  return 0;
257 }
258 #endif /* __OpenBSD__ */
259 #endif /* OS_WIN32 */
util-byte.h
ThreadVars_::name
char name[16]
Definition: threadvars.h:65
SC_ERR_GID_FAILED
@ SC_ERR_GID_FAILED
Definition: util-error.h:188
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
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:100
util-privs.h
SCDropCaps
#define SCDropCaps(...)
Definition: util-privs.h:37
SC_CAP_NET_BROADCAST
#define SC_CAP_NET_BROADCAST
Definition: util-privs.h:34
SC_ERR_CHANGING_CAPS_FAILED
@ SC_ERR_CHANGING_CAPS_FAILED
Definition: util-error.h:189
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
SC_ERR_UID_FAILED
@ SC_ERR_UID_FAILED
Definition: util-error.h:187
util-debug.h
util-cpu.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
SC_ERR_PLEDGE_FAILED
@ SC_ERR_PLEDGE_FAILED
Definition: util-error.h:352
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:217
FALSE
#define FALSE
Definition: suricata-common.h:34
SC_CAP_SYS_ADMIN
#define SC_CAP_SYS_ADMIN
Definition: util-privs.h:28
ByteExtractStringUint32
int ByteExtractStringUint32(uint32_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:239
SCDropMainThreadCaps
#define SCDropMainThreadCaps(...)
Definition: util-privs.h:38
runmodes.h
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:217
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:200
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:257
FatalError
#define FatalError(x,...)
Definition: util-debug.h:532
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:29
threadvars.h
RUNMODE_NFQ
@ RUNMODE_NFQ
Definition: runmodes.h:32
suricata.h
sc_set_caps
int sc_set_caps
Definition: suricata.c:217
RUNMODE_AFP_DEV
@ RUNMODE_AFP_DEV
Definition: runmodes.h:37
SC_CAP_NET_RAW
#define SC_CAP_NET_RAW
Definition: util-privs.h:32