info_nisplus.c revision 174294
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
57struct nis_callback_data {
58  mnt_map *ncd_m;
59  char *ncd_map;
60  void (*ncd_fn)();
61};
62
63struct nisplus_search_callback_data {
64  nis_name key;
65  char *value;
66};
67
68
69static int
70nisplus_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
87int
88nisplus_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
140static int
141nisplus_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 */
156int
157nisplus_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
253int
254nisplus_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
303int
304nisplus_mtime(mnt_map *m, char *map, time_t *tp)
305{
306  return nisplus_init(m,map, tp);
307}
308