xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/dict_nis.c (revision a30b880ed60a24c405edba78187a04247f4d9d33)
1 /*	$NetBSD: dict_nis.c,v 1.1.1.2 2013/01/02 18:59:12 tron Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	dict_nis 3
6 /* SUMMARY
7 /*	dictionary manager interface to NIS maps
8 /* SYNOPSIS
9 /*	#include <dict_nis.h>
10 /*
11 /*	DICT	*dict_nis_open(map, open_flags, dict_flags)
12 /*	const char *map;
13 /*	int	open_flags;
14 /*	int	dict_flags;
15 /* DESCRIPTION
16 /*	dict_nis_open() makes the specified NIS map accessible via
17 /*	the generic dictionary operations described in dict_open(3).
18 /* SEE ALSO
19 /*	dict(3) generic dictionary manager
20 /* DIAGNOSTICS
21 /*	Fatal errors: out of memory, attempt to update NIS map.
22 /* LICENSE
23 /* .ad
24 /* .fi
25 /*	The Secure Mailer license must be distributed with this software.
26 /* AUTHOR(S)
27 /*	Wietse Venema
28 /*	IBM T.J. Watson Research
29 /*	P.O. Box 704
30 /*	Yorktown Heights, NY 10598, USA
31 /*--*/
32 
33 /* System library. */
34 
35 #include "sys_defs.h"
36 #include <string.h>
37 
38 #ifdef STRCASECMP_IN_STRINGS_H
39 #include <strings.h>
40 #endif
41 
42 #ifdef HAS_NIS
43 
44 #include <rpcsvc/ypclnt.h>
45 #ifndef YPERR_BUSY
46 #define YPERR_BUSY  16
47 #endif
48 #ifndef YPERR_ACCESS
49 #define YPERR_ACCESS  15
50 #endif
51 
52 #endif
53 
54 /* Utility library. */
55 
56 #include "msg.h"
57 #include "mymalloc.h"
58 #include "vstring.h"
59 #include "stringops.h"
60 #include "dict.h"
61 #include "dict_nis.h"
62 
63 #ifdef HAS_NIS
64 
65 /* Application-specific. */
66 
67 typedef struct {
68     DICT    dict;			/* generic members */
69 } DICT_NIS;
70 
71  /*
72   * Class variables, so that multiple maps can share this info.
73   */
74 static char dict_nis_disabled[1];
75 static char *dict_nis_domain;
76 
77 /* dict_nis_init - NIS binding */
78 
dict_nis_init(void)79 static void dict_nis_init(void)
80 {
81     const char *myname = "dict_nis_init";
82 
83     if (yp_get_default_domain(&dict_nis_domain) != 0
84 	|| dict_nis_domain == 0 || *dict_nis_domain == 0
85 	|| strcasecmp(dict_nis_domain, "(none)") == 0) {
86 	dict_nis_domain = dict_nis_disabled;
87 	msg_warn("%s: NIS domain name not set - NIS lookups disabled", myname);
88     }
89     if (msg_verbose)
90 	msg_info("%s: NIS domain %s", myname, dict_nis_domain);
91 }
92 
93 /* dict_nis_strerror - map error number to string */
94 
dict_nis_strerror(int err)95 static char *dict_nis_strerror(int err)
96 {
97 
98     /*
99      * Grr. There should be a standard function for this.
100      */
101     switch (err) {
102 	case YPERR_BADARGS:
103 	return ("args to function are bad");
104     case YPERR_RPC:
105 	return ("RPC failure - domain has been unbound");
106     case YPERR_DOMAIN:
107 	return ("can't bind to server on this domain");
108     case YPERR_MAP:
109 	return ("no such map in server's domain");
110     case YPERR_KEY:
111 	return ("no such key in map");
112     case YPERR_YPERR:
113 	return ("internal yp server or client error");
114     case YPERR_RESRC:
115 	return ("resource allocation failure");
116     case YPERR_NOMORE:
117 	return ("no more records in map database");
118     case YPERR_PMAP:
119 	return ("can't communicate with portmapper");
120     case YPERR_YPBIND:
121 	return ("can't communicate with ypbind");
122     case YPERR_YPSERV:
123 	return ("can't communicate with ypserv");
124     case YPERR_NODOM:
125 	return ("local domain name not set");
126     case YPERR_BADDB:
127 	return ("yp database is bad");
128     case YPERR_VERS:
129 	return ("yp version mismatch");
130     case YPERR_ACCESS:
131 	return ("access violation");
132     case YPERR_BUSY:
133 	return ("database busy");
134     default:
135 	return ("unknown NIS lookup error");
136     }
137 }
138 
139 /* dict_nis_lookup - find table entry */
140 
dict_nis_lookup(DICT * dict,const char * key)141 static const char *dict_nis_lookup(DICT *dict, const char *key)
142 {
143     DICT_NIS *dict_nis = (DICT_NIS *) dict;
144     static char *result;
145     int     result_len;
146     int     err;
147     static VSTRING *buf;
148 
149     dict->error = 0;
150 
151     /*
152      * Sanity check.
153      */
154     if ((dict->flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0)
155 	msg_panic("dict_nis_lookup: no DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL flag");
156 
157     if (dict_nis_domain == dict_nis_disabled)
158 	return (0);
159 
160     /*
161      * Optionally fold the key.
162      */
163     if (dict->flags & DICT_FLAG_FOLD_FIX) {
164 	if (dict->fold_buf == 0)
165 	    dict->fold_buf = vstring_alloc(10);
166 	vstring_strcpy(dict->fold_buf, key);
167 	key = lowercase(vstring_str(dict->fold_buf));
168     }
169 
170     /*
171      * See if this NIS map was written with one null byte appended to key and
172      * value.
173      */
174     if (dict->flags & DICT_FLAG_TRY1NULL) {
175 	err = yp_match(dict_nis_domain, dict_nis->dict.name,
176 		       (void *) key, strlen(key) + 1,
177 		       &result, &result_len);
178 	if (err == 0) {
179 	    dict->flags &= ~DICT_FLAG_TRY0NULL;
180 	    return (result);
181 	}
182     }
183 
184     /*
185      * See if this NIS map was written with no null byte appended to key and
186      * value. This should never be the case, but better play safe.
187      */
188     if (dict->flags & DICT_FLAG_TRY0NULL) {
189 	err = yp_match(dict_nis_domain, dict_nis->dict.name,
190 		       (void *) key, strlen(key),
191 		       &result, &result_len);
192 	if (err == 0) {
193 	    dict->flags &= ~DICT_FLAG_TRY1NULL;
194 	    if (buf == 0)
195 		buf = vstring_alloc(10);
196 	    vstring_strncpy(buf, result, result_len);
197 	    return (vstring_str(buf));
198 	}
199     }
200 
201     /*
202      * When the NIS lookup fails for reasons other than "key not found", keep
203      * logging warnings, and hope that someone will eventually notice the
204      * problem and fix it.
205      */
206     if (err != YPERR_KEY) {
207 	msg_warn("lookup %s, NIS domain %s, map %s: %s",
208 		 key, dict_nis_domain, dict_nis->dict.name,
209 		 dict_nis_strerror(err));
210 	dict->error = DICT_ERR_RETRY;
211     }
212     return (0);
213 }
214 
215 /* dict_nis_close - close NIS map */
216 
dict_nis_close(DICT * dict)217 static void dict_nis_close(DICT *dict)
218 {
219     if (dict->fold_buf)
220 	vstring_free(dict->fold_buf);
221     dict_free(dict);
222 }
223 
224 /* dict_nis_open - open NIS map */
225 
dict_nis_open(const char * map,int open_flags,int dict_flags)226 DICT   *dict_nis_open(const char *map, int open_flags, int dict_flags)
227 {
228     DICT_NIS *dict_nis;
229 
230     if (open_flags != O_RDONLY)
231 	return (dict_surrogate(DICT_TYPE_NIS, map, open_flags, dict_flags,
232 			       "%s:%s map requires O_RDONLY access mode",
233 			       DICT_TYPE_NIS, map));
234 
235     dict_nis = (DICT_NIS *) dict_alloc(DICT_TYPE_NIS, map, sizeof(*dict_nis));
236     dict_nis->dict.lookup = dict_nis_lookup;
237     dict_nis->dict.close = dict_nis_close;
238     dict_nis->dict.flags = dict_flags | DICT_FLAG_FIXED;
239     if ((dict_flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0)
240 	dict_nis->dict.flags |= (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL);
241     if (dict_flags & DICT_FLAG_FOLD_FIX)
242 	dict_nis->dict.fold_buf = vstring_alloc(10);
243     if (dict_nis_domain == 0)
244 	dict_nis_init();
245     dict_nis->dict.owner.status = DICT_OWNER_TRUSTED;
246     return (DICT_DEBUG (&dict_nis->dict));
247 }
248 
249 #endif
250