1 |
#include "unixpriv.h" |
2 |
|
3 |
|
4 |
/**************************************************** |
5 |
C-GUL |
6 |
|
7 |
****************************************************/ |
8 |
|
9 |
|
10 |
char * cgul_process_identity_oneline(void) |
11 |
{ |
12 |
int t = 0; |
13 |
int stored_errno = 0; |
14 |
char * line_buf = NULL; |
15 |
struct passwd * p = NULL; |
16 |
struct group * g = NULL; |
17 |
int ngroups = 0; |
18 |
gid_t * list = NULL; |
19 |
|
20 |
uid_t uid = getuid(); |
21 |
uid_t euid = geteuid(); |
22 |
gid_t gid = getgid(); |
23 |
gid_t egid = getegid(); |
24 |
|
25 |
|
26 |
/* Allocate write buffer, must be free'd */ |
27 |
if (!(line_buf = calloc (sizeof (char), 1024 + 1))) |
28 |
return NULL; |
29 |
|
30 |
/* Real User ID */ |
31 |
if((p = getpwuid (uid))){ |
32 |
snprintf (&line_buf[strlen(line_buf)], 1024 - strlen(line_buf), "uid=%d(%s)", uid, p -> pw_name); |
33 |
} else { |
34 |
snprintf (&line_buf[strlen(line_buf)], 1024 - strlen(line_buf), "uid=%d", uid); |
35 |
} |
36 |
|
37 |
/* Effective User ID */ |
38 |
if((p = getpwuid (euid))){ |
39 |
snprintf (&line_buf[strlen(line_buf)], 1024 - strlen(line_buf), ",euid=%d(%s)", euid, p -> pw_name); |
40 |
} else { |
41 |
snprintf (&line_buf[strlen(line_buf)], 1024 - strlen(line_buf), ",euid=%d", euid); |
42 |
} |
43 |
|
44 |
/* Real Group ID */ |
45 |
if((g = getgrgid (gid))){ |
46 |
snprintf (&line_buf[strlen(line_buf)], 1024 - strlen(line_buf), ",gid=%d(%s)", gid, g -> gr_name); |
47 |
} else { |
48 |
snprintf (&line_buf[strlen(line_buf)], 1024 - strlen(line_buf), ",gid=%d", gid); |
49 |
} |
50 |
|
51 |
/* Effective Group ID */ |
52 |
if((g = getgrgid (egid))){ |
53 |
snprintf (&line_buf[strlen(line_buf)], 1024 - strlen(line_buf), ",egid=%d(%s)", egid, g -> gr_name); |
54 |
} else { |
55 |
snprintf (&line_buf[strlen(line_buf)], 1024 - strlen(line_buf), ",egid=%d", egid); |
56 |
} |
57 |
|
58 |
/* Get the number of secondary group IDs for root */ |
59 |
if ((ngroups = getgroups(0, NULL)) < 0) |
60 |
{ |
61 |
stored_errno = errno; |
62 |
free (line_buf); |
63 |
errno = stored_errno; |
64 |
return NULL; |
65 |
} |
66 |
list = (gid_t *) malloc(ngroups * sizeof(gid_t)); |
67 |
|
68 |
/* Get the secondary group IDs for root */ |
69 |
if (getgroups(ngroups, list) < 0) |
70 |
{ |
71 |
stored_errno = errno; |
72 |
free (line_buf); |
73 |
errno = stored_errno; |
74 |
return NULL; |
75 |
} |
76 |
|
77 |
/* Make a oneliner out of all the secondary GIDs */ |
78 |
for (t = 0; t < ngroups; t++) |
79 |
{ |
80 |
/* Secondary Group ID */ |
81 |
if((g = getgrgid (list[t]))){ |
82 |
snprintf (&line_buf[strlen(line_buf)], 1024 - strlen(line_buf), ",sgid=%d(%s)", list[t], g -> gr_name); |
83 |
} else { |
84 |
snprintf (&line_buf[strlen(line_buf)], 1024 - strlen(line_buf), ",sgid=%d", list[t]); |
85 |
} |
86 |
} |
87 |
|
88 |
/* Memory liberation */ |
89 |
if (list) free(list); |
90 |
list=(gid_t *) NULL; |
91 |
|
92 |
return line_buf; |
93 |
} |
94 |
|
95 |
|
96 |
uid_t threadsafe_getuid_from_name (const char * username) |
97 |
{ |
98 |
struct passwd * p = NULL; |
99 |
uid_t uid = -1; |
100 |
int errno_save = 0; |
101 |
#define HAVE_GETPWNAM_R |
102 |
#if defined HAVE_GETPWNAM_R || defined _LIBC |
103 |
char * pwtmpbuf = NULL; |
104 |
struct passwd pwbuf; |
105 |
size_t buflen = 1024; |
106 |
#ifdef _SC_GETPW_R_SIZE_MAX |
107 |
buflen = sysconf (_SC_GETPW_R_SIZE_MAX); |
108 |
if ((buflen == -1) && (errno != 0)) |
109 |
{ |
110 |
buflen = 1024; |
111 |
} |
112 |
#endif |
113 |
|
114 |
/* Allocate the buffer for getpwnam_r() */ |
115 |
pwtmpbuf = (char *) calloc (1, buflen); |
116 |
|
117 |
/* Get Passwd Info for Username */ |
118 |
while (getpwnam_r (username, &pwbuf, pwtmpbuf, buflen, &p) != 0) |
119 |
{ |
120 |
/* If the errno is anything different then ERANGE, something is wrong or the ID is not available */ |
121 |
if (errno != ERANGE) |
122 |
{ |
123 |
errno_save = errno; |
124 |
p = NULL; |
125 |
break; |
126 |
} |
127 |
|
128 |
/* ERANGE is left over, which means that there is insufficient buffer space. Increasing buffer side and try again */ |
129 |
buflen *= 2; |
130 |
free (pwtmpbuf); |
131 |
|
132 |
/* Allocate the buffer for getpwnam_r() */ |
133 |
if (!(pwtmpbuf = (char *) calloc (1, buflen))) |
134 |
{ |
135 |
/* System ran out of memory */ |
136 |
if (errno == ENOMEM) |
137 |
{ |
138 |
/* No memory available, bail out */ |
139 |
p = NULL; |
140 |
errno_save = errno; |
141 |
break; |
142 |
} |
143 |
} |
144 |
} |
145 |
#else |
146 |
p = getpwnam (username); |
147 |
#endif |
148 |
|
149 |
/* If there is an entry found, fetch the UID info */ |
150 |
if (p) |
151 |
{ |
152 |
uid = p -> pw_uid; |
153 |
} |
154 |
|
155 |
/* Remove the buffer for the getpwnam_r() */ |
156 |
free (pwtmpbuf); |
157 |
errno = errno_save; |
158 |
return uid; |
159 |
} |
160 |
|
161 |
|
162 |
gid_t threadsafe_getgid_from_name (const char * groupname) |
163 |
{ |
164 |
struct group * p = NULL; |
165 |
gid_t gid = -1; |
166 |
int errno_save = 0; |
167 |
#define HAVE_GETPWNAM_R |
168 |
#if defined HAVE_GETPWNAM_R || defined _LIBC |
169 |
char * grtmpbuf = NULL; |
170 |
struct group grbuf; |
171 |
size_t buflen = 1024; |
172 |
#ifdef _SC_GETGR_R_SIZE_MAX |
173 |
buflen = sysconf (_SC_GETGR_R_SIZE_MAX); |
174 |
if ((buflen == -1) && (errno != 0)) |
175 |
{ |
176 |
buflen = 1024; |
177 |
} |
178 |
#endif |
179 |
|
180 |
/* Allocate the buffer for getpwnam_r() */ |
181 |
grtmpbuf = (char *) calloc (1, buflen); |
182 |
|
183 |
/* Get Passwd Info for Username */ |
184 |
while (getgrnam_r (groupname, &grbuf, grtmpbuf, buflen, &p) != 0) |
185 |
{ |
186 |
/* If the errno is anything different then ERANGE, something is wrong or the ID is not available */ |
187 |
if (errno != ERANGE) |
188 |
{ |
189 |
errno_save = errno; |
190 |
p = NULL; |
191 |
break; |
192 |
} |
193 |
|
194 |
/* ERANGE is left over, which means that there is insufficient buffer space. Increasing buffer side and try again */ |
195 |
buflen *= 2; |
196 |
free (grtmpbuf); |
197 |
|
198 |
/* Allocate the buffer for getpwnam_r() */ |
199 |
if (!(grtmpbuf = (char *) calloc (1, buflen))) |
200 |
{ |
201 |
/* System ran out of memory */ |
202 |
if (errno == ENOMEM) |
203 |
{ |
204 |
/* No memory available, bail out */ |
205 |
p = NULL; |
206 |
errno_save = errno; |
207 |
break; |
208 |
} |
209 |
} |
210 |
} |
211 |
#else |
212 |
/* If the platform doesn't have a getgrnam_r() function */ |
213 |
p = getgrnam (username); |
214 |
#endif |
215 |
|
216 |
/* If there is an entry found, fetch the GID info */ |
217 |
if (p) |
218 |
{ |
219 |
gid = p -> gr_gid; |
220 |
} |
221 |
|
222 |
/* Remove the buffer for the getgrnam_r() */ |
223 |
free (grtmpbuf); |
224 |
errno = errno_save; |
225 |
return gid; |
226 |
} |
227 |
|
228 |
|
229 |
|
230 |
|
231 |
|
232 |
/* When the proxy is located on an NFS mount and on the server side the root squash |
233 |
* option has been enabled, the effective uid is mapped to user 'nobody' which should |
234 |
* not be able to read the proxy file. To work around this problem, the effective |
235 |
* uid of the process is changed to that of the calling user and once glexec is done, |
236 |
* the saved uid is used to restore the identity of the process, |
237 |
*/ |
238 |
#if 0 |
239 |
Example: |
240 |
uid_t stored_real_uid = -1; |
241 |
uid_t stored_eff_uid = -1; |
242 |
|
243 |
/* Downgrade effective privileges to cope with NFS mounted file systems with root squashing */ |
244 |
downgradeEffectiveToRealUid (&stored_real_uid, &stored_eff_uid); |
245 |
|
246 |
/* Read PEM string */ |
247 |
fopen(proxyfile, "r"); |
248 |
|
249 |
/* Restore privileges to previous state */ |
250 |
upgradeEffectiveToRealUid (stored_real_uid, stored_eff_uid); |
251 |
#endif |
252 |
int downgradeEffectiveToRealUid (uid_t * real_uid, uid_t * saved_uid) |
253 |
{ |
254 |
*real_uid = getuid(); |
255 |
if (*real_uid != 0) |
256 |
{ |
257 |
/* Save it */ |
258 |
*saved_uid = geteuid(); |
259 |
if (seteuid(*real_uid)) |
260 |
{ |
261 |
fprintf (stderr, "Error on downsizing with seteuid()\n"); |
262 |
return 1; |
263 |
} |
264 |
} |
265 |
return 0; |
266 |
} |
267 |
|
268 |
int upgradeEffectiveToRealUid (uid_t real_uid, uid_t saved_uid) |
269 |
{ |
270 |
/* Do not forget to put back the original effective uid on the process. */ |
271 |
if (real_uid != 0) |
272 |
{ |
273 |
if (seteuid(saved_uid)) |
274 |
{ |
275 |
fprintf (stderr, "Error on returning seteuid()\n"); |
276 |
return 1; |
277 |
} |
278 |
} |
279 |
return 0; |
280 |
} |
281 |
|
282 |
|
283 |
|
284 |
/****************************************************************************** |
285 |
Function: get_gidlist() |
286 |
|
287 |
Description: |
288 |
Finds the list of gids for user in the group file (/etc/group) |
289 |
Returns a list of gid_t which should be freed by calling program. |
290 |
|
291 |
Parameters: |
292 |
username: the name of the user |
293 |
ngroups: ptr to int which will be filled with the number of gids. |
294 |
group_list: ptr to an array of gid_t. |
295 |
|
296 |
Returns: |
297 |
0 on success. |
298 |
-1 on realloc failure |
299 |
-2 on getgrent failure |
300 |
1 on failure |
301 |
******************************************************************************/ |
302 |
int get_gidlist( |
303 |
const char * username, |
304 |
int * ngroups, |
305 |
gid_t ** group_list |
306 |
) |
307 |
{ |
308 |
struct group * group_info = NULL; |
309 |
gid_t * groups = NULL; |
310 |
gid_t * newgroups = NULL; |
311 |
int i = 0; |
312 |
|
313 |
/* rewind the file pointer to the beginning of the /etc/group file */ |
314 |
setgrent(); |
315 |
|
316 |
lcmaps_log_debug(2, "\tlcmaps_get_gidlist(): looping through group file\n"); |
317 |
*ngroups = 0; |
318 |
while ( ( group_info = getgrent() ) ) |
319 |
{ |
320 |
char ** pgr_mem = group_info->gr_mem; |
321 |
char * gr_mem = NULL; |
322 |
|
323 |
lcmaps_log_debug(4, "\tlcmaps_get_gidlist(): group %s\n", group_info->gr_name); |
324 |
while ( (gr_mem = *pgr_mem) ) |
325 |
{ |
326 |
lcmaps_log_debug(4, "\tlcmaps_get_gidlist(): \tgroup member %s\n", gr_mem); |
327 |
if (strncmp(username, gr_mem, strlen(username))==0) |
328 |
{ |
329 |
lcmaps_log_debug(2, "\tlcmaps_get_gidlist(): \t\tfound group %s for %s\n", |
330 |
group_info->gr_name, username); |
331 |
(*ngroups)++; |
332 |
newgroups = (gid_t *) realloc(groups, ((*ngroups) * sizeof(gid_t))); |
333 |
if (newgroups == NULL) |
334 |
{ |
335 |
lcmaps_log(1, "lcmaps_get_gidlist(): cannot realloc\n"); |
336 |
free(groups); |
337 |
return -1; |
338 |
} |
339 |
groups=newgroups; |
340 |
groups[(*ngroups)-1] = group_info->gr_gid; |
341 |
} |
342 |
++pgr_mem; |
343 |
} |
344 |
} |
345 |
if (errno==ENOMEM) |
346 |
{ |
347 |
lcmaps_log(1, "lcmaps_get_gidlist(): Cannot read the group file, %s\n", strerror(errno)); |
348 |
free(groups); |
349 |
groups=NULL; |
350 |
/* Close the group file */ |
351 |
endgrent(); |
352 |
return -2; |
353 |
} |
354 |
*group_list=groups; |
355 |
lcmaps_log_debug(4,"\tlcmaps_get_gidlist(): %d groups found for %s\n", *ngroups, username); |
356 |
for (i = 0; i < *ngroups; i++) |
357 |
{ |
358 |
lcmaps_log_debug(4,"\tlcmaps_get_gidlist(): group nr %d ==> gid_t %d\n", i+1, groups[i]); |
359 |
} |
360 |
/* Close the group file */ |
361 |
endgrent(); |
362 |
return 0; |
363 |
} |
364 |
|
365 |
|