1/*	SCCS Id: @(#)unixres.c	3.4	2001/07/08	*/
2/* Copyright (c) Slash'EM development team, 2001. */
3/* NetHack may be freely redistributed.  See license for details. */
4
5/* [ALI] This module defines nh_xxx functions to replace getuid etc which
6 * will hide privileges from the caller if so desired.
7 *
8 * Currently supported UNIX variants:
9 *	Linux version 2.1.44 and above
10 *	FreeBSD (versions unknown)
11 *
12 * Note: SunOS and Solaris have no mechanism for retrieving the saved id,
13 * so temporarily dropping privileges on these systems is sufficient to
14 * hide them.
15 */
16
17#include "config.h"
18
19#ifdef GETRES_SUPPORT
20
21# if defined(LINUX)
22
23/* requires dynamic linking with libc */
24#include <dlfcn.h>
25
26static int
27real_getresuid(ruid, euid, suid)
28uid_t *ruid, *euid, *suid;
29{
30    int (*f)(uid_t *, uid_t *, uid_t *); /* getresuid signature */
31
32    f = dlsym(RTLD_NEXT, "getresuid");
33    if (!f) return -1;
34
35    return f(ruid, euid, suid);
36}
37
38static int
39real_getresgid(rgid, egid, sgid)
40gid_t *rgid, *egid, *sgid;
41{
42    int (*f)(gid_t *, gid_t *, gid_t *); /* getresgid signature */
43
44    f = dlsym(RTLD_NEXT, "getresgid");
45    if (!f) return -1;
46
47    return f(rgid, egid, sgid);
48}
49
50# else
51#  if defined(BSD) || defined(SVR4)
52
53#   ifdef SYS_getresuid
54
55static int
56real_getresuid(ruid, euid, suid)
57uid_t *ruid, *euid, *suid;
58{
59    return syscall(SYS_getresuid, ruid, euid, suid);
60}
61
62#   else	/* SYS_getresuid */
63
64#ifdef SVR4
65#include <sys/stat.h>
66#endif /* SVR4 */
67
68static int
69real_getresuid(ruid, euid, suid)
70uid_t *ruid, *euid, *suid;
71{
72    int retval;
73    int pfd[2];
74    struct stat st;
75    if (pipe(pfd))
76	return -1;
77    retval = fstat(pfd[0], &st);
78    close(pfd[0]);
79    close(pfd[1]);
80    if (!retval) {
81	*euid = st.st_uid;
82	*ruid = syscall(SYS_getuid);
83	*suid = *ruid;			/* Not supported under SVR4 */
84    }
85    return retval;
86}
87
88#   endif	/* SYS_getresuid */
89
90#   ifdef SYS_getresgid
91
92static int
93real_getresgid(rgid, egid, sgid)
94gid_t *rgid, *egid, *sgid;
95{
96    return syscall(SYS_getresgid, rgid, egid, sgid);
97}
98
99#   else	/* SYS_getresgid */
100
101static int
102real_getresgid(rgid, egid, sgid)
103gid_t *rgid, *egid, *sgid;
104{
105    int retval;
106    int pfd[2];
107    struct stat st;
108    if (pipe(pfd))
109	return -1;
110    retval = fstat(pfd[0], &st);
111    close(pfd[0]);
112    close(pfd[1]);
113    if (!retval) {
114	*egid = st.st_gid;
115	*rgid = syscall(SYS_getgid);
116	*sgid = *rgid;			/* Not supported under SVR4 */
117    }
118    return retval;
119}
120
121#   endif	/* SYS_getresgid */
122#  endif	/* BSD || SVR4 */
123# endif		/* LINUX */
124
125static unsigned int hiding_privileges = 0;
126
127/*
128 * Note: returns the value _after_ action.
129 */
130
131int
132hide_privileges(flag)
133boolean flag;
134{
135    if (flag)
136	hiding_privileges++;
137    else if (hiding_privileges)
138	hiding_privileges--;
139    return hiding_privileges;
140}
141
142int
143nh_getresuid(ruid, euid, suid)
144uid_t *ruid, *euid, *suid;
145{
146    int retval = real_getresuid(ruid, euid, suid);
147    if (!retval && hiding_privileges)
148	*euid = *suid = *ruid;
149    return retval;
150}
151
152uid_t
153nh_getuid()
154{
155    uid_t ruid, euid, suid;
156    (void) real_getresuid(&ruid, &euid, &suid);
157    return ruid;
158}
159
160uid_t
161nh_geteuid()
162{
163    uid_t ruid, euid, suid;
164    (void) real_getresuid(&ruid, &euid, &suid);
165    if (hiding_privileges)
166	euid = ruid;
167    return euid;
168}
169
170int
171nh_getresgid(rgid, egid, sgid)
172gid_t *rgid, *egid, *sgid;
173{
174    int retval = real_getresgid(rgid, egid, sgid);
175    if (!retval && hiding_privileges)
176	*egid = *sgid = *rgid;
177    return retval;
178}
179
180gid_t
181nh_getgid()
182{
183    gid_t rgid, egid, sgid;
184    (void) real_getresgid(&rgid, &egid, &sgid);
185    return rgid;
186}
187
188gid_t
189nh_getegid()
190{
191    gid_t rgid, egid, sgid;
192    (void) real_getresgid(&rgid, &egid, &sgid);
193    if (hiding_privileges)
194	egid = rgid;
195    return egid;
196}
197
198#else	/* GETRES_SUPPORT */
199
200# ifdef GNOME_GRAPHICS
201int
202hide_privileges(flag)
203boolean flag;
204{
205    return 0;
206}
207# endif
208
209#endif	/* GETRES_SUPPORT */
210