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