1 /*
2 * Copyright (c) 1997-2006 Erez Zadok
3 * Copyright (c) 1989 Jan-Simon Pendry
4 * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
5 * Copyright (c) 1989 The Regents of the University of California.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Jan-Simon Pendry at Imperial College, London.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgment:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 *
40 * File: am-utils/amd/info_nisplus.c
41 *
42 */
43
44 /*
45 * Get info from NIS+ (version 3) map
46 */
47
48 #ifdef HAVE_CONFIG_H
49 # include <config.h>
50 #endif /* HAVE_CONFIG_H */
51 #include <am_defs.h>
52 #include <amd.h>
53
54 #define NISPLUS_KEY "key="
55 #define NISPLUS_ORGDIR ".org_dir"
56
57 struct nis_callback_data {
58 mnt_map *ncd_m;
59 char *ncd_map;
60 void (*ncd_fn)();
61 };
62
63 struct nisplus_search_callback_data {
64 nis_name key;
65 char *value;
66 };
67
68
69 static int
nisplus_callback(const nis_name key,const nis_object * value,voidp opaquedata)70 nisplus_callback(const nis_name key, const nis_object *value, voidp opaquedata)
71 {
72 char *kp = strnsave(ENTRY_VAL(value, 0), ENTRY_LEN(value, 0));
73 char *vp = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1));
74 struct nis_callback_data *data = (struct nis_callback_data *) opaquedata;
75
76 dlog("NISplus callback for <%s,%s>", kp, vp);
77
78 (*data->ncd_fn) (data->ncd_m, kp, vp);
79
80 /*
81 * We want more ...
82 */
83 return FALSE;
84 }
85
86
87 int
nisplus_reload(mnt_map * m,char * map,void (* fn)())88 nisplus_reload(mnt_map *m, char *map, void (*fn) ())
89 {
90 int error = 0;
91 struct nis_callback_data data;
92 nis_result *result;
93 char *org; /* if map does not have ".org_dir" then append it */
94 nis_name map_name;
95 size_t l;
96
97 org = strstr(map, NISPLUS_ORGDIR);
98 if (org == NULL)
99 org = NISPLUS_ORGDIR;
100 else
101 org = "";
102
103 /* make some room for the NIS map_name */
104 l = strlen(map) + sizeof(NISPLUS_ORGDIR);
105 map_name = xmalloc(l);
106 if (map_name == NULL) {
107 plog(XLOG_ERROR, "Unable to create map_name %s: %s",
108 map, strerror(ENOMEM));
109 return ENOMEM;
110 }
111 xsnprintf(map_name, l, "%s%s", map, org);
112
113 data.ncd_m = m;
114 data.ncd_map = map_name;
115 data.ncd_fn = fn;
116
117 dlog("NISplus reload for %s", map);
118
119 result = nis_list(map_name,
120 EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH,
121 (int (*)()) nisplus_callback,
122 &data);
123
124 /* free off the NIS map_name */
125 XFREE(map_name);
126
127 if (result->status != NIS_SUCCESS && result->status != NIS_CBRESULTS)
128 error = 1;
129
130 if (error)
131 plog(XLOG_ERROR, "error grabbing nisplus map of %s: %s",
132 map,
133 nis_sperrno(result->status));
134
135 nis_freeresult(result);
136 return error;
137 }
138
139
140 static int
nisplus_search_callback(const nis_name key,const nis_object * value,voidp opaquedata)141 nisplus_search_callback(const nis_name key, const nis_object *value, voidp opaquedata)
142 {
143 struct nisplus_search_callback_data *data = (struct nisplus_search_callback_data *) opaquedata;
144
145 dlog("NISplus search callback for <%s>", ENTRY_VAL(value, 0));
146 dlog("NISplus search callback value <%s>", ENTRY_VAL(value, 1));
147
148 data->value = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1));
149 return TRUE;
150 }
151
152
153 /*
154 * Try to locate a key using NIS+.
155 */
156 int
nisplus_search(mnt_map * m,char * map,char * key,char ** val,time_t * tp)157 nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
158 {
159 nis_result *result;
160 int error = 0;
161 struct nisplus_search_callback_data data;
162 nis_name index;
163 char *org; /* if map does not have ".org_dir" then append it */
164 size_t l;
165
166 org = strstr(map, NISPLUS_ORGDIR);
167 if (org == NULL)
168 org = NISPLUS_ORGDIR;
169 else
170 org = "";
171
172 /* make some room for the NIS index */
173 l = sizeof('[') /* for opening selection criteria */
174 + sizeof(NISPLUS_KEY)
175 + strlen(key)
176 + sizeof(']') /* for closing selection criteria */
177 + sizeof(',') /* + 1 for , separator */
178 + strlen(map)
179 + sizeof(NISPLUS_ORGDIR);
180 index = xmalloc(l);
181 if (index == NULL) {
182 plog(XLOG_ERROR,
183 "Unable to create index %s: %s",
184 map,
185 strerror(ENOMEM));
186 return ENOMEM;
187 }
188 xsnprintf(index, l, "[%s%s],%s%s", NISPLUS_KEY, key, map, org);
189
190 data.key = key;
191 data.value = NULL;
192
193 dlog("NISplus search for %s", index);
194
195 result = nis_list(index,
196 EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH,
197 (int (*)()) nisplus_search_callback,
198 &data);
199
200 /* free off the NIS index */
201 XFREE(index);
202
203 if (result == NULL) {
204 plog(XLOG_ERROR, "nisplus_search: %s: %s", map, strerror(ENOMEM));
205 return ENOMEM;
206 }
207
208 /*
209 * Do something interesting with the return code
210 */
211 switch (result->status) {
212 case NIS_SUCCESS:
213 case NIS_CBRESULTS:
214
215 if (data.value == NULL) {
216 nis_object *value = result->objects.objects_val;
217 dlog("NISplus search found <nothing>");
218 dlog("NISplus search for %s: %s(%d)",
219 map, nis_sperrno(result->status), result->status);
220
221 if (value != NULL)
222 data.value = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1));
223 }
224 *val = data.value;
225
226 if (*val) {
227 error = 0;
228 dlog("NISplus search found %s", *val);
229 } else {
230 error = ENOENT;
231 dlog("NISplus search found nothing");
232 }
233
234 *tp = 0;
235 break;
236
237 case NIS_NOSUCHNAME:
238 dlog("NISplus search returned %d", result->status);
239 error = ENOENT;
240 break;
241
242 default:
243 plog(XLOG_ERROR, "nisplus_search: %s: %s", map, nis_sperrno(result->status));
244 error = EIO;
245 break;
246 }
247 nis_freeresult(result);
248
249 return error;
250 }
251
252
253 int
nisplus_init(mnt_map * m,char * map,time_t * tp)254 nisplus_init(mnt_map *m, char *map, time_t *tp)
255 {
256 nis_result *result;
257 char *org; /* if map does not have ".org_dir" then append it */
258 nis_name map_name;
259 int error = 0;
260 size_t l;
261
262 org = strstr(map, NISPLUS_ORGDIR);
263 if (org == NULL)
264 org = NISPLUS_ORGDIR;
265 else
266 org = "";
267
268 /* make some room for the NIS map_name */
269 l = strlen(map) + sizeof(NISPLUS_ORGDIR);
270 map_name = xmalloc(l);
271 if (map_name == NULL) {
272 plog(XLOG_ERROR,
273 "Unable to create map_name %s: %s",
274 map,
275 strerror(ENOMEM));
276 return ENOMEM;
277 }
278 xsnprintf(map_name, l, "%s%s", map, org);
279
280 result = nis_lookup(map_name, (EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH));
281
282 /* free off the NIS map_name */
283 XFREE(map_name);
284
285 if (result == NULL) {
286 plog(XLOG_ERROR, "NISplus init <%s>: %s", map, strerror(ENOMEM));
287 return ENOMEM;
288 }
289
290 if (result->status != NIS_SUCCESS) {
291 dlog("NISplus init <%s>: %s (%d)",
292 map, nis_sperrno(result->status), result->status);
293
294 error = ENOENT;
295 }
296
297 *tp = 0; /* no time */
298 nis_freeresult(result);
299 return error;
300 }
301
302
303 int
nisplus_mtime(mnt_map * m,char * map,time_t * tp)304 nisplus_mtime(mnt_map *m, char *map, time_t *tp)
305 {
306 return nisplus_init(m,map, tp);
307 }
308