1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * ns_generic.c
23 *
24 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27
28 #include <stdio.h>
29 #include <syslog.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <nsswitch.h>
33 #include <sys/param.h>
34 #include <netdb.h>
35 #include <errno.h>
36 #include <assert.h>
37 #include <rpc/rpc.h>
38 #include <rpcsvc/nfs_prot.h>
39 #include "automount.h"
40
41 /*
42 * Each name service is represented by a ns_info structure.
43 */
44 struct ns_info {
45 char *ns_name; /* service name */
46 void (*ns_init)(); /* initialization routine */
47 int (*ns_getmapent)(); /* get map entry given key */
48 int (*ns_loadmaster)(); /* load master map */
49 int (*ns_loaddirect)(); /* load direct map */
50 int (*ns_getmapkeys)(); /* readdir */
51 };
52
53 static struct ns_info ns_info[] = {
54
55 "files", init_files, getmapent_files,
56 loadmaster_files, loaddirect_files,
57 getmapkeys_files,
58
59 "ldap", init_ldap, getmapent_ldap,
60 loadmaster_ldap, loaddirect_ldap,
61 getmapkeys_ldap,
62
63 "nis", init_nis, getmapent_nis,
64 loadmaster_nis, loaddirect_nis,
65 getmapkeys_nis,
66
67 NULL, NULL, NULL, NULL, NULL, NULL, NULL
68 };
69
70 static struct ns_info *get_next_ns(struct __nsw_lookup **, int);
71
72 void
ns_setup(char ** stack,char *** stkptr)73 ns_setup(char **stack, char ***stkptr)
74 {
75 struct ns_info *nsp;
76
77 for (nsp = ns_info; nsp->ns_name; nsp++) {
78 nsp->ns_init(stack, stkptr);
79 }
80 }
81
82 static struct ns_info *
get_next_ns(curr_ns,curr_nserr)83 get_next_ns(curr_ns, curr_nserr)
84 struct __nsw_lookup **curr_ns;
85 int curr_nserr;
86 {
87 static struct __nsw_switchconfig *conf = NULL;
88 enum __nsw_parse_err pserr;
89 struct __nsw_lookup *lkp;
90 struct ns_info *nsp;
91
92 if (conf == NULL) {
93 /* __nsw_getconfig() is protected by a lock */
94 conf = __nsw_getconfig("automount", &pserr);
95 if (conf == NULL) {
96 return (NULL);
97 }
98 }
99
100 if (*curr_ns == NULL)
101 /* first time */
102 lkp = conf->lookups;
103 else {
104 lkp = *curr_ns;
105 /* __NSW_ACTION is MT-Safe */
106 if (__NSW_ACTION(lkp, curr_nserr) == __NSW_RETURN)
107 return (NULL);
108 lkp = lkp->next;
109 }
110
111 for (; lkp; lkp = lkp->next) {
112 for (nsp = ns_info; nsp->ns_name; nsp++) {
113 if (strcmp(lkp->service_name, nsp->ns_name) == 0) {
114 *curr_ns = lkp;
115 return (nsp);
116 }
117 }
118 /*
119 * Note: if we get here then we've found
120 * an unsupported name service.
121 */
122 }
123
124 return (NULL);
125 }
126
127 int
getmapent(key,mapname,ml,stack,stkptr,iswildcard,isrestricted)128 getmapent(key, mapname, ml, stack, stkptr, iswildcard, isrestricted)
129 char *key, *mapname;
130 struct mapline *ml;
131 char **stack, ***stkptr;
132 bool_t *iswildcard;
133 bool_t isrestricted;
134 {
135 struct __nsw_lookup *curr_ns = NULL;
136 int ns_err = __NSW_SUCCESS;
137 struct ns_info *nsp;
138
139 if (strcmp(mapname, "-hosts") == 0) {
140 (void) strcpy(ml->linebuf, "-hosts");
141 return (__NSW_SUCCESS);
142 }
143
144 if (*mapname == '/') /* must be a file */
145 return (getmapent_files(key, mapname, ml, stack, stkptr,
146 iswildcard, isrestricted));
147
148 while ((nsp = get_next_ns(&curr_ns, ns_err)) != NULL) {
149 ns_err = nsp->ns_getmapent(key, mapname, ml, stack, stkptr,
150 iswildcard, isrestricted);
151 if (ns_err == __NSW_SUCCESS)
152 return (__NSW_SUCCESS);
153 }
154
155 return (__NSW_UNAVAIL);
156 }
157
158 int
loadmaster_map(mapname,defopts,stack,stkptr)159 loadmaster_map(mapname, defopts, stack, stkptr)
160 char *mapname, *defopts;
161 char **stack, ***stkptr;
162 {
163 struct __nsw_lookup *curr_ns = NULL;
164 int ns_err = __NSW_SUCCESS;
165 struct ns_info *nsp;
166
167 if (*mapname == '/') /* must be a file */
168 return (loadmaster_files(mapname, defopts, stack, stkptr));
169
170 while ((nsp = get_next_ns(&curr_ns, ns_err)) != NULL) {
171 ns_err = nsp->ns_loadmaster(mapname, defopts, stack, stkptr);
172 if (ns_err == __NSW_SUCCESS)
173 return (__NSW_SUCCESS);
174 }
175
176 return (__NSW_UNAVAIL);
177 }
178
179 int
loaddirect_map(mapname,localmap,defopts,stack,stkptr)180 loaddirect_map(mapname, localmap, defopts, stack, stkptr)
181 char *mapname, *localmap, *defopts;
182 char **stack, ***stkptr;
183 {
184 struct __nsw_lookup *curr_ns = NULL;
185 int ns_err = __NSW_SUCCESS;
186 struct ns_info *nsp;
187
188 if (*mapname == '/') /* must be a file */
189 return (loaddirect_files(mapname, localmap, defopts,
190 stack, stkptr));
191
192 while ((nsp = get_next_ns(&curr_ns, ns_err)) != NULL) {
193 ns_err = nsp->ns_loaddirect(mapname, localmap, defopts, stack,
194 stkptr);
195 if (ns_err == __NSW_SUCCESS)
196 return (__NSW_SUCCESS);
197 }
198
199 return (__NSW_UNAVAIL);
200 }
201
202 int
gethostkeys(mapname,list,error,cache_time)203 gethostkeys(mapname, list, error, cache_time)
204 char *mapname;
205 struct dir_entry **list;
206 int *error;
207 int *cache_time;
208 {
209 char *buffer, **p;
210 int bufferlen = 1000;
211 struct dir_entry *last = NULL;
212 struct hostent ent;
213
214 #ifdef lint
215 mapname = mapname;
216 #endif
217
218 *cache_time = RDDIR_CACHE_TIME * 2;
219 *error = 0;
220 if (trace > 1)
221 trace_prt(1, "gethostkeys called\n");
222
223 if (sethostent(1)) {
224 syslog(LOG_ERR, "gethostkeys: sethostent failed");
225 *error = EIO;
226 return (__NSW_UNAVAIL);
227 }
228
229 buffer = (char *)malloc(bufferlen);
230 if (buffer == NULL) {
231 syslog(LOG_ERR, "gethostkeys: malloc of buffer failed");
232 *error = ENOMEM;
233 return (__NSW_UNAVAIL);
234 }
235
236 while (gethostent_r(&ent, buffer, bufferlen, error)) {
237 /*
238 * add canonical name
239 */
240 if (add_dir_entry(ent.h_name, list, &last)) {
241 *error = ENOMEM;
242 goto done;
243 }
244 if (ent.h_aliases == NULL)
245 goto done; /* no aliases */
246 for (p = ent.h_aliases; *p != 0; p++) {
247 if (strcmp(*p, ent.h_name) != 0) {
248 /*
249 * add alias only if different
250 * from canonical name
251 */
252 if (add_dir_entry(*p, list, &last)) {
253 *error = ENOMEM;
254 goto done;
255 }
256 }
257 }
258 assert(last != NULL);
259 }
260 done: if (*list != NULL) {
261 /*
262 * list of entries found
263 */
264 *error = 0;
265 }
266 endhostent();
267
268 return (__NSW_SUCCESS);
269 }
270
271 /*
272 * enumerate all entries in the map in the various name services.
273 */
274 int
getmapkeys(mapname,list,error,cache_time,stack,stkptr,uid)275 getmapkeys(mapname, list, error, cache_time, stack, stkptr, uid)
276 char *mapname;
277 struct dir_entry **list;
278 int *error;
279 int *cache_time;
280 char **stack, ***stkptr;
281 uid_t uid;
282
283 {
284 struct __nsw_lookup *curr_ns = NULL;
285 int ns_err = __NSW_SUCCESS;
286 int success = 0;
287 struct ns_info *nsp;
288
289 if (*mapname == '/') /* must be a file */
290 return (getmapkeys_files(mapname, list, error, cache_time,
291 stack, stkptr));
292 if (strcmp(mapname, "-hosts") == 0) {
293 return (gethostkeys(mapname, list, error, cache_time));
294 }
295
296 while ((nsp = get_next_ns(&curr_ns, ns_err)) != NULL) {
297 ns_err = nsp->ns_getmapkeys(mapname, list, error,
298 cache_time, stack, stkptr);
299 if (*error == 0) {
300 /*
301 * return success if listing was successful
302 * for at least one name service
303 */
304 success++;
305 }
306
307 /*
308 * XXX force next name service
309 */
310 if (ns_err != __NSW_UNAVAIL)
311 ns_err = __NSW_NOTFOUND;
312 }
313 if (success) {
314 /*
315 * if succeeded at least once, return error=0
316 */
317 *error = 0;
318 };
319
320 return (success ? __NSW_SUCCESS : __NSW_NOTFOUND);
321 }
322