Libinfo-89.tar.gz
[apple/libinfo.git] / lookup.subproj / lu_group.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 * Unix group lookup
26 * Copyright (C) 1989 by NeXT, Inc.
27 */
28
29 #include <stdlib.h>
30 #include <mach/mach.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <ctype.h>
34 #include <rpc/types.h>
35 #include <rpc/xdr.h>
36 #include <grp.h>
37 #include <netinet/in.h>
38 #include <sys/param.h>
39 #include <unistd.h>
40
41 #include "_lu_types.h"
42 #include "lookup.h"
43 #include "lu_utils.h"
44 #include "lu_overrides.h"
45
46 #define GROUP_SENTINEL -99
47
48 static lookup_state gr_state = LOOKUP_CACHE;
49 static struct group global_gr;
50 static int global_free = 1;
51 static char *gr_data;
52 static unsigned gr_datalen = 0;
53 static int gr_nentries = 0;
54 static int gr_start = 1;
55 static XDR gr_xdr;
56
57 static void
58 freeold(void)
59 {
60 char **mem;
61
62 if (global_free == 1) return;
63
64 free(global_gr.gr_name);
65 global_gr.gr_name = NULL;
66
67 free(global_gr.gr_passwd);
68 global_gr.gr_passwd = NULL;
69
70 mem = global_gr.gr_mem;
71 if (mem != NULL)
72 {
73 while (*mem != NULL) free(*mem++);
74 free(global_gr.gr_mem);
75 global_gr.gr_mem = NULL;
76 }
77
78 global_free = 1;
79 }
80
81 static void
82 convert_gr(_lu_group *lu_gr)
83 {
84 int i, len;
85
86 freeold();
87
88 global_gr.gr_name = strdup(lu_gr->gr_name);
89 global_gr.gr_passwd = strdup(lu_gr->gr_passwd);
90 global_gr.gr_gid = lu_gr->gr_gid;
91
92 len = lu_gr->gr_mem.gr_mem_len;
93 global_gr.gr_mem = (char **)malloc((len + 1) * sizeof(char *));
94
95 for (i = 0; i < len; i++)
96 {
97 global_gr.gr_mem[i] = strdup(lu_gr->gr_mem.gr_mem_val[i]);
98 }
99
100 global_gr.gr_mem[len] = NULL;
101
102 global_free = 0;
103 }
104
105 static struct group *
106 lu_getgrgid(int gid)
107 {
108 unsigned datalen;
109 _lu_group_ptr lu_gr;
110 XDR xdr;
111 static int proc = -1;
112 unit lookup_buf[MAX_INLINE_UNITS];
113
114 if (proc < 0)
115 {
116 if (_lookup_link(_lu_port, "getgrgid", &proc) != KERN_SUCCESS)
117 {
118 return (NULL);
119 }
120 }
121
122 gid = htonl(gid);
123 datalen = MAX_INLINE_UNITS;
124
125 if (_lookup_one(_lu_port, proc, (unit *)&gid, 1, lookup_buf, &datalen)
126 != KERN_SUCCESS)
127 {
128 return (NULL);
129 }
130
131 datalen *= BYTES_PER_XDR_UNIT;
132 xdrmem_create(&xdr, lookup_buf, datalen, XDR_DECODE);
133 lu_gr = NULL;
134
135 if (!xdr__lu_group_ptr(&xdr, &lu_gr) || lu_gr == NULL)
136 {
137 xdr_destroy(&xdr);
138 return (NULL);
139 }
140
141 xdr_destroy(&xdr);
142
143 convert_gr(lu_gr);
144 xdr_free(xdr__lu_group_ptr, &lu_gr);
145 return (&global_gr);
146 }
147
148 static struct group *
149 lu_getgrnam(const char *name)
150 {
151 unsigned datalen;
152 char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT];
153 XDR outxdr;
154 XDR inxdr;
155 _lu_group_ptr lu_gr;
156 static int proc = -1;
157 unit lookup_buf[MAX_INLINE_UNITS];
158
159 if (proc < 0)
160 {
161 if (_lookup_link(_lu_port, "getgrnam", &proc) != KERN_SUCCESS)
162 {
163 return (NULL);
164 }
165 }
166
167 xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE);
168
169 if (!xdr__lu_string(&outxdr, &name))
170 {
171 xdr_destroy(&outxdr);
172 return (NULL);
173 }
174
175 datalen = MAX_INLINE_UNITS;
176
177 if (_lookup_one(_lu_port, proc, (unit *)namebuf,
178 xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, lookup_buf, &datalen)
179 != KERN_SUCCESS)
180 {
181 return (NULL);
182 }
183
184 xdr_destroy(&outxdr);
185
186 datalen *= BYTES_PER_XDR_UNIT;
187 xdrmem_create(&inxdr, lookup_buf, datalen,
188 XDR_DECODE);
189 lu_gr = NULL;
190
191 if (!xdr__lu_group_ptr(&inxdr, &lu_gr) || (lu_gr == NULL))
192 {
193 xdr_destroy(&inxdr);
194 return (NULL);
195 }
196
197 xdr_destroy(&inxdr);
198
199 convert_gr(lu_gr);
200 xdr_free(xdr__lu_group_ptr, &lu_gr);
201 return (&global_gr);
202 }
203
204
205 static int
206 lu_initgroups(const char *name, int basegid)
207 {
208 unsigned datalen;
209 XDR outxdr;
210 XDR inxdr;
211 static int proc = -1;
212 unit lookup_buf[MAX_INLINE_UNITS];
213 char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT];
214 int groups[NGROUPS];
215 int ngroups = 1;
216 int a_group;
217 int count;
218
219 groups[0] = basegid;
220
221 if (proc < 0)
222 {
223 if (_lookup_link(_lu_port, "initgroups", &proc) != KERN_SUCCESS)
224 {
225 return -1;
226 }
227 }
228
229 xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE);
230 if (!xdr__lu_string(&outxdr, &name))
231 {
232 xdr_destroy(&outxdr);
233 return -1;
234 }
235
236 datalen = MAX_INLINE_UNITS;
237 if (_lookup_one(_lu_port, proc, (unit *)namebuf,
238 xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, lookup_buf, &datalen)
239 != KERN_SUCCESS)
240 {
241 xdr_destroy(&outxdr);
242 return -1;
243 }
244
245 xdr_destroy(&outxdr);
246
247 datalen *= BYTES_PER_XDR_UNIT;
248 xdrmem_create(&inxdr, lookup_buf, datalen,
249 XDR_DECODE);
250
251 while (xdr_int(&inxdr, &a_group))
252 {
253 if (a_group == GROUP_SENTINEL) break;
254
255 for (count = 0; count < ngroups; count++)
256 {
257 if (groups[count] == a_group) break;
258 }
259
260 if (count >= ngroups) groups[ngroups++] = a_group;
261 }
262 xdr_destroy(&inxdr);
263
264 return setgroups(ngroups, groups);
265 }
266
267 static void
268 lu_endgrent(void)
269 {
270 gr_nentries = 0;
271 if (gr_data != NULL)
272 {
273 freeold();
274 vm_deallocate(mach_task_self(), (vm_address_t)gr_data, gr_datalen);
275 gr_data = NULL;
276 }
277 }
278
279 static int
280 lu_setgrent(void)
281 {
282 lu_endgrent();
283 gr_start = 1;
284 return (1);
285 }
286
287 static struct group *
288 lu_getgrent()
289 {
290 static int proc = -1;
291 _lu_group lu_gr;
292
293 if (gr_start == 1)
294 {
295 gr_start = 0;
296
297 if (proc < 0)
298 {
299 if (_lookup_link(_lu_port, "getgrent", &proc) != KERN_SUCCESS)
300 {
301 lu_endgrent();
302 return (NULL);
303 }
304 }
305
306 if (_lookup_all(_lu_port, proc, NULL, 0, &gr_data, &gr_datalen)
307 != KERN_SUCCESS)
308 {
309 lu_endgrent();
310 return (NULL);
311 }
312
313 #ifdef NOTDEF
314 /* NOTDEF because OOL buffers are counted in bytes with untyped IPC */
315 gr_datalen *= BYTES_PER_XDR_UNIT;
316 #endif
317 xdrmem_create(&gr_xdr, gr_data, gr_datalen,
318 XDR_DECODE);
319 if (!xdr_int(&gr_xdr, &gr_nentries))
320 {
321 xdr_destroy(&gr_xdr);
322 lu_endgrent();
323 return (NULL);
324 }
325 }
326
327 if (gr_nentries == 0)
328 {
329 xdr_destroy(&gr_xdr);
330 lu_endgrent();
331 return (NULL);
332 }
333
334 bzero(&lu_gr, sizeof(lu_gr));
335 if (!xdr__lu_group(&gr_xdr, &lu_gr))
336 {
337 xdr_destroy(&gr_xdr);
338 lu_endgrent();
339 return (NULL);
340 }
341
342 gr_nentries--;
343 convert_gr(&lu_gr);
344 xdr_free(xdr__lu_group, &lu_gr);
345 return (&global_gr);
346 }
347
348 struct group *
349 getgrgid(gid_t gid)
350 {
351 LOOKUP1(lu_getgrgid, _old_getgrgid, gid, struct group);
352 }
353
354 struct group *
355 getgrnam(const char *name)
356 {
357 LOOKUP1(lu_getgrnam, _old_getgrnam, name, struct group);
358 }
359
360 int
361 initgroups(const char *name, int basegid)
362 {
363 int res;
364
365 if (name == NULL) return -1;
366
367 if (_lu_running())
368 {
369 if ((res = lu_initgroups(name, basegid)))
370 {
371 res = _old_initgroups(name, basegid);
372 }
373 }
374 else
375 {
376 res = _old_initgroups(name, basegid);
377 }
378
379 return (res);
380 }
381
382 struct group *
383 getgrent(void)
384 {
385 GETENT(lu_getgrent, _old_getgrent, &gr_state, struct group);
386 }
387
388 int
389 setgrent(void)
390 {
391 INTSETSTATEVOID(lu_setgrent, _old_setgrent, &gr_state);
392 }
393
394 void
395 endgrent(void)
396 {
397 UNSETSTATE(lu_endgrent, _old_endgrent, &gr_state);
398 }