2 * Routines for handling privileges, e.g. set-UID and set-GID on UNIX.
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 2006 Gerald Combs
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREGUID)
26 #define _GNU_SOURCE /* Otherwise [sg]etres[gu]id won't be defined on Linux */
31 #include "privileges.h"
39 * Called when the program starts, to save whatever credential information
40 * we'll need later, and to do whatever other specialized platform-dependent
41 * initialization we want.
44 init_process_policies(void)
46 HMODULE kernel32Handle;
47 typedef BOOL (WINAPI *SetProcessDEPPolicyHandler)(DWORD);
48 SetProcessDEPPolicyHandler PSetProcessDEPPolicy;
50 #ifndef PROCESS_DEP_ENABLE
51 #define PROCESS_DEP_ENABLE 1
55 * If we have SetProcessDEPPolicy(), turn "data execution
56 * prevention" on - i.e., if the MMU lets you set execute
57 * permission on a per-page basis, turn execute permission
58 * off on most data pages. SetProcessDEPPolicy() fails on
59 * 64-bit Windows (it's *always* on there), but if it fails,
60 * we don't care (we did our best), so we don't check for
63 * XXX - if the GetModuleHandle() call fails, should we report
64 * an error? That "shouldn't happen" - it's the equivalent
65 * of libc.{so,sl,a} or libSystem.dylib being missing on UN*X.
67 kernel32Handle = GetModuleHandle(_T("kernel32.dll"));
68 if (kernel32Handle != NULL) {
69 PSetProcessDEPPolicy = (SetProcessDEPPolicyHandler) GetProcAddress(kernel32Handle, "SetProcessDEPPolicy");
70 if (PSetProcessDEPPolicy) {
71 PSetProcessDEPPolicy(PROCESS_DEP_ENABLE);
77 * For now, we say the program wasn't started with special privileges.
78 * There are ways of running programs with credentials other than those
79 * for the session in which it's run, but I don't know whether that'd be
80 * done with Wireshark/TShark or not.
83 started_with_special_privs(void)
89 * For now, we say the program isn't running with special privileges.
90 * There are ways of running programs with credentials other than those
91 * for the session in which it's run, but I don't know whether that'd be
92 * done with Wireshark/TShark or not.
95 running_with_special_privs(void)
101 * For now, we don't do anything when asked to relinquish special privileges.
104 relinquish_special_privs_perm(void)
109 * Get the current username. String must be g_free()d after use.
112 get_cur_username(void) {
114 username = g_strdup("UNKNOWN");
119 * Get the current group. String must be g_free()d after use.
122 get_cur_groupname(void) {
124 groupname = g_strdup("UNKNOWN");
130 #ifdef HAVE_SYS_TYPES_H
131 # include <sys/types.h>
149 static uid_t ruid, euid;
150 static gid_t rgid, egid;
151 static gboolean init_process_policies_called = FALSE;
154 * Called when the program starts, to save whatever credential information
155 * we'll need later, and to do whatever other specialized platform-dependent
156 * initialization we want.
158 * The credential information we'll need later on UNIX is the real and
159 * effective UID and GID.
161 * XXX - do any UN*Xes have opt-in "no execute on data pages by default"
162 * permission? This would be the place to request it.
165 init_process_policies(void)
172 init_process_policies_called = TRUE;
176 * "Started with special privileges" means "started out set-UID or set-GID",
177 * or run as the root user or group.
180 started_with_special_privs(void)
182 g_assert(init_process_policies_called);
183 #ifdef HAVE_ISSETUGID
186 return (ruid != euid || rgid != egid || ruid == 0 || rgid == 0);
191 * Return TRUE if the real, effective, or saved (if we can check it) user
195 running_with_special_privs(void)
197 #ifdef HAVE_SETRESUID
200 #ifdef HAVE_SETRESGID
204 #ifdef HAVE_SETRESUID
205 getresuid(&ru, &eu, &su);
206 if (ru == 0 || eu == 0 || su == 0)
209 if (getuid() == 0 || geteuid() == 0)
212 #ifdef HAVE_SETRESGID
213 getresgid(&rg, &eg, &sg);
214 if (rg == 0 || eg == 0 || sg == 0)
217 if (getgid() == 0 || getegid() == 0)
224 * Permanently relinquish set-UID and set-GID privileges.
225 * If error, abort since we probably shouldn't continue
226 * with elevated privileges.
227 * Note that if this error occurs when dumpcap is called from
228 * wireshark or tshark, the message seen will be
229 * "Child dumpcap process died:". This is obscure but we'll
230 * consider it acceptable since it should be highly unlikely
231 * that this error will occur.
235 setxid_fail(const gchar *str)
237 g_error("Attempt to relinguish privileges failed [%s()] - aborting: %s\n",
238 str, g_strerror(errno));
242 relinquish_special_privs_perm(void)
245 * If we were started with special privileges, set the
246 * real and effective group and user IDs to the original
247 * values of the real and effective group and user IDs.
248 * If we're not, don't bother - doing so seems to mung
249 * our group set, at least in OS X 10.5.
251 * (Set the effective UID last - that takes away our
252 * rights to set anything else.)
254 if (started_with_special_privs()) {
255 #ifdef HAVE_SETRESGID
256 if (setresgid(rgid, rgid, rgid) == -1) {setxid_fail("setresgid");}
258 if (setgid(rgid) == -1) {setxid_fail("setgid"); }
259 if (setegid(rgid) == -1) {setxid_fail("setegid");}
262 #ifdef HAVE_SETRESUID
263 if (setresuid(ruid, ruid, ruid) == -1) {setxid_fail("setresuid");}
265 if (setuid(ruid) == -1) {setxid_fail("setuid"); }
266 if (seteuid(ruid) == -1) {setxid_fail("seteuid");}
272 * Get the current username. String must be g_free()d after use.
275 get_cur_username(void) {
277 struct passwd *pw = getpwuid(getuid());
280 username = g_strdup(pw->pw_name);
282 username = g_strdup("UNKNOWN");
289 * Get the current group. String must be g_free()d after use.
292 get_cur_groupname(void) {
294 struct group *gr = getgrgid(getgid());
297 groupname = g_strdup(gr->gr_name);
299 groupname = g_strdup("UNKNOWN");
313 * indent-tabs-mode: t
316 * ex: set shiftwidth=8 tabstop=8 noexpandtab:
317 * :indentSize=8:tabSize=8:noTabs=false: