1 /*
2 * Copyright (c) 1989 Jan-Simon Pendry
3 * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Jan-Simon Pendry at Imperial College, London.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * from: @(#)info_nis.c 8.1 (Berkeley) 6/6/93
35 * $Id: info_nis.c,v 1.13 2014/10/26 03:28:41 guenther Exp $
36 */
37
38 /*
39 * Get info from NIS map
40 */
41
42 #include "am.h"
43
44 #include <unistd.h>
45
46 #include <rpcsvc/yp_prot.h>
47 #include <rpcsvc/ypclnt.h>
48 #include <time.h>
49
50 /*
51 * Sun's NIS+ server in NIS compat mode does not have yp_order()
52 */
53 static int has_yp_order = FALSE;
54
55 /*
56 * Figure out the nis domain name
57 */
58 static int
determine_nis_domain(void)59 determine_nis_domain(void)
60 {
61 static int nis_not_running = 0;
62
63 char default_domain[YPMAXDOMAIN];
64
65 if (nis_not_running)
66 return ENOENT;
67
68 if (getdomainname(default_domain, sizeof(default_domain)) < 0) {
69 nis_not_running = 1;
70 plog(XLOG_ERROR, "getdomainname: %m");
71 return EIO;
72 }
73
74 if (!*default_domain) {
75 nis_not_running = 1;
76 plog(XLOG_INFO, "NIS domain name is not set. NIS ignored.");
77 return ENOENT;
78 }
79
80 domain = strdup(default_domain);
81
82 return 0;
83 }
84
85
86 struct nis_callback_data {
87 mnt_map *ncd_m;
88 char *ncd_map;
89 void (*ncd_fn)(mnt_map *, char *, char *);
90 };
91
92 /*
93 * Callback from yp_all
94 */
95 static int
callback(unsigned long status,char * key,int kl,char * val,int vl,void * arg)96 callback(unsigned long status, char *key, int kl, char *val, int vl, void *arg)
97 {
98 struct nis_callback_data *data = arg;
99
100 if (status == YP_TRUE) {
101 /*
102 * Add to list of maps
103 */
104 char *kp = strnsave(key, kl);
105 char *vp = strnsave(val, vl);
106
107 (*data->ncd_fn)(data->ncd_m, kp, vp);
108
109 /*
110 * We want more ...
111 */
112 return FALSE;
113 } else {
114 /*
115 * NOMORE means end of map - otherwise log error
116 */
117 if (status != YP_NOMORE) {
118 /*
119 * Check what went wrong
120 */
121 int e = ypprot_err(status);
122
123 #ifdef DEBUG
124 plog(XLOG_ERROR, "yp enumeration of %s: %s, status=%d, e=%d",
125 data->ncd_map, yperr_string(e), status, e);
126 #else
127 plog(XLOG_ERROR, "yp enumeration of %s: %s",
128 data->ncd_map, yperr_string(e));
129 #endif
130 }
131 return TRUE;
132 }
133 }
134
135 int
nis_reload(mnt_map * m,char * map,void (* fn)(mnt_map *,char *,char *))136 nis_reload(mnt_map *m, char *map, void (*fn)(mnt_map *, char *, char *))
137 {
138 struct ypall_callback cbinfo;
139 int error;
140 struct nis_callback_data data;
141
142 if (!domain) {
143 error = determine_nis_domain();
144 if (error)
145 return error;
146 }
147
148 data.ncd_m = m;
149 data.ncd_map = map;
150 data.ncd_fn = fn;
151 cbinfo.data = (void *)&data;
152 cbinfo.foreach = &callback;
153
154 error = yp_all(domain, map, &cbinfo);
155
156 if (error)
157 plog(XLOG_ERROR, "error grabbing nis map of %s: %s",
158 map, yperr_string(ypprot_err(error)));
159
160 return error;
161 }
162
163 /*
164 * Try to locate a key using NIS.
165 */
166 int
nis_search(mnt_map * m,char * map,char * key,char ** val,time_t * tp)167 nis_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
168 {
169 int outlen;
170 int order;
171 int res;
172
173 /*
174 * Make sure domain initialised
175 */
176 if (has_yp_order) {
177 /* check if map has changed */
178 if (yp_order(domain, map, &order))
179 return EIO;
180 if ((time_t) order > *tp) {
181 *tp = (time_t) order;
182 return -1;
183 }
184 } else {
185 /*
186 * NIS+ server without yp_order
187 * Check if timeout has expired to invalidate the cache
188 */
189 order = time(NULL);
190 if ((time_t)order - *tp > am_timeo) {
191 *tp = (time_t)order;
192 return(-1);
193 }
194 }
195
196
197 if (has_yp_order) {
198 /*
199 * Check if map has changed
200 */
201 if (yp_order(domain, map, &order))
202 return EIO;
203 if ((time_t) order > *tp) {
204 *tp = (time_t) order;
205 return -1;
206 }
207 } else {
208 /*
209 * NIS+ server without yp_order
210 * Check if timeout has expired to invalidate the cache
211 */
212 order = time(NULL);
213 if ((time_t)order - *tp > am_timeo) {
214 *tp = (time_t)order;
215 return(-1);
216 }
217 }
218
219 /*
220 * Lookup key
221 */
222 res = yp_match(domain, map, key, strlen(key), val, &outlen);
223
224 /*
225 * Do something interesting with the return code
226 */
227 switch (res) {
228 case 0:
229 return 0;
230
231 case YPERR_KEY:
232 return ENOENT;
233
234 default:
235 plog(XLOG_ERROR, "%s: %s", map, yperr_string(res));
236 return EIO;
237 }
238 }
239
240 int
nis_init(char * map,time_t * tp)241 nis_init(char *map, time_t *tp)
242 {
243 int order;
244 int yp_order_result;
245 char *master;
246
247 if (!domain) {
248 int error = determine_nis_domain();
249
250 if (error)
251 return error;
252 }
253
254 /*
255 * To see if the map exists, try to find
256 * a master for it.
257 */
258 yp_order_result = yp_order(domain, map, &order);
259 switch (yp_order_result) {
260 case 0:
261 has_yp_order = TRUE;
262 *tp = (time_t)order;
263 #ifdef DEBUG
264 dlog("NIS master for %s@%s has order %d", map, domain, order);
265 #endif
266 break;
267 case YPERR_YPERR:
268 plog(XLOG_ERROR, "%s: %s", map, "NIS+ server");
269 /* NIS+ server found ! */
270 has_yp_order = FALSE;
271
272 /* try yp_master() instead */
273 if (yp_master(domain, map, &master))
274 return ENOENT;
275 else
276 *tp = time(NULL); /* Use fake timestamps */
277 break;
278 default:
279 return ENOENT;
280 }
281 return 0;
282 }
283