237 lines
5.7 KiB
C
237 lines
5.7 KiB
C
/*++
|
|
/* NAME
|
|
/* dict_nis 3
|
|
/* SUMMARY
|
|
/* dictionary manager interface to NIS maps
|
|
/* SYNOPSIS
|
|
/* #include <dict_nis.h>
|
|
/*
|
|
/* DICT *dict_nis_open(map, dummy, dict_flags)
|
|
/* const char *map;
|
|
/* int dummy;
|
|
/* int dict_flags;
|
|
/* DESCRIPTION
|
|
/* dict_nis_open() makes the specified NIS map accessible via
|
|
/* the generic dictionary operations described in dict_open(3).
|
|
/* The \fIdummy\fR argument is not used.
|
|
/* SEE ALSO
|
|
/* dict(3) generic dictionary manager
|
|
/* DIAGNOSTICS
|
|
/* Fatal errors: out of memory, attempt to update NIS map.
|
|
/* LICENSE
|
|
/* .ad
|
|
/* .fi
|
|
/* The Secure Mailer license must be distributed with this software.
|
|
/* AUTHOR(S)
|
|
/* Wietse Venema
|
|
/* IBM T.J. Watson Research
|
|
/* P.O. Box 704
|
|
/* Yorktown Heights, NY 10598, USA
|
|
/*--*/
|
|
|
|
/* System library. */
|
|
|
|
#include "sys_defs.h"
|
|
#include <string.h>
|
|
|
|
#ifdef STRCASECMP_IN_STRINGS_H
|
|
#include <strings.h>
|
|
#endif
|
|
|
|
#ifdef HAS_NIS
|
|
|
|
#include <rpcsvc/ypclnt.h>
|
|
#ifndef YPERR_BUSY
|
|
#define YPERR_BUSY 16
|
|
#endif
|
|
#ifndef YPERR_ACCESS
|
|
#define YPERR_ACCESS 15
|
|
#endif
|
|
|
|
#endif
|
|
|
|
/* Utility library. */
|
|
|
|
#include "msg.h"
|
|
#include "mymalloc.h"
|
|
#include "vstring.h"
|
|
#include "dict.h"
|
|
#include "dict_nis.h"
|
|
|
|
#ifdef HAS_NIS
|
|
|
|
/* Application-specific. */
|
|
|
|
typedef struct {
|
|
DICT dict; /* generic members */
|
|
char *map; /* NIS map name */
|
|
} DICT_NIS;
|
|
|
|
/*
|
|
* Class variables, so that multiple maps can share this info.
|
|
*/
|
|
static char dict_nis_disabled[1];
|
|
static char *dict_nis_domain;
|
|
|
|
/* dict_nis_init - NIS binding */
|
|
|
|
static void dict_nis_init(void)
|
|
{
|
|
char *myname = "dict_nis_init";
|
|
|
|
if (yp_get_default_domain(&dict_nis_domain) != 0
|
|
|| dict_nis_domain == 0 || *dict_nis_domain == 0
|
|
|| strcasecmp(dict_nis_domain, "(none)") == 0) {
|
|
dict_nis_domain = dict_nis_disabled;
|
|
msg_warn("%s: NIS domain name not set - NIS lookups disabled", myname);
|
|
}
|
|
if (msg_verbose)
|
|
msg_info("%s: NIS domain %s", myname, dict_nis_domain);
|
|
}
|
|
|
|
/* dict_nis_strerror - map error number to string */
|
|
|
|
static char *dict_nis_strerror(int err)
|
|
{
|
|
|
|
/*
|
|
* Grr. There should be a standard function for this.
|
|
*/
|
|
switch (err) {
|
|
case YPERR_BADARGS:
|
|
return ("args to function are bad");
|
|
case YPERR_RPC:
|
|
return ("RPC failure - domain has been unbound");
|
|
case YPERR_DOMAIN:
|
|
return ("can't bind to server on this domain");
|
|
case YPERR_MAP:
|
|
return ("no such map in server's domain");
|
|
case YPERR_KEY:
|
|
return ("no such key in map");
|
|
case YPERR_YPERR:
|
|
return ("internal yp server or client error");
|
|
case YPERR_RESRC:
|
|
return ("resource allocation failure");
|
|
case YPERR_NOMORE:
|
|
return ("no more records in map database");
|
|
case YPERR_PMAP:
|
|
return ("can't communicate with portmapper");
|
|
case YPERR_YPBIND:
|
|
return ("can't communicate with ypbind");
|
|
case YPERR_YPSERV:
|
|
return ("can't communicate with ypserv");
|
|
case YPERR_NODOM:
|
|
return ("local domain name not set");
|
|
case YPERR_BADDB:
|
|
return ("yp database is bad");
|
|
case YPERR_VERS:
|
|
return ("yp version mismatch");
|
|
case YPERR_ACCESS:
|
|
return ("access violation");
|
|
case YPERR_BUSY:
|
|
return ("database busy");
|
|
default:
|
|
return ("unknown NIS lookup error");
|
|
}
|
|
}
|
|
|
|
/* dict_nis_lookup - find table entry */
|
|
|
|
static const char *dict_nis_lookup(DICT *dict, const char *key)
|
|
{
|
|
DICT_NIS *dict_nis = (DICT_NIS *) dict;
|
|
static char *result;
|
|
int result_len;
|
|
int err;
|
|
static VSTRING *buf;
|
|
|
|
dict_errno = 0;
|
|
if (dict_nis_domain == dict_nis_disabled)
|
|
return (0);
|
|
|
|
/*
|
|
* See if this NIS map was written with one null byte appended to key and
|
|
* value.
|
|
*/
|
|
if (dict->flags & DICT_FLAG_TRY1NULL) {
|
|
err = yp_match(dict_nis_domain, dict_nis->map,
|
|
(void *) key, strlen(key) + 1,
|
|
&result, &result_len);
|
|
if (err == 0) {
|
|
dict->flags &= ~DICT_FLAG_TRY0NULL;
|
|
return (result);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* See if this NIS map was written with no null byte appended to key and
|
|
* value. This should never be the case, but better play safe.
|
|
*/
|
|
if (dict->flags & DICT_FLAG_TRY0NULL) {
|
|
err = yp_match(dict_nis_domain, dict_nis->map,
|
|
(void *) key, strlen(key),
|
|
&result, &result_len);
|
|
if (err == 0) {
|
|
dict->flags &= ~DICT_FLAG_TRY1NULL;
|
|
if (buf == 0)
|
|
buf = vstring_alloc(10);
|
|
vstring_strncpy(buf, result, result_len);
|
|
return (vstring_str(buf));
|
|
}
|
|
}
|
|
|
|
/*
|
|
* When the NIS lookup fails for reasons other than "key not found", keep
|
|
* logging warnings, and hope that someone will eventually notice the
|
|
* problem and fix it.
|
|
*/
|
|
if (err != YPERR_KEY) {
|
|
msg_warn("lookup %s, NIS domain %s, map %s: %s",
|
|
key, dict_nis_domain, dict_nis->map,
|
|
dict_nis_strerror(err));
|
|
dict_errno = DICT_ERR_RETRY;
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
/* dict_nis_update - add or update table entry */
|
|
|
|
static void dict_nis_update(DICT *dict, const char *unused_name, const char *unused_value)
|
|
{
|
|
DICT_NIS *dict_nis = (DICT_NIS *) dict;
|
|
|
|
msg_fatal("dict_nis_update: attempt to update NIS map %s", dict_nis->map);
|
|
}
|
|
|
|
/* dict_nis_close - close NIS map */
|
|
|
|
static void dict_nis_close(DICT *dict)
|
|
{
|
|
DICT_NIS *dict_nis = (DICT_NIS *) dict;
|
|
|
|
myfree(dict_nis->map);
|
|
myfree((char *) dict_nis);
|
|
}
|
|
|
|
/* dict_nis_open - open NIS map */
|
|
|
|
DICT *dict_nis_open(const char *map, int unused_flags, int dict_flags)
|
|
{
|
|
DICT_NIS *dict_nis;
|
|
|
|
dict_nis = (DICT_NIS *) mymalloc(sizeof(*dict_nis));
|
|
dict_nis->dict.lookup = dict_nis_lookup;
|
|
dict_nis->dict.update = dict_nis_update;
|
|
dict_nis->dict.close = dict_nis_close;
|
|
dict_nis->dict.fd = -1;
|
|
dict_nis->map = mystrdup(map);
|
|
dict_nis->dict.flags = dict_flags | DICT_FLAG_FIXED;
|
|
if ((dict_flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0)
|
|
dict_nis->dict.flags |= (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL);
|
|
if (dict_nis_domain == 0)
|
|
dict_nis_init();
|
|
return (&dict_nis->dict);
|
|
}
|
|
|
|
#endif
|