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