2 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (c) 1996-1999 by Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #if !defined(LINT) && !defined(CODECENTER)
19 static const char rcsid
[] = "$Id: gen_gr.c,v 1.4.2.1.4.2 2004/05/17 07:48:56 marka Exp $";
24 #include "port_before.h"
27 static int __bind_irs_gr_unneeded
;
30 #include <sys/types.h>
32 #include <isc/assertions.h>
38 #include <netinet/in.h>
39 #include <arpa/nameser.h>
42 #include <isc/memcluster.h>
45 #include "port_after.h"
53 struct irs_rule
* rules
;
54 struct irs_rule
* rule
;
57 * Need space to store the entries read from the group file.
58 * The members list also needs space per member, and the
59 * strings making up the user names must be allocated
60 * somewhere. Rather than doing lots of small allocations,
61 * we keep one buffer and resize it as needed.
64 size_t nmemb
; /* Malloc'd max index of gr_mem[]. */
67 struct __res_state
* res
;
68 void (*free_res
)(void *);
73 static void gr_close(struct irs_gr
*);
74 static struct group
* gr_next(struct irs_gr
*);
75 static struct group
* gr_byname(struct irs_gr
*, const char *);
76 static struct group
* gr_bygid(struct irs_gr
*, gid_t
);
77 static void gr_rewind(struct irs_gr
*);
78 static int gr_list(struct irs_gr
*, const char *,
79 gid_t
, gid_t
*, int *);
80 static void gr_minimize(struct irs_gr
*);
81 static struct __res_state
* gr_res_get(struct irs_gr
*);
82 static void gr_res_set(struct irs_gr
*,
86 static int grmerge(struct irs_gr
*gr
, const struct group
*src
,
89 static int countvec(char **vec
);
90 static int isnew(char **old
, char *new);
91 static int countnew(char **old
, char **new);
92 static size_t sizenew(char **old
, char **new);
93 static int newgid(int, gid_t
*, gid_t
);
97 #define FREE_IF(x) do { if ((x) != NULL) { free(x); (x) = NULL; } } while (0)
102 irs_gen_gr(struct irs_acc
*this) {
103 struct gen_p
*accpvt
= (struct gen_p
*)this->private;
107 if (!(gr
= memget(sizeof *gr
))) {
111 memset(gr
, 0x5e, sizeof *gr
);
112 if (!(pvt
= memget(sizeof *pvt
))) {
113 memput(gr
, sizeof *gr
);
117 memset(pvt
, 0, sizeof *pvt
);
118 pvt
->rules
= accpvt
->map_rules
[irs_gr
];
119 pvt
->rule
= pvt
->rules
;
121 gr
->close
= gr_close
;
123 gr
->byname
= gr_byname
;
124 gr
->bygid
= gr_bygid
;
125 gr
->rewind
= gr_rewind
;
127 gr
->minimize
= gr_minimize
;
128 gr
->res_get
= gr_res_get
;
129 gr
->res_set
= gr_res_set
;
136 gr_close(struct irs_gr
*this) {
137 struct pvt
*pvt
= (struct pvt
*)this->private;
139 memput(pvt
, sizeof *pvt
);
140 memput(this, sizeof *this);
143 static struct group
*
144 gr_next(struct irs_gr
*this) {
145 struct pvt
*pvt
= (struct pvt
*)this->private;
150 gr
= pvt
->rule
->inst
->gr
;
151 rval
= (*gr
->next
)(gr
);
154 if (!(pvt
->rule
->flags
& IRS_CONTINUE
))
156 pvt
->rule
= pvt
->rule
->next
;
158 gr
= pvt
->rule
->inst
->gr
;
165 static struct group
*
166 gr_byname(struct irs_gr
*this, const char *name
) {
167 struct pvt
*pvt
= (struct pvt
*)this->private;
168 struct irs_rule
*rule
;
174 for (rule
= pvt
->rules
; rule
; rule
= rule
->next
) {
176 tval
= (*gr
->byname
)(gr
, name
);
178 if (!grmerge(this, tval
, dirty
++))
180 if (!(rule
->flags
& IRS_MERGE
))
183 if (!(rule
->flags
& IRS_CONTINUE
))
188 return (&pvt
->group
);
192 static struct group
*
193 gr_bygid(struct irs_gr
*this, gid_t gid
) {
194 struct pvt
*pvt
= (struct pvt
*)this->private;
195 struct irs_rule
*rule
;
201 for (rule
= pvt
->rules
; rule
; rule
= rule
->next
) {
203 tval
= (*gr
->bygid
)(gr
, gid
);
205 if (!grmerge(this, tval
, dirty
++))
207 if (!(rule
->flags
& IRS_MERGE
))
210 if (!(rule
->flags
& IRS_CONTINUE
))
215 return (&pvt
->group
);
220 gr_rewind(struct irs_gr
*this) {
221 struct pvt
*pvt
= (struct pvt
*)this->private;
224 pvt
->rule
= pvt
->rules
;
226 gr
= pvt
->rule
->inst
->gr
;
232 gr_list(struct irs_gr
*this, const char *name
,
233 gid_t basegid
, gid_t
*groups
, int *ngroups
)
235 struct pvt
*pvt
= (struct pvt
*)this->private;
236 struct irs_rule
*rule
;
238 int t_ngroups
, maxgroups
;
242 maxgroups
= *ngroups
;
244 t_groups
= (gid_t
*)malloc(maxgroups
* sizeof(gid_t
));
250 for (rule
= pvt
->rules
; rule
; rule
= rule
->next
) {
251 t_ngroups
= maxgroups
;
253 t
= (*gr
->list
)(gr
, name
, basegid
, t_groups
, &t_ngroups
);
254 for (n
= 0; n
< t_ngroups
; n
++) {
255 if (newgid(*ngroups
, groups
, t_groups
[n
])) {
256 if (*ngroups
== maxgroups
) {
260 groups
[(*ngroups
)++] = t_groups
[n
];
264 if (!(rule
->flags
& IRS_MERGE
))
267 if (!(rule
->flags
& IRS_CONTINUE
))
277 gr_minimize(struct irs_gr
*this) {
278 struct pvt
*pvt
= (struct pvt
*)this->private;
279 struct irs_rule
*rule
;
281 for (rule
= pvt
->rules
; rule
!= NULL
; rule
= rule
->next
) {
282 struct irs_gr
*gr
= rule
->inst
->gr
;
288 static struct __res_state
*
289 gr_res_get(struct irs_gr
*this) {
290 struct pvt
*pvt
= (struct pvt
*)this->private;
293 struct __res_state
*res
;
294 res
= (struct __res_state
*)malloc(sizeof *res
);
299 memset(res
, 0, sizeof *res
);
300 gr_res_set(this, res
, free
);
307 gr_res_set(struct irs_gr
*this, struct __res_state
*res
,
308 void (*free_res
)(void *)) {
309 struct pvt
*pvt
= (struct pvt
*)this->private;
310 struct irs_rule
*rule
;
312 if (pvt
->res
&& pvt
->free_res
) {
313 res_nclose(pvt
->res
);
314 (*pvt
->free_res
)(pvt
->res
);
318 pvt
->free_res
= free_res
;
320 for (rule
= pvt
->rules
; rule
!= NULL
; rule
= rule
->next
) {
321 struct irs_gr
*gr
= rule
->inst
->gr
;
324 (*gr
->res_set
)(gr
, pvt
->res
, NULL
);
331 grmerge(struct irs_gr
*this, const struct group
*src
, int preserve
) {
332 struct pvt
*pvt
= (struct pvt
*)this->private;
333 char *cp
, **m
, **p
, *oldmembuf
, *ep
;
338 pvt
->group
.gr_gid
= src
->gr_gid
;
339 if (pvt
->nmemb
< 1) {
340 m
= malloc(sizeof *m
);
342 /* No harm done, no work done. */
345 pvt
->group
.gr_mem
= m
;
348 pvt
->group
.gr_mem
[0] = NULL
;
350 ndst
= countvec(pvt
->group
.gr_mem
);
351 nnew
= countnew(pvt
->group
.gr_mem
, src
->gr_mem
);
354 * Make sure destination member array is large enough.
355 * p points to new portion.
358 if ((size_t)n
> pvt
->nmemb
) {
359 m
= realloc(pvt
->group
.gr_mem
, n
* sizeof *m
);
361 /* No harm done, no work done. */
364 pvt
->group
.gr_mem
= m
;
367 p
= pvt
->group
.gr_mem
+ ndst
;
370 * Enlarge destination membuf; cp points at new portion.
372 n
= sizenew(pvt
->group
.gr_mem
, src
->gr_mem
);
373 INSIST((nnew
== 0) == (n
== 0));
375 n
+= strlen(src
->gr_name
) + 1;
376 n
+= strlen(src
->gr_passwd
) + 1;
382 used
= preserve
? pvt
->membufsize
: 0;
383 cp
= malloc(used
+ n
);
385 /* No harm done, no work done. */
390 memcpy(cp
, pvt
->membuf
, used
);
391 oldmembuf
= pvt
->membuf
;
393 pvt
->membufsize
= used
+ n
;
397 * Adjust group.gr_mem.
399 if (pvt
->membuf
!= oldmembuf
)
400 for (m
= pvt
->group
.gr_mem
; *m
; m
++)
401 *m
= pvt
->membuf
+ (*m
- oldmembuf
);
406 for (m
= src
->gr_mem
; *m
; m
++)
407 if (isnew(pvt
->group
.gr_mem
, *m
)) {
415 strcpy(cp
, *m
); /* (checked) */
419 pvt
->group
.gr_name
= pvt
->membuf
+
420 (pvt
->group
.gr_name
- oldmembuf
);
421 pvt
->group
.gr_passwd
= pvt
->membuf
+
422 (pvt
->group
.gr_passwd
- oldmembuf
);
424 pvt
->group
.gr_name
= cp
;
425 n
= strlen(src
->gr_name
) + 1;
430 strcpy(cp
, src
->gr_name
); /* (checked) */
433 pvt
->group
.gr_passwd
= cp
;
434 n
= strlen(src
->gr_passwd
) + 1;
439 strcpy(cp
, src
->gr_passwd
); /* (checked) */
443 INSIST(cp
>= pvt
->membuf
&& cp
<= &pvt
->membuf
[pvt
->membufsize
]);
448 countvec(char **vec
) {
457 isnew(char **old
, char *new) {
459 if (strcmp(*old
, new) == 0)
465 countnew(char **old
, char **new) {
469 n
+= isnew(old
, *new);
474 sizenew(char **old
, char **new) {
478 if (isnew(old
, *new))
479 n
+= strlen(*new) + 1;
484 newgid(int ngroups
, gid_t
*groups
, gid_t group
) {
486 for (; ngroups
-- > 0; groups
++)
487 if (*groups
== group
)
492 #endif /* WANT_IRS_GR */