4cd1ae4adbed22651ac3a0ed15a709918be272a3
[obnox/wireshark/wip.git] / wsutil / privileges.c
1 /* privileges.c
2  * Routines for handling privileges, e.g. set-UID and set-GID on UNIX.
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 2006 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREGUID)
30 #define _GNU_SOURCE /* Otherwise [sg]etres[gu]id won't be defined on Linux */
31 #endif
32
33 #include <glib.h>
34
35 #include "privileges.h"
36
37 #ifdef _WIN32
38 #include <windows.h>
39 #include <wchar.h>
40 #include <tchar.h>
41
42 /*
43  * Called when the program starts, to save whatever credential information
44  * we'll need later.
45  */
46 void
47 init_process_policies(void)
48 {
49         typedef BOOL (*SetProcessDEPPolicyHandler)(DWORD);
50         SetProcessDEPPolicyHandler PSetProcessDEPPolicy;
51
52 #ifndef PROCESS_DEP_ENABLE
53 #define PROCESS_DEP_ENABLE 1
54 #endif
55
56         if (PSetProcessDEPPolicy = (SetProcessDEPPolicyHandler) GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "SetProcessDEPPolicy")) {
57                 PSetProcessDEPPolicy(PROCESS_DEP_ENABLE);
58         }
59
60         npf_sys_is_running();
61 }
62
63 /*
64  * For now, we say the program wasn't started with special privileges.
65  * There are ways of running programs with credentials other than those
66  * for the session in which it's run, but I don't know whether that'd be
67  * done with Wireshark/TShark or not.
68  */
69 gboolean
70 started_with_special_privs(void)
71 {
72         return FALSE;
73 }
74
75 /*
76  * For now, we say the program isn't running with special privileges.
77  * There are ways of running programs with credentials other than those
78  * for the session in which it's run, but I don't know whether that'd be
79  * done with Wireshark/TShark or not.
80  */
81 gboolean
82 running_with_special_privs(void)
83 {
84         return FALSE;
85 }
86
87 /*
88  * For now, we don't do anything when asked to relinquish special privileges.
89  */
90 void
91 relinquish_special_privs_perm(void)
92 {
93 }
94
95 /*
96  * Get the current username.  String must be g_free()d after use.
97  */
98 gchar *
99 get_cur_username(void) {
100         gchar *username;
101         username = g_strdup("UNKNOWN");
102         return username;
103 }
104
105 /*
106  * Get the current group.  String must be g_free()d after use.
107  */
108 gchar *
109 get_cur_groupname(void) {
110         gchar *groupname;
111         groupname = g_strdup("UNKNOWN");
112         return groupname;
113 }
114
115 /*
116  * If npf.sys is running, return TRUE.
117  */
118 gboolean
119 npf_sys_is_running() {
120         SC_HANDLE h_scm, h_serv;
121         SERVICE_STATUS ss;
122
123         h_scm = OpenSCManager(NULL, NULL, 0);
124         if (!h_scm)
125                 return FALSE;
126
127         h_serv = OpenService(h_scm, _T("npf"), SC_MANAGER_CONNECT|SERVICE_QUERY_STATUS);
128         if (!h_serv)
129                 return FALSE;
130
131         if (QueryServiceStatus(h_serv, &ss)) {
132                 if (ss.dwCurrentState & SERVICE_RUNNING)
133                         return TRUE;
134         }
135         return FALSE;
136 }
137
138
139 #else /* _WIN32 */
140
141 #ifdef HAVE_SYS_TYPES_H
142 # include <sys/types.h>
143 #endif
144
145 #ifdef HAVE_UNISTD_H
146 #include <unistd.h>
147 #endif
148
149 #ifdef HAVE_PWD_H
150 #include <pwd.h>
151 #endif
152
153 #ifdef HAVE_GRP_H
154 #include <grp.h>
155 #endif
156
157 #include <glib.h>
158 #include <string.h>
159 #include <errno.h>
160
161 static uid_t ruid, euid;
162 static gid_t rgid, egid;
163 static gboolean init_process_polices_called = FALSE;
164
165 /*
166  * Called when the program starts, to save whatever credential information
167  * we'll need later.
168  * That'd be the real and effective UID and GID on UNIX.
169  */
170 void
171 init_process_polices(void)
172 {
173         ruid = getuid();
174         euid = geteuid();
175         rgid = getgid();
176         egid = getegid();
177
178         init_process_polices_called = TRUE;
179 }
180
181 /*
182  * "Started with special privileges" means "started out set-UID or set-GID",
183  * or run as the root user or group.
184  */
185 gboolean
186 started_with_special_privs(void)
187 {
188         g_assert(init_process_polices_called);
189 #ifdef HAVE_ISSETUGID
190         return issetugid();
191 #else
192         return (ruid != euid || rgid != egid || ruid == 0 || rgid == 0);
193 #endif
194 }
195
196 /*
197  * Return TRUE if the real, effective, or saved (if we can check it) user
198  * ID or group are 0.
199  */
200 gboolean
201 running_with_special_privs(void)
202 {
203 #ifdef HAVE_SETRESUID
204         uid_t ru, eu, su;
205 #endif
206 #ifdef HAVE_SETRESGID
207         gid_t rg, eg, sg;
208 #endif
209
210 #ifdef HAVE_SETRESUID
211         getresuid(&ru, &eu, &su);
212         if (ru == 0 || eu == 0 || su == 0)
213                 return TRUE;
214 #else
215         if (getuid() == 0 || geteuid() == 0)
216                 return TRUE;
217 #endif
218 #ifdef HAVE_SETRESGID
219         getresgid(&rg, &eg, &sg);
220         if (rg == 0 || eg == 0 || sg == 0)
221                 return TRUE;
222 #else
223         if (getgid() == 0 || getegid() == 0)
224                 return TRUE;
225 #endif
226         return FALSE;
227 }
228
229 /*
230  * Permanently relinquish  set-UID and set-GID privileges.
231  * Ignore errors for now - if we have the privileges, we should
232  * be able to relinquish them.
233  */
234
235 void
236 relinquish_special_privs_perm(void)
237 {
238         /*
239          * If we were started with special privileges, set the
240          * real and effective group and user IDs to the original
241          * values of the real and effective group and user IDs.
242          * If we're not, don't bother - doing so seems to mung
243          * our group set, at least in OS X 10.5.
244          *
245          * (Set the effective UID last - that takes away our
246          * rights to set anything else.)
247          */
248         if (started_with_special_privs()) {
249 #ifdef HAVE_SETRESGID
250                 setresgid(rgid, rgid, rgid);
251 #else
252                 setgid(rgid);
253                 setegid(rgid);
254 #endif
255
256 #ifdef HAVE_SETRESUID
257                 setresuid(ruid, ruid, ruid);
258 #else
259                 setuid(ruid);
260                 seteuid(ruid);
261 #endif
262         }
263 }
264
265 /*
266  * Get the current username.  String must be g_free()d after use.
267  */
268 gchar *
269 get_cur_username(void) {
270         gchar *username;
271         struct passwd *pw = getpwuid(getuid());
272
273         if (pw) {
274                 username = g_strdup(pw->pw_name);
275         } else {
276                 username = g_strdup("UNKNOWN");
277         }
278         endpwent();
279         return username;
280 }
281
282 /*
283  * Get the current group.  String must be g_free()d after use.
284  */
285 gchar *
286 get_cur_groupname(void) {
287         gchar *groupname;
288         struct group *gr = getgrgid(getgid());
289
290         if (gr) {
291                 groupname = g_strdup(gr->gr_name);
292         } else {
293                 groupname = g_strdup("UNKNOWN");
294         }
295         endgrent();
296         return groupname;
297 }
298
299 #endif /* _WIN32 */
300
301 /*
302  * Editor modelines
303  *
304  * Local Variables:
305  * c-basic-offset: 8
306  * tab-width: 8
307  * indent-tabs-mode: tabs
308  * End:
309  *
310  * ex: set shiftwidth=8 tabstop=8 noexpandtab
311  * :indentSize=8:tabSize=8:noTabs=false:
312  */