Windows: Remove cruft for unsupported versons
[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  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 2006 Gerald Combs
7  *
8  * SPDX-License-Identifier: GPL-2.0-or-later
9  */
10
11 #include "config.h"
12
13 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREGUID)
14 #define _GNU_SOURCE /* Otherwise [sg]etres[gu]id won't be defined on Linux */
15 #endif
16
17 #include <glib.h>
18
19 #include "privileges.h"
20
21 #ifdef _WIN32
22 #include <windows.h>
23 #include <wchar.h>
24 #include <tchar.h>
25
26 /*
27  * Called when the program starts, to save whatever credential information
28  * we'll need later, and to do whatever other specialized platform-dependent
29  * initialization we want.
30  */
31 void
32 init_process_policies(void)
33 {
34         /*
35          * If we have SetProcessDEPPolicy(), turn "data execution
36          * prevention" on - i.e., if the MMU lets you set execute
37          * permission on a per-page basis, turn execute permission
38          * off on most data pages.  SetProcessDEPPolicy() fails on
39          * 64-bit Windows (it's *always* on there), but if it fails,
40          * we don't care (we did our best), so we don't check for
41          * errors.
42          *
43          */
44         SetProcessDEPPolicy(PROCESS_DEP_ENABLE);
45 }
46
47 /*
48  * For now, we say the program wasn't started with special privileges.
49  * There are ways of running programs with credentials other than those
50  * for the session in which it's run, but I don't know whether that'd be
51  * done with Wireshark/TShark or not.
52  */
53 gboolean
54 started_with_special_privs(void)
55 {
56         return FALSE;
57 }
58
59 /*
60  * For now, we say the program isn't running with special privileges.
61  * There are ways of running programs with credentials other than those
62  * for the session in which it's run, but I don't know whether that'd be
63  * done with Wireshark/TShark or not.
64  */
65 gboolean
66 running_with_special_privs(void)
67 {
68         return FALSE;
69 }
70
71 /*
72  * For now, we don't do anything when asked to relinquish special privileges.
73  */
74 void
75 relinquish_special_privs_perm(void)
76 {
77 }
78
79 /*
80  * Get the current username.  String must be g_free()d after use.
81  */
82 gchar *
83 get_cur_username(void) {
84         gchar *username;
85         username = g_strdup("UNKNOWN");
86         return username;
87 }
88
89 /*
90  * Get the current group.  String must be g_free()d after use.
91  */
92 gchar *
93 get_cur_groupname(void) {
94         gchar *groupname;
95         groupname = g_strdup("UNKNOWN");
96         return groupname;
97 }
98
99 #else /* _WIN32 */
100
101 #ifdef HAVE_SYS_TYPES_H
102 # include <sys/types.h>
103 #endif
104
105 #ifdef HAVE_UNISTD_H
106 #include <unistd.h>
107 #endif
108
109 #ifdef HAVE_PWD_H
110 #include <pwd.h>
111 #endif
112
113 #ifdef HAVE_GRP_H
114 #include <grp.h>
115 #endif
116
117 #include <string.h>
118 #include <errno.h>
119
120 static uid_t ruid, euid;
121 static gid_t rgid, egid;
122 static gboolean init_process_policies_called = FALSE;
123
124 /*
125  * Called when the program starts, to save whatever credential information
126  * we'll need later, and to do whatever other specialized platform-dependent
127  * initialization we want.
128  *
129  * The credential information we'll need later on UNIX is the real and
130  * effective UID and GID.
131  *
132  * XXX - do any UN*Xes have opt-in "no execute on data pages by default"
133  * permission?  This would be the place to request it.
134  */
135 void
136 init_process_policies(void)
137 {
138         ruid = getuid();
139         euid = geteuid();
140         rgid = getgid();
141         egid = getegid();
142
143         init_process_policies_called = TRUE;
144 }
145
146 /*
147  * "Started with special privileges" means "started out set-UID or set-GID",
148  * or run as the root user or group.
149  */
150 gboolean
151 started_with_special_privs(void)
152 {
153         g_assert(init_process_policies_called);
154 #ifdef HAVE_ISSETUGID
155         return issetugid();
156 #else
157         return (ruid != euid || rgid != egid || ruid == 0 || rgid == 0);
158 #endif
159 }
160
161 /*
162  * Return TRUE if the real, effective, or saved (if we can check it) user
163  * ID or group are 0.
164  */
165 gboolean
166 running_with_special_privs(void)
167 {
168 #ifdef HAVE_SETRESUID
169         uid_t ru, eu, su;
170 #endif
171 #ifdef HAVE_SETRESGID
172         gid_t rg, eg, sg;
173 #endif
174
175 #ifdef HAVE_SETRESUID
176         getresuid(&ru, &eu, &su);
177         if (ru == 0 || eu == 0 || su == 0)
178                 return TRUE;
179 #else
180         if (getuid() == 0 || geteuid() == 0)
181                 return TRUE;
182 #endif
183 #ifdef HAVE_SETRESGID
184         getresgid(&rg, &eg, &sg);
185         if (rg == 0 || eg == 0 || sg == 0)
186                 return TRUE;
187 #else
188         if (getgid() == 0 || getegid() == 0)
189                 return TRUE;
190 #endif
191         return FALSE;
192 }
193
194 /*
195  * Permanently relinquish  set-UID and set-GID privileges.
196  * If error, abort since we probably shouldn't continue
197  * with elevated privileges.
198  * Note that if this error occurs when dumpcap is called from
199  * wireshark or tshark, the message seen will be
200  * "Child dumpcap process died:". This is obscure but we'll
201  *   consider it acceptable since it should be highly unlikely
202  *   that this error will occur.
203  */
204
205 static void
206 setxid_fail(const gchar *str)
207 {
208         g_error("Attempt to relinguish privileges failed [%s()] - aborting: %s\n",
209                 str, g_strerror(errno));
210 }
211
212 void
213 relinquish_special_privs_perm(void)
214 {
215         /*
216          * If we were started with special privileges, set the
217          * real and effective group and user IDs to the original
218          * values of the real and effective group and user IDs.
219          * If we're not, don't bother - doing so seems to mung
220          * our group set, at least in Mac OS X 10.5.
221          *
222          * (Set the effective UID last - that takes away our
223          * rights to set anything else.)
224          */
225         if (started_with_special_privs()) {
226 #ifdef HAVE_SETRESGID
227                 if (setresgid(rgid, rgid, rgid) == -1) {setxid_fail("setresgid");}
228 #else
229                 if (setgid(rgid)                == -1) {setxid_fail("setgid"); }
230                 if (setegid(rgid)               == -1) {setxid_fail("setegid");}
231 #endif
232
233 #ifdef HAVE_SETRESUID
234                 if (setresuid(ruid, ruid, ruid) == -1) {setxid_fail("setresuid");}
235 #else
236                 if (setuid(ruid)                == -1) {setxid_fail("setuid"); }
237                 if (seteuid(ruid)               == -1) {setxid_fail("seteuid");}
238 #endif
239         }
240 }
241
242 /*
243  * Get the current username.  String must be g_free()d after use.
244  */
245 gchar *
246 get_cur_username(void) {
247         gchar *username;
248         struct passwd *pw = getpwuid(getuid());
249
250         if (pw) {
251                 username = g_strdup(pw->pw_name);
252         } else {
253                 username = g_strdup("UNKNOWN");
254         }
255         endpwent();
256         return username;
257 }
258
259 /*
260  * Get the current group.  String must be g_free()d after use.
261  */
262 gchar *
263 get_cur_groupname(void) {
264         gchar *groupname;
265         struct group *gr = getgrgid(getgid());
266
267         if (gr) {
268                 groupname = g_strdup(gr->gr_name);
269         } else {
270                 groupname = g_strdup("UNKNOWN");
271         }
272         endgrent();
273         return groupname;
274 }
275
276 #endif /* _WIN32 */
277
278 /*
279  * Editor modelines
280  *
281  * Local Variables:
282  * c-basic-offset: 8
283  * tab-width: 8
284  * indent-tabs-mode: t
285  * End:
286  *
287  * ex: set shiftwidth=8 tabstop=8 noexpandtab:
288  * :indentSize=8:tabSize=8:noTabs=false:
289  */