xref: /openbsd-src/usr.sbin/amd/amd/info_nis.c (revision 26d0c865b2e28f6e7d4c71090534c37cab976ea0)
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