Merge from vendor branch LESS:
[dragonfly.git] / contrib / bind-9.3 / lib / bind / irs / nis_ng.c
1 /*
2  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (c) 1996,1999 by Internet Software Consortium.
4  *
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.
8  *
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.
16  */
17
18 #if defined(LIBC_SCCS) && !defined(lint)
19 static const char rcsid[] = "$Id: nis_ng.c,v 1.2.206.1 2004/03/09 08:33:38 marka Exp $";
20 #endif
21
22 /* Imports */
23
24 #include "port_before.h"
25
26 #ifndef WANT_IRS_NIS
27 static int __bind_irs_nis_unneeded;
28 #else
29
30 #include <sys/types.h>
31 #include <netinet/in.h>
32 #include <rpc/rpc.h>
33 #include <rpc/xdr.h>
34 #include <rpcsvc/yp_prot.h>
35 #include <rpcsvc/ypclnt.h>
36
37 #include <isc/assertions.h>
38 #include <ctype.h>
39 #include <errno.h>
40 #include <netdb.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44
45 #include <netinet/in.h>
46 #ifdef T_NULL
47 #undef T_NULL                   /* Silence re-definition warning of T_NULL. */
48 #endif
49 #include <arpa/nameser.h>
50 #include <resolv.h>
51
52 #include <isc/memcluster.h>
53 #include <irs.h>
54
55 #include "port_after.h"
56
57 #include "irs_p.h"
58 #include "nis_p.h"
59
60 /* Definitions */
61
62 struct tmpgrp {
63         const char *    name;
64         const char *    host;
65         const char *    user;
66         const char *    domain;
67         struct tmpgrp * next;
68 };
69
70 struct pvt {
71         char *          nis_domain;
72         struct tmpgrp * tmp;
73         struct tmpgrp * cur;
74         char *          tmpgroup;
75 };
76
77 enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 };
78
79 static /*const*/ char netgroup_map[]    = "netgroup";
80
81 /* Forward */
82
83 static void             ng_close(struct irs_ng *);
84 static int              ng_next(struct irs_ng *, const char **,
85                                 const char **, const char **);
86 static int              ng_test(struct irs_ng *,
87                                 const char *, const char *,
88                                 const char *, const char *);
89 static void             ng_rewind(struct irs_ng *, const char *);
90 static void             ng_minimize(struct irs_ng *);
91
92 static void             add_group_to_list(struct pvt *, const char *, int);
93 static void             add_tuple_to_list(struct pvt *, const char *, char *);
94 static void             tmpfree(struct pvt *);
95
96 /* Public */
97
98 struct irs_ng *
99 irs_nis_ng(struct irs_acc *this) {
100         struct irs_ng *ng;
101         struct pvt *pvt;
102
103         if (!(ng = memget(sizeof *ng))) {
104                 errno = ENOMEM;
105                 return (NULL);
106         }
107         memset(ng, 0x5e, sizeof *ng);
108         if (!(pvt = memget(sizeof *pvt))) {
109                 memput(ng, sizeof *ng);
110                 errno = ENOMEM;
111                 return (NULL);
112         }
113         memset(pvt, 0, sizeof *pvt);
114         pvt->nis_domain = ((struct nis_p *)this->private)->domain;
115         ng->private = pvt;
116         ng->close = ng_close;
117         ng->next = ng_next;
118         ng->test = ng_test;
119         ng->rewind = ng_rewind;
120         ng->minimize = ng_minimize;
121         return (ng);
122 }
123
124 /* Methods */
125
126 static void
127 ng_close(struct irs_ng *this) {
128         struct pvt *pvt = (struct pvt *)this->private;
129
130         tmpfree(pvt);
131         memput(pvt, sizeof *pvt);
132         memput(this, sizeof *this);
133 }
134
135 static int
136 ng_next(struct irs_ng *this, const char **host, const char **user, const char **domain) {
137         struct pvt *pvt = (struct pvt *)this->private;
138
139         if (!pvt->cur)
140                 return (0);
141         *host = pvt->cur->host;
142         *user = pvt->cur->user;
143         *domain = pvt->cur->domain;
144         pvt->cur = pvt->cur->next;
145         return (1);
146 }
147
148 static int
149 ng_test(struct irs_ng *this, const char *name,
150         const char *host, const char *user, const char *domain)
151 {
152         struct pvt *pvt = (struct pvt *)this->private;
153         struct tmpgrp *cur;
154
155         tmpfree(pvt);
156         add_group_to_list(pvt, name, strlen(name));
157         for (cur = pvt->tmp; cur; cur = cur->next) {
158                 if ((!host || !cur->host || !strcmp(host, cur->host)) &&
159                     (!user || !cur->user || !strcmp(user, cur->user)) &&
160                     (!domain || !cur->domain || !strcmp(domain, cur->domain)))
161                         break;
162         }
163         tmpfree(pvt);
164         return ((cur == NULL) ? 0 : 1);
165 }
166
167 static void
168 ng_rewind(struct irs_ng *this, const char *name) {
169         struct pvt *pvt = (struct pvt *)this->private;
170
171         /* Either hand back or free the existing list. */
172         if (pvt->tmpgroup) {
173                 if (pvt->tmp && !strcmp(pvt->tmpgroup, name))
174                         goto reset;
175                 tmpfree(pvt);
176         }
177         pvt->tmpgroup = strdup(name);
178         add_group_to_list(pvt, name, strlen(name));
179  reset:
180         pvt->cur = pvt->tmp;
181 }
182
183 static void
184 ng_minimize(struct irs_ng *this) {
185         UNUSED(this);
186         /* NOOP */
187 }
188
189 /* Private */
190
191 static void
192 add_group_to_list(struct pvt *pvt, const char *name, int len) {
193         char *vdata, *cp, *np;
194         struct tmpgrp *tmp;
195         int vlen, r;
196         char *nametmp;
197
198         /* Don't add the same group to the list more than once. */
199         for (tmp = pvt->tmp; tmp; tmp = tmp->next)
200                 if (!strcmp(tmp->name, name))
201                         return;
202
203         DE_CONST(name, nametmp);
204         r = yp_match(pvt->nis_domain, netgroup_map, nametmp, len,
205                      &vdata, &vlen);
206         if (r == 0) {
207                 cp = vdata;
208                 if (*cp && cp[strlen(cp)-1] == '\n')
209                   cp[strlen(cp)-1] = '\0';
210                 for ( ; cp; cp = np) {
211                         np = strchr(cp, ' ');
212                         if (np)
213                                 *np++ = '\0';
214                         if (*cp == '(')
215                                 add_tuple_to_list(pvt, name, cp);
216                         else
217                                 add_group_to_list(pvt, cp, strlen(cp));
218                 }
219                 free(vdata);
220         }
221 }
222
223 static void
224 add_tuple_to_list(struct pvt *pvt, const char *name, char *cp) {
225         struct tmpgrp *tmp;
226         char *tp, *np;
227
228         INSIST(*cp++ == '(');
229
230         tmp = malloc(sizeof *tmp + strlen(name) + sizeof '\0' +
231                      strlen(cp) - sizeof ')');
232         if (!tmp)
233                 return;
234         memset(tmp, 0, sizeof *tmp);
235         tp = ((char *)tmp) + sizeof *tmp;
236
237         /* Name */
238         strcpy(tp, name);
239         tmp->name = tp;
240         tp += strlen(tp) + 1;
241
242         /* Host */
243         if (!(np = strchr(cp, ',')))
244                 goto cleanup;
245         *np++ = '\0';
246         strcpy(tp, cp);
247         tmp->host = tp;
248         tp += strlen(tp) + 1;
249         cp = np;
250
251         /* User */
252         if (!(np = strchr(cp, ',')))
253                 goto cleanup;
254         *np++ = '\0';
255         strcpy(tp, cp);
256         tmp->user = tp;
257         tp += strlen(tp) + 1;
258         cp = np;
259
260         /* Domain */
261         if (!(np = strchr(cp, ')')))
262                 goto cleanup;
263         *np++ = '\0';
264         strcpy(tp, cp);
265         tmp->domain = tp;
266
267         /*
268          * Empty string in file means wildcard, but
269          * NULL string in return value means wildcard.
270          */
271         if (!*tmp->host)
272                 tmp->host = NULL;
273         if (!*tmp->user)
274                 tmp->user = NULL;
275         if (!*tmp->domain)
276                 tmp->domain = NULL;
277
278         /* Add to list (LIFO). */
279         tmp->next = pvt->tmp;
280         pvt->tmp = tmp;
281         return;
282
283  cleanup:
284         free(tmp);
285 }
286
287 static void
288 tmpfree(struct pvt *pvt) {
289         struct tmpgrp *cur, *next;
290
291         if (pvt->tmpgroup) {
292                 free(pvt->tmpgroup);
293                 pvt->tmpgroup = NULL;
294         }
295         for (cur = pvt->tmp; cur; cur = next) {
296                 next = cur->next;
297                 free(cur);
298         }
299         pvt->tmp = NULL;
300 }
301
302 #endif /*WANT_IRS_NIS*/