Move privileges.c and unicode-utils.c from epan to wsutil (so things like
[metze/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 get_credential_info(void)
48 {
49         npf_sys_is_running();
50 }
51
52 /*
53  * For now, we say the program wasn't started with special privileges.
54  * There are ways of running programs with credentials other than those
55  * for the session in which it's run, but I don't know whether that'd be
56  * done with Wireshark/TShark or not.
57  */
58 gboolean
59 started_with_special_privs(void)
60 {
61         return FALSE;
62 }
63
64 /*
65  * For now, we say the program isn't running with special privileges.
66  * There are ways of running programs with credentials other than those
67  * for the session in which it's run, but I don't know whether that'd be
68  * done with Wireshark/TShark or not.
69  */
70 gboolean
71 running_with_special_privs(void)
72 {
73         return FALSE;
74 }
75
76 /*
77  * For now, we don't do anything when asked to relinquish special privileges.
78  */
79 void
80 relinquish_special_privs_perm(void)
81 {
82 }
83
84 /*
85  * Get the current username.  String must be g_free()d after use.
86  */
87 gchar *
88 get_cur_username(void) {
89         gchar *username;
90         username = g_strdup("UNKNOWN");
91         return username;
92 }
93
94 /*
95  * Get the current group.  String must be g_free()d after use.
96  */
97 gchar *
98 get_cur_groupname(void) {
99         gchar *groupname;
100         groupname = g_strdup("UNKNOWN");
101         return groupname;
102 }
103
104 /*
105  * If npf.sys is running, return TRUE.
106  */
107 gboolean
108 npf_sys_is_running() {
109         SC_HANDLE h_scm, h_serv;
110         SERVICE_STATUS ss;
111
112         h_scm = OpenSCManager(NULL, NULL, 0);
113         if (!h_scm)
114                 return FALSE;
115
116         h_serv = OpenService(h_scm, _T("npf"), SC_MANAGER_CONNECT|SERVICE_QUERY_STATUS);
117         if (!h_serv)
118                 return FALSE;
119
120         if (QueryServiceStatus(h_serv, &ss)) {
121                 if (ss.dwCurrentState & SERVICE_RUNNING)
122                         return TRUE;
123         }
124         return FALSE;
125 }
126
127
128 #else /* _WIN32 */
129
130 #ifdef HAVE_SYS_TYPES_H
131 # include <sys/types.h>
132 #endif
133
134 #ifdef HAVE_UNISTD_H
135 #include <unistd.h>
136 #endif
137
138 #ifdef HAVE_PWD_H
139 #include <pwd.h>
140 #endif
141
142 #ifdef HAVE_GRP_H
143 #include <grp.h>
144 #endif
145
146 #include <glib.h>
147 #include <string.h>
148 #include <errno.h>
149
150 static uid_t ruid, euid;
151 static gid_t rgid, egid;
152 static gboolean get_credential_info_called = FALSE;
153
154 /*
155  * Called when the program starts, to save whatever credential information
156  * we'll need later.
157  * That'd be the real and effective UID and GID on UNIX.
158  */
159 void
160 get_credential_info(void)
161 {
162         ruid = getuid();
163         euid = geteuid();
164         rgid = getgid();
165         egid = getegid();
166
167         get_credential_info_called = TRUE;
168 }
169
170 /*
171  * "Started with special privileges" means "started out set-UID or set-GID",
172  * or run as the root user or group.
173  */
174 gboolean
175 started_with_special_privs(void)
176 {
177         g_assert(get_credential_info_called);
178 #ifdef HAVE_ISSETUGID
179         return issetugid();
180 #else
181         return (ruid != euid || rgid != egid || ruid == 0 || rgid == 0);
182 #endif
183 }
184
185 /*
186  * Return TRUE if the real, effective, or saved (if we can check it) user
187  * ID or group are 0.
188  */
189 gboolean
190 running_with_special_privs(void)
191 {
192 #ifdef HAVE_SETRESUID
193         uid_t ru, eu, su;
194 #endif
195 #ifdef HAVE_SETRESGID
196         gid_t rg, eg, sg;
197 #endif
198
199 #ifdef HAVE_SETRESUID
200         getresuid(&ru, &eu, &su);
201         if (ru == 0 || eu == 0 || su == 0)
202                 return TRUE;
203 #else
204         if (getuid() == 0 || geteuid() == 0)
205                 return TRUE;
206 #endif
207 #ifdef HAVE_SETRESGID
208         getresgid(&rg, &eg, &sg);
209         if (rg == 0 || eg == 0 || sg == 0)
210                 return TRUE;
211 #else
212         if (getgid() == 0 || getegid() == 0)
213                 return TRUE;
214 #endif
215         return FALSE;
216 }
217
218 /*
219  * Permanently relinquish  set-UID and set-GID privileges.
220  * Ignore errors for now - if we have the privileges, we should
221  * be able to relinquish them.
222  */
223
224 void
225 relinquish_special_privs_perm(void)
226 {
227         /*
228          * If we were started with special privileges, set the
229          * real and effective group and user IDs to the original
230          * values of the real and effective group and user IDs.
231          * If we're not, don't bother - doing so seems to mung
232          * our group set, at least in OS X 10.5.
233          *
234          * (Set the effective UID last - that takes away our
235          * rights to set anything else.)
236          */
237         if (started_with_special_privs()) {
238 #ifdef HAVE_SETRESGID
239                 setresgid(rgid, rgid, rgid);
240 #else
241                 setgid(rgid);
242                 setegid(rgid);
243 #endif
244
245 #ifdef HAVE_SETRESUID
246                 setresuid(ruid, ruid, ruid);
247 #else
248                 setuid(ruid);
249                 seteuid(ruid);
250 #endif
251         }
252 }
253
254 /*
255  * Get the current username.  String must be g_free()d after use.
256  */
257 gchar *
258 get_cur_username(void) {
259         gchar *username;
260         struct passwd *pw = getpwuid(getuid());
261
262         if (pw) {
263                 username = g_strdup(pw->pw_name);
264         } else {
265                 username = g_strdup("UNKNOWN");
266         }
267         endpwent();
268         return username;
269 }
270
271 /*
272  * Get the current group.  String must be g_free()d after use.
273  */
274 gchar *
275 get_cur_groupname(void) {
276         gchar *groupname;
277         struct group *gr = getgrgid(getgid());
278
279         if (gr) {
280                 groupname = g_strdup(gr->gr_name);
281         } else {
282                 groupname = g_strdup("UNKNOWN");
283         }
284         endgrent();
285         return groupname;
286 }
287
288 #endif /* _WIN32 */
289
290 /*
291  * Editor modelines
292  *
293  * Local Variables:
294  * c-basic-offset: 8
295  * tab-width: 8
296  * indent-tabs-mode: tabs
297  * End:
298  *
299  * ex: set shiftwidth=8 tabstop=8 noexpandtab
300  * :indentSize=8:tabSize=8:noTabs=false:
301  */