1 |
/**************************************************** |
2 |
C-GUL |
3 |
|
4 |
Generate random characters |
5 |
|
6 |
****************************************************/ |
7 |
|
8 |
|
9 |
uid_t threadsafe_getuid_from_name (const char * username) |
10 |
{ |
11 |
struct passwd * p = NULL; |
12 |
uid_t uid = -1; |
13 |
int errno_save = 0; |
14 |
#define HAVE_GETPWNAM_R |
15 |
#ifdef HAVE_GETPWNAM_R || defined _LIBC |
16 |
#ifdef _SC_GETPW_R_SIZE_MAX |
17 |
size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX); |
18 |
#else |
19 |
size_t buflen = 128; |
20 |
#endif |
21 |
char *pwtmpbuf; |
22 |
struct passwd pwbuf; |
23 |
|
24 |
|
25 |
if (buflen == -1) |
26 |
/* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a |
27 |
moderate value. */ |
28 |
buflen = 128; |
29 |
|
30 |
pwtmpbuf = (char *) calloc (1, buflen); |
31 |
|
32 |
while (getpwnam_r (username, &pwbuf, pwtmpbuf, buflen, &p) != 0) |
33 |
{ |
34 |
if (errno != ERANGE) |
35 |
{ |
36 |
p = NULL; |
37 |
break; |
38 |
} |
39 |
buflen *= 2; |
40 |
free (pwtmpbuf); |
41 |
|
42 |
if (!(pwtmpbuf = (char *) calloc (1, buflen))) |
43 |
{ |
44 |
if (errno == ENOMEM) |
45 |
{ |
46 |
/* No memory available, bail out */ |
47 |
p = NULL; |
48 |
errno_save = errno; |
49 |
break; |
50 |
} |
51 |
} |
52 |
} |
53 |
#else |
54 |
p = getpwnam (username); |
55 |
#endif |
56 |
|
57 |
if (p) |
58 |
{ |
59 |
uid = p -> pw_uid; |
60 |
} |
61 |
|
62 |
free (pwtmpbuf); |
63 |
errno = errno_save; |
64 |
return uid; |
65 |
} |
66 |
|
67 |
|
68 |
|
69 |
/* When the proxy is located on an NFS mount and on the server side the root squash |
70 |
* option has been enabled, the effective uid is mapped to user 'nobody' which should |
71 |
* not be able to read the proxy file. To work around this problem, the effective |
72 |
* uid of the process is changed to that of the calling user and once glexec is done, |
73 |
* the saved uid is used to restore the identity of the process, |
74 |
*/ |
75 |
#if 0 |
76 |
Example: |
77 |
uid_t stored_real_uid = -1; |
78 |
uid_t stored_eff_uid = -1; |
79 |
|
80 |
/* Downgrade effective privileges to cope with NFS mounted file systems with root squashing */ |
81 |
downgradeEffectiveToRealUid (&stored_real_uid, &stored_eff_uid); |
82 |
|
83 |
/* Read PEM string */ |
84 |
fopen(proxyfile, "r"); |
85 |
|
86 |
/* Restore privileges to previous state */ |
87 |
upgradeEffectiveToRealUid (stored_real_uid, stored_eff_uid); |
88 |
#endif |
89 |
int downgradeEffectiveToRealUid (uid_t * real_uid, uid_t * saved_uid) |
90 |
{ |
91 |
*real_uid = getuid(); |
92 |
if (*real_uid != 0) |
93 |
{ |
94 |
/* Save it */ |
95 |
*saved_uid = geteuid(); |
96 |
if (seteuid(*real_uid)) |
97 |
{ |
98 |
fprintf (stderr, "Error on downsizing with seteuid()\n"); |
99 |
return 1; |
100 |
} |
101 |
} |
102 |
return 0; |
103 |
} |
104 |
|
105 |
int upgradeEffectiveToRealUid (uid_t real_uid, uid_t saved_uid) |
106 |
{ |
107 |
/* Do not forget to put back the original effective uid on the process. */ |
108 |
if (real_uid != 0) |
109 |
{ |
110 |
if (seteuid(saved_uid)) |
111 |
{ |
112 |
fprintf (stderr, "Error on returning seteuid()\n"); |
113 |
return 1; |
114 |
} |
115 |
} |
116 |
return 0; |
117 |
} |
118 |
|
119 |
|
120 |
|
121 |
/****************************************************************************** |
122 |
Function: get_gidlist() |
123 |
|
124 |
Description: |
125 |
Finds the list of gids for user in the group file (/etc/group) |
126 |
Returns a list of gid_t which should be freed by calling program. |
127 |
|
128 |
Parameters: |
129 |
username: the name of the user |
130 |
ngroups: ptr to int which will be filled with the number of gids. |
131 |
group_list: ptr to an array of gid_t. |
132 |
|
133 |
Returns: |
134 |
0 on success. |
135 |
-1 on realloc failure |
136 |
-2 on getgrent failure |
137 |
1 on failure |
138 |
******************************************************************************/ |
139 |
int get_gidlist( |
140 |
const char * username, |
141 |
int * ngroups, |
142 |
gid_t ** group_list |
143 |
) |
144 |
{ |
145 |
struct group * group_info = NULL; |
146 |
gid_t * groups = NULL; |
147 |
gid_t * newgroups = NULL; |
148 |
int i = 0; |
149 |
|
150 |
/* rewind the file pointer to the beginning of the /etc/group file */ |
151 |
setgrent(); |
152 |
|
153 |
lcmaps_log_debug(2, "\tlcmaps_get_gidlist(): looping through group file\n"); |
154 |
*ngroups = 0; |
155 |
while ( ( group_info = getgrent() ) ) |
156 |
{ |
157 |
char ** pgr_mem = group_info->gr_mem; |
158 |
char * gr_mem = NULL; |
159 |
|
160 |
lcmaps_log_debug(4, "\tlcmaps_get_gidlist(): group %s\n", group_info->gr_name); |
161 |
while ( (gr_mem = *pgr_mem) ) |
162 |
{ |
163 |
lcmaps_log_debug(4, "\tlcmaps_get_gidlist(): \tgroup member %s\n", gr_mem); |
164 |
if (strncmp(username, gr_mem, strlen(username))==0) |
165 |
{ |
166 |
lcmaps_log_debug(2, "\tlcmaps_get_gidlist(): \t\tfound group %s for %s\n", |
167 |
group_info->gr_name, username); |
168 |
(*ngroups)++; |
169 |
newgroups = (gid_t *) realloc(groups, ((*ngroups) * sizeof(gid_t))); |
170 |
if (newgroups == NULL) |
171 |
{ |
172 |
lcmaps_log(1, "lcmaps_get_gidlist(): cannot realloc\n"); |
173 |
free(groups); |
174 |
return -1; |
175 |
} |
176 |
groups=newgroups; |
177 |
groups[(*ngroups)-1] = group_info->gr_gid; |
178 |
} |
179 |
++pgr_mem; |
180 |
} |
181 |
} |
182 |
if (errno==ENOMEM) |
183 |
{ |
184 |
lcmaps_log(1, "lcmaps_get_gidlist(): Cannot read the group file, %s\n", strerror(errno)); |
185 |
free(groups); |
186 |
groups=NULL; |
187 |
/* Close the group file */ |
188 |
endgrent(); |
189 |
return -2; |
190 |
} |
191 |
*group_list=groups; |
192 |
lcmaps_log_debug(4,"\tlcmaps_get_gidlist(): %d groups found for %s\n", *ngroups, username); |
193 |
for (i = 0; i < *ngroups; i++) |
194 |
{ |
195 |
lcmaps_log_debug(4,"\tlcmaps_get_gidlist(): group nr %d ==> gid_t %d\n", i+1, groups[i]); |
196 |
} |
197 |
/* Close the group file */ |
198 |
endgrent(); |
199 |
return 0; |
200 |
} |
201 |
|
202 |
|