138494Sobrien/*
2174294Sobrien * Copyright (c) 1997-2006 Erez Zadok
338494Sobrien * Copyright (c) 1989 Jan-Simon Pendry
438494Sobrien * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
538494Sobrien * Copyright (c) 1989 The Regents of the University of California.
638494Sobrien * All rights reserved.
738494Sobrien *
838494Sobrien * This code is derived from software contributed to Berkeley by
938494Sobrien * Jan-Simon Pendry at Imperial College, London.
1038494Sobrien *
1138494Sobrien * Redistribution and use in source and binary forms, with or without
1238494Sobrien * modification, are permitted provided that the following conditions
1338494Sobrien * are met:
1438494Sobrien * 1. Redistributions of source code must retain the above copyright
1538494Sobrien *    notice, this list of conditions and the following disclaimer.
1638494Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1738494Sobrien *    notice, this list of conditions and the following disclaimer in the
1838494Sobrien *    documentation and/or other materials provided with the distribution.
1938494Sobrien * 3. All advertising materials mentioning features or use of this software
2042629Sobrien *    must display the following acknowledgment:
2138494Sobrien *      This product includes software developed by the University of
2238494Sobrien *      California, Berkeley and its contributors.
2338494Sobrien * 4. Neither the name of the University nor the names of its contributors
2438494Sobrien *    may be used to endorse or promote products derived from this software
2538494Sobrien *    without specific prior written permission.
2638494Sobrien *
2738494Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2838494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2938494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3038494Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3138494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3238494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3338494Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3438494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3538494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3638494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3738494Sobrien * SUCH DAMAGE.
3838494Sobrien *
3938494Sobrien *
40174294Sobrien * File: am-utils/amd/info_nisplus.c
4138494Sobrien *
4238494Sobrien */
4338494Sobrien
4438494Sobrien/*
4538494Sobrien * Get info from NIS+ (version 3) map
4638494Sobrien */
4738494Sobrien
4838494Sobrien#ifdef HAVE_CONFIG_H
4938494Sobrien# include <config.h>
5038494Sobrien#endif /* HAVE_CONFIG_H */
5138494Sobrien#include <am_defs.h>
5238494Sobrien#include <amd.h>
5338494Sobrien
5438494Sobrien#define NISPLUS_KEY "key="
5538494Sobrien#define NISPLUS_ORGDIR ".org_dir"
5638494Sobrien
5738494Sobrienstruct nis_callback_data {
5838494Sobrien  mnt_map *ncd_m;
5938494Sobrien  char *ncd_map;
6038494Sobrien  void (*ncd_fn)();
6138494Sobrien};
6238494Sobrien
6338494Sobrienstruct nisplus_search_callback_data {
6438494Sobrien  nis_name key;
6538494Sobrien  char *value;
6638494Sobrien};
6738494Sobrien
6838494Sobrien
6938494Sobrienstatic int
7038494Sobriennisplus_callback(const nis_name key, const nis_object *value, voidp opaquedata)
7138494Sobrien{
7238494Sobrien  char *kp = strnsave(ENTRY_VAL(value, 0), ENTRY_LEN(value, 0));
7338494Sobrien  char *vp = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1));
7438494Sobrien  struct nis_callback_data *data = (struct nis_callback_data *) opaquedata;
7538494Sobrien
7638494Sobrien  dlog("NISplus callback for <%s,%s>", kp, vp);
7738494Sobrien
7838494Sobrien  (*data->ncd_fn) (data->ncd_m, kp, vp);
7938494Sobrien
8038494Sobrien  /*
8138494Sobrien   * We want more ...
8238494Sobrien   */
8338494Sobrien  return FALSE;
8438494Sobrien}
8538494Sobrien
8638494Sobrien
8738494Sobrienint
8838494Sobriennisplus_reload(mnt_map *m, char *map, void (*fn) ())
8938494Sobrien{
9038494Sobrien  int error = 0;
9138494Sobrien  struct nis_callback_data data;
9238494Sobrien  nis_result *result;
9338494Sobrien  char *org;		/* if map does not have ".org_dir" then append it */
9438494Sobrien  nis_name map_name;
95174294Sobrien  size_t l;
9638494Sobrien
9738494Sobrien  org = strstr(map, NISPLUS_ORGDIR);
9838494Sobrien  if (org == NULL)
9938494Sobrien    org = NISPLUS_ORGDIR;
10038494Sobrien  else
10138494Sobrien    org = "";
10238494Sobrien
10338494Sobrien  /* make some room for the NIS map_name */
104174294Sobrien  l = strlen(map) + sizeof(NISPLUS_ORGDIR);
105174294Sobrien  map_name = xmalloc(l);
10638494Sobrien  if (map_name == NULL) {
10738494Sobrien    plog(XLOG_ERROR, "Unable to create map_name %s: %s",
10838494Sobrien	 map, strerror(ENOMEM));
10938494Sobrien    return ENOMEM;
11038494Sobrien  }
111174294Sobrien  xsnprintf(map_name, l, "%s%s", map, org);
11238494Sobrien
11338494Sobrien  data.ncd_m = m;
11438494Sobrien  data.ncd_map = map_name;
11538494Sobrien  data.ncd_fn = fn;
11638494Sobrien
11738494Sobrien  dlog("NISplus reload for %s", map);
11838494Sobrien
11938494Sobrien  result = nis_list(map_name,
12038494Sobrien		    EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH,
12138494Sobrien		    (int (*)()) nisplus_callback,
12238494Sobrien		    &data);
12338494Sobrien
12438494Sobrien  /* free off the NIS map_name */
12538494Sobrien  XFREE(map_name);
12638494Sobrien
12738494Sobrien  if (result->status != NIS_SUCCESS && result->status != NIS_CBRESULTS)
12838494Sobrien    error = 1;
12938494Sobrien
13038494Sobrien  if (error)
13138494Sobrien    plog(XLOG_ERROR, "error grabbing nisplus map of %s: %s",
13238494Sobrien	 map,
13338494Sobrien	 nis_sperrno(result->status));
13438494Sobrien
13538494Sobrien  nis_freeresult(result);
13638494Sobrien  return error;
13738494Sobrien}
13838494Sobrien
13938494Sobrien
14038494Sobrienstatic int
14138494Sobriennisplus_search_callback(const nis_name key, const nis_object *value, voidp opaquedata)
14238494Sobrien{
14338494Sobrien  struct nisplus_search_callback_data *data = (struct nisplus_search_callback_data *) opaquedata;
14438494Sobrien
14538494Sobrien  dlog("NISplus search callback for <%s>", ENTRY_VAL(value, 0));
14638494Sobrien  dlog("NISplus search callback value <%s>", ENTRY_VAL(value, 1));
14738494Sobrien
14838494Sobrien  data->value = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1));
14938494Sobrien  return TRUE;
15038494Sobrien}
15138494Sobrien
15238494Sobrien
15338494Sobrien/*
15438494Sobrien * Try to locate a key using NIS+.
15538494Sobrien */
15638494Sobrienint
15738494Sobriennisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
15838494Sobrien{
15938494Sobrien  nis_result *result;
16038494Sobrien  int error = 0;
16138494Sobrien  struct nisplus_search_callback_data data;
16238494Sobrien  nis_name index;
16338494Sobrien  char *org;		/* if map does not have ".org_dir" then append it */
164174294Sobrien  size_t l;
16538494Sobrien
16638494Sobrien  org = strstr(map, NISPLUS_ORGDIR);
16738494Sobrien  if (org == NULL)
16838494Sobrien    org = NISPLUS_ORGDIR;
16938494Sobrien  else
17038494Sobrien    org = "";
17138494Sobrien
17238494Sobrien  /* make some room for the NIS index */
173174294Sobrien  l = sizeof('[')		/* for opening selection criteria */
174174294Sobrien    + sizeof(NISPLUS_KEY)
175174294Sobrien    + strlen(key)
176174294Sobrien    + sizeof(']')		/* for closing selection criteria */
177174294Sobrien    + sizeof(',')		/* + 1 for , separator */
178174294Sobrien    + strlen(map)
179174294Sobrien    + sizeof(NISPLUS_ORGDIR);
180174294Sobrien  index = xmalloc(l);
18138494Sobrien  if (index == NULL) {
18238494Sobrien    plog(XLOG_ERROR,
18338494Sobrien	 "Unable to create index %s: %s",
18438494Sobrien	 map,
18538494Sobrien	 strerror(ENOMEM));
18638494Sobrien    return ENOMEM;
18738494Sobrien  }
188174294Sobrien  xsnprintf(index, l, "[%s%s],%s%s", NISPLUS_KEY, key, map, org);
18938494Sobrien
19038494Sobrien  data.key = key;
19138494Sobrien  data.value = NULL;
19238494Sobrien
19338494Sobrien  dlog("NISplus search for %s", index);
19438494Sobrien
19538494Sobrien  result = nis_list(index,
19638494Sobrien		    EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH,
19738494Sobrien		    (int (*)()) nisplus_search_callback,
19838494Sobrien		    &data);
19938494Sobrien
20038494Sobrien  /* free off the NIS index */
20138494Sobrien  XFREE(index);
20238494Sobrien
20338494Sobrien  if (result == NULL) {
20482794Sobrien    plog(XLOG_ERROR, "nisplus_search: %s: %s", map, strerror(ENOMEM));
20538494Sobrien    return ENOMEM;
20638494Sobrien  }
20738494Sobrien
20838494Sobrien  /*
20938494Sobrien   * Do something interesting with the return code
21038494Sobrien   */
21138494Sobrien  switch (result->status) {
21238494Sobrien  case NIS_SUCCESS:
21338494Sobrien  case NIS_CBRESULTS:
21438494Sobrien
21538494Sobrien    if (data.value == NULL) {
21638494Sobrien      nis_object *value = result->objects.objects_val;
21738494Sobrien      dlog("NISplus search found <nothing>");
21838494Sobrien      dlog("NISplus search for %s: %s(%d)",
21938494Sobrien	   map, nis_sperrno(result->status), result->status);
22038494Sobrien
22138494Sobrien      if (value != NULL)
22238494Sobrien	data.value = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1));
22338494Sobrien    }
22438494Sobrien    *val = data.value;
22538494Sobrien
22638494Sobrien    if (*val) {
22738494Sobrien      error = 0;
22838494Sobrien      dlog("NISplus search found %s", *val);
22938494Sobrien    } else {
23038494Sobrien      error = ENOENT;
23138494Sobrien      dlog("NISplus search found nothing");
23238494Sobrien    }
23338494Sobrien
23438494Sobrien    *tp = 0;
23538494Sobrien    break;
23638494Sobrien
23738494Sobrien  case NIS_NOSUCHNAME:
23838494Sobrien    dlog("NISplus search returned %d", result->status);
23938494Sobrien    error = ENOENT;
24038494Sobrien    break;
24138494Sobrien
24238494Sobrien  default:
24382794Sobrien    plog(XLOG_ERROR, "nisplus_search: %s: %s", map, nis_sperrno(result->status));
24438494Sobrien    error = EIO;
24538494Sobrien    break;
24638494Sobrien  }
24738494Sobrien  nis_freeresult(result);
24838494Sobrien
24938494Sobrien  return error;
25038494Sobrien}
25138494Sobrien
25238494Sobrien
25338494Sobrienint
25438494Sobriennisplus_init(mnt_map *m, char *map, time_t *tp)
25538494Sobrien{
25638494Sobrien  nis_result *result;
25738494Sobrien  char *org;		/* if map does not have ".org_dir" then append it */
25838494Sobrien  nis_name map_name;
25938494Sobrien  int error = 0;
260174294Sobrien  size_t l;
26138494Sobrien
26238494Sobrien  org = strstr(map, NISPLUS_ORGDIR);
26338494Sobrien  if (org == NULL)
26438494Sobrien    org = NISPLUS_ORGDIR;
26538494Sobrien  else
26638494Sobrien    org = "";
26738494Sobrien
26838494Sobrien  /* make some room for the NIS map_name */
269174294Sobrien  l = strlen(map) + sizeof(NISPLUS_ORGDIR);
270174294Sobrien  map_name = xmalloc(l);
27138494Sobrien  if (map_name == NULL) {
27238494Sobrien    plog(XLOG_ERROR,
27338494Sobrien	 "Unable to create map_name %s: %s",
27438494Sobrien	 map,
27538494Sobrien	 strerror(ENOMEM));
27638494Sobrien    return ENOMEM;
27738494Sobrien  }
278174294Sobrien  xsnprintf(map_name, l, "%s%s", map, org);
27938494Sobrien
28038494Sobrien  result = nis_lookup(map_name, (EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH));
28138494Sobrien
28238494Sobrien  /* free off the NIS map_name */
28338494Sobrien  XFREE(map_name);
28438494Sobrien
28538494Sobrien  if (result == NULL) {
28638494Sobrien    plog(XLOG_ERROR, "NISplus init <%s>: %s", map, strerror(ENOMEM));
28738494Sobrien    return ENOMEM;
28838494Sobrien  }
28938494Sobrien
29038494Sobrien  if (result->status != NIS_SUCCESS) {
29138494Sobrien    dlog("NISplus init <%s>: %s (%d)",
29238494Sobrien	 map, nis_sperrno(result->status), result->status);
29338494Sobrien
29438494Sobrien    error = ENOENT;
29538494Sobrien  }
29638494Sobrien
29738494Sobrien  *tp = 0;			/* no time */
29838494Sobrien  nis_freeresult(result);
29938494Sobrien  return error;
30038494Sobrien}
30138494Sobrien
30238494Sobrien
30338494Sobrienint
30438494Sobriennisplus_mtime(mnt_map *m, char *map, time_t *tp)
30538494Sobrien{
30638494Sobrien  return nisplus_init(m,map, tp);
30738494Sobrien}
308