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 
26 static int
real_getresuid(ruid,euid,suid)27 real_getresuid(ruid, euid, suid)
28 uid_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 
38 static int
real_getresgid(rgid,egid,sgid)39 real_getresgid(rgid, egid, sgid)
40 gid_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 
55 static int
real_getresuid(ruid,euid,suid)56 real_getresuid(ruid, euid, suid)
57 uid_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 
68 static int
real_getresuid(ruid,euid,suid)69 real_getresuid(ruid, euid, suid)
70 uid_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 
92 static int
real_getresgid(rgid,egid,sgid)93 real_getresgid(rgid, egid, sgid)
94 gid_t *rgid, *egid, *sgid;
95 {
96     return syscall(SYS_getresgid, rgid, egid, sgid);
97 }
98 
99 #   else	/* SYS_getresgid */
100 
101 static int
real_getresgid(rgid,egid,sgid)102 real_getresgid(rgid, egid, sgid)
103 gid_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 
125 static unsigned int hiding_privileges = 0;
126 
127 /*
128  * Note: returns the value _after_ action.
129  */
130 
131 int
hide_privileges(flag)132 hide_privileges(flag)
133 boolean flag;
134 {
135     if (flag)
136 	hiding_privileges++;
137     else if (hiding_privileges)
138 	hiding_privileges--;
139     return hiding_privileges;
140 }
141 
142 int
nh_getresuid(ruid,euid,suid)143 nh_getresuid(ruid, euid, suid)
144 uid_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 
152 uid_t
nh_getuid()153 nh_getuid()
154 {
155     uid_t ruid, euid, suid;
156     (void) real_getresuid(&ruid, &euid, &suid);
157     return ruid;
158 }
159 
160 uid_t
nh_geteuid()161 nh_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 
170 int
nh_getresgid(rgid,egid,sgid)171 nh_getresgid(rgid, egid, sgid)
172 gid_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 
180 gid_t
nh_getgid()181 nh_getgid()
182 {
183     gid_t rgid, egid, sgid;
184     (void) real_getresgid(&rgid, &egid, &sgid);
185     return rgid;
186 }
187 
188 gid_t
nh_getegid()189 nh_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
201 int
hide_privileges(flag)202 hide_privileges(flag)
203 boolean flag;
204 {
205     return 0;
206 }
207 # endif
208 
209 #endif	/* GETRES_SUPPORT */
210