xref: /titanic_44/usr/src/lib/nsswitch/nis/common/getexecattr.c (revision 1cb6af97c6f66f456d4f726ef056e1ebc0f73305)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 1999-2002 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #include <exec_attr.h>
33 #include <rpcsvc/ypclnt.h>
34 #include <rpcsvc/yp_prot.h>
35 #include "nis_common.h"
36 
37 
38 /* extern from nis_common.c */
39 extern void massage_netdb(const char **, int *);
40 /* externs from libnsl */
41 extern int _doexeclist(nss_XbyY_args_t *);
42 extern char *_exec_wild_id(char *, const char *);
43 extern void _exec_cleanup(nss_status_t, nss_XbyY_args_t *);
44 
45 
46 typedef struct __exec_nis_args {
47 	int		*yp_status;
48 	nss_XbyY_args_t	*argp;
49 } _exec_nis_args;
50 
51 
52 /*
53  * check_match: returns 1 if -  matching entry found and no more entries needed,
54  *				or, entry cannot be found because of error;
55  *		returns 0 if -  no matching entry found, or,
56  *				matching entry found and next match needed.
57  */
58 static int
59 check_match(nss_XbyY_args_t *argp, int check_policy)
60 {
61 	execstr_t	*exec = (execstr_t *)(argp->returnval);
62 	_priv_execattr	*_priv_exec = (_priv_execattr *)(argp->key.attrp);
63 	const char	*name = _priv_exec->name;
64 	const char	*type = _priv_exec->type;
65 	const char	*id = _priv_exec->id;
66 	const char	*policy = _priv_exec->policy;
67 
68 	if (name && id) {
69 		/*
70 		 * NSS_DBOP_EXECATTR_BYNAMEID searched for name and id in
71 		 * _exec_nis_lookup already.
72 		 * If we're talking to pre-Solaris9 nis servers, check policy,
73 		 * as policy was not a searchable column then.
74 		 */
75 		if ((check_policy && policy &&
76 		    (strcmp(policy, exec->policy) != 0)) ||
77 		    (type && (strcmp(type, exec->type) != 0))) {
78 			return (0);
79 		}
80 	} else if ((policy && exec->policy &&
81 	    (strcmp(policy, exec->policy) != 0)) ||
82 	    (name && exec->name && (strcmp(name, exec->name) != 0)) ||
83 	    (type && exec->type && (strcmp(type, exec->type) != 0)) ||
84 	    (id && exec->id && (strcmp(id, exec->id) != 0))) {
85 		return (0);
86 	}
87 
88 	return (1);
89 }
90 
91 
92 static  nss_status_t
93 _exec_nis_parse(const char *instr,
94     int instr_len,
95     nss_XbyY_args_t *argp,
96     int check_policy)
97 {
98 	int		parse_stat;
99 	nss_status_t	res;
100 	_priv_execattr	*_priv_exec = (_priv_execattr *)(argp->key.attrp);
101 
102 	parse_stat = (*argp->str2ent)(instr, instr_len, argp->buf.result,
103 	    argp->buf.buffer, argp->buf.buflen);
104 	switch (parse_stat) {
105 	case NSS_STR_PARSE_SUCCESS:
106 		argp->returnval = argp->buf.result;
107 		if (check_match(argp, check_policy)) {
108 			res = NSS_SUCCESS;
109 			if (_priv_exec->search_flag == GET_ALL) {
110 				if (_doexeclist(argp) == 0) {
111 					res = NSS_UNAVAIL;
112 				}
113 			}
114 		} else {
115 			res = NSS_NOTFOUND;
116 		}
117 		break;
118 	case NSS_STR_PARSE_ERANGE:
119 		argp->erange = 1;
120 		res = NSS_NOTFOUND;
121 		break;
122 	default:
123 		res = NSS_UNAVAIL;
124 		break;
125 	}
126 
127 	return (res);
128 }
129 
130 /*
131  * This is the callback for yp_all. It returns 0 to indicate that it wants to
132  * be called again for further key-value pairs, or returns non-zero to stop the
133  * flow of key-value pairs. If it returns a non-zero value, it is not called
134  * again. The functional value of yp_all is then 0.
135  */
136 static int
137 _exec_nis_cb(int instatus,
138     char *inkey,
139     int inkeylen,
140     char *inval,
141     int invallen,
142     void *indata)
143 {
144 	int		check_policy = 1; /* always check policy for yp_all */
145 	int		stop_cb;
146 	const char	*filter;
147 	char		*key = NULL;
148 	nss_status_t	res;
149 	_exec_nis_args	*eargp = (_exec_nis_args *)indata;
150 	nss_XbyY_args_t	*argp = eargp->argp;
151 	_priv_execattr	*_priv_exec = (_priv_execattr *)(argp->key.attrp);
152 
153 	if (instatus != YP_TRUE) {
154 		*(eargp->yp_status) = YPERR_YPERR;
155 		return (0);	/* yp_all may decide otherwise... */
156 	}
157 
158 	filter = (_priv_exec->name) ? _priv_exec->name : _priv_exec->id;
159 
160 	/*
161 	 * yp_all does not null terminate the entry it retrieves from the
162 	 * map, unlike yp_match. so we do it explicitly here.
163 	 */
164 	inval[invallen] = '\0';
165 
166 	/*
167 	 * Optimization:  if the entry doesn't contain the filter string then
168 	 * it can't be the entry we want, so don't bother looking more closely
169 	 * at it.
170 	 */
171 	if ((_priv_exec->policy &&
172 	    (strstr(inval, _priv_exec->policy) == NULL)) ||
173 	    (strstr(inval, filter) == NULL)) {
174 		*(eargp->yp_status) = YPERR_KEY;
175 		return (0);
176 	}
177 
178 	res = _exec_nis_parse(inval, invallen, argp, check_policy);
179 
180 	switch (res) {
181 	case NSS_SUCCESS:
182 		*(eargp->yp_status) = 0;
183 		stop_cb = (_priv_exec->search_flag == GET_ONE);
184 		break;
185 	case NSS_UNAVAIL:
186 		*(eargp->yp_status) = YPERR_KEY;
187 		stop_cb = 1;
188 		break;
189 	default:
190 		*(eargp->yp_status) = YPERR_YPERR;
191 		stop_cb = 0;
192 		break;
193 	}
194 
195 	return (stop_cb);
196 }
197 
198 static nss_status_t
199 _exec_nis_lookup(nis_backend_ptr_t be, nss_XbyY_args_t *argp, int getby_flag)
200 {
201 	int		ypstatus;
202 	nss_status_t	res = NSS_SUCCESS;
203 	nss_status_t	ypres;
204 	_priv_execattr	*_priv_exec = (_priv_execattr *)(argp->key.attrp);
205 
206 	if (getby_flag == NSS_DBOP_EXECATTR_BYNAMEID) {
207 		int		check_policy = 0;
208 		int		vallen;
209 		int		parse_stat;
210 		char		*val;
211 		char		key[MAX_INPUT];
212 
213 		/*
214 		 * Try using policy as part of search key. If that fails,
215 		 * (it will, in case of pre-Solaris9 nis server where policy
216 		 * was not searchable), try again without using policy.
217 		 */
218 		if (snprintf(key, MAX_INPUT, "%s%s%s%s%s", _priv_exec->name,
219 		    KV_TOKEN_DELIMIT, _priv_exec->policy, KV_TOKEN_DELIMIT,
220 		    _priv_exec->id) >= MAX_INPUT)
221 			return (NSS_NOTFOUND);
222 		do {
223 			ypres = _nss_nis_ypmatch(be->domain, NIS_MAP_EXECATTR,
224 			    key, &val, &vallen, &ypstatus);
225 			if ((check_policy == 0) && (ypstatus == YPERR_KEY)) {
226 				(void) snprintf(key, MAX_INPUT, "%s%s%s",
227 				    _priv_exec->name, KV_TOKEN_DELIMIT,
228 				    _priv_exec->id);
229 				check_policy = 1;
230 				continue;
231 			} else if (ypres != NSS_SUCCESS) {
232 				res = ypres;
233 				break;
234 			} else {
235 				massage_netdb((const char **)&val, &vallen);
236 				res = _exec_nis_parse((const char *)val,
237 				    vallen, argp, check_policy);
238 				break;
239 			}
240 		} while (res == NSS_SUCCESS);
241 	} else {
242 		int			ypstat = YPERR_YPERR;
243 		struct ypall_callback	cback;
244 		_exec_nis_args		eargs;
245 
246 		eargs.yp_status = &ypstat;
247 		eargs.argp = argp;
248 
249 		cback.foreach = _exec_nis_cb;
250 		cback.data = (void *)&eargs;
251 
252 		/*
253 		 * Instead of calling yp_all() doing hard lookup, we use
254 		 * the alternative function, __yp_all_cflookup(), to
255 		 * perform soft lookup when binding to nis servers with
256 		 * time-out control. Other than that, these two functions
257 		 * do exactly the same thing.
258 		 */
259 		ypstatus = __yp_all_cflookup((char *)(be->domain),
260 			(char *)(be->enum_map), &cback, 0);
261 
262 		/*
263 		 * For GET_ALL, check if we found anything at all.
264 		 */
265 		if (_priv_exec->head_exec != NULL)
266 			return (NSS_SUCCESS);
267 
268 		switch (ypstat) {
269 		case 0:
270 			res = NSS_SUCCESS;
271 			break;
272 		case YPERR_BUSY:
273 			res = NSS_TRYAGAIN;
274 			break;
275 		default:
276 			res = NSS_UNAVAIL;
277 			break;
278 		}
279 
280 	}
281 
282 	return (res);
283 }
284 
285 /*
286  * If search for exact match for id failed, get_wild checks if we have
287  * a wild-card entry for that id.
288  */
289 static  nss_status_t
290 get_wild(nis_backend_ptr_t be, nss_XbyY_args_t *argp, int getby_flag)
291 {
292 	char		*orig_id = NULL;
293 	char		*old_id = NULL;
294 	char		*wild_id = NULL;
295 	nss_status_t	res = NSS_NOTFOUND;
296 	_priv_execattr	*_priv_exec = (_priv_execattr *)(argp->key.attrp);
297 
298 	orig_id = strdup(_priv_exec->id);
299 	old_id = strdup(_priv_exec->id);
300 	wild_id = old_id;
301 	while ((wild_id = _exec_wild_id(wild_id, _priv_exec->type)) != NULL) {
302 		_priv_exec->id = wild_id;
303 		res = _exec_nis_lookup(be, argp, getby_flag);
304 		if (res == NSS_SUCCESS)
305 			break;
306 	}
307 	_priv_exec->id = orig_id;
308 	if (old_id)
309 		free(old_id);
310 
311 	return (res);
312 }
313 
314 
315 static  nss_status_t
316 getbynam(nis_backend_ptr_t be, void *a)
317 {
318 	nss_status_t	res;
319 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
320 
321 	res = _exec_nis_lookup(be, argp, NSS_DBOP_EXECATTR_BYNAME);
322 
323 	_exec_cleanup(res, argp);
324 
325 	return (res);
326 }
327 
328 static  nss_status_t
329 getbyid(nis_backend_ptr_t be, void *a)
330 {
331 	nss_status_t	res;
332 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
333 	_priv_execattr	*_priv_exec = (_priv_execattr *)(argp->key.attrp);
334 
335 	res = _exec_nis_lookup(be, argp, NSS_DBOP_EXECATTR_BYID);
336 
337 	if (res != NSS_SUCCESS)
338 		res = get_wild(be, argp, NSS_DBOP_EXECATTR_BYID);
339 
340 	_exec_cleanup(res, argp);
341 
342 	return (res);
343 }
344 
345 
346 static  nss_status_t
347 getbynameid(nis_backend_ptr_t be, void *a)
348 {
349 	nss_status_t	res;
350 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
351 	_priv_execattr	*_priv_exec = (_priv_execattr *)(argp->key.attrp);
352 
353 	res = _exec_nis_lookup(be, argp, NSS_DBOP_EXECATTR_BYNAMEID);
354 
355 	if (res != NSS_SUCCESS)
356 		res = get_wild(be, argp, NSS_DBOP_EXECATTR_BYNAMEID);
357 
358 	_exec_cleanup(res, argp);
359 
360 	return (res);
361 }
362 
363 
364 static nis_backend_op_t execattr_ops[] = {
365 	_nss_nis_destr,
366 	_nss_nis_endent,
367 	_nss_nis_setent,
368 	_nss_nis_getent_netdb,
369 	getbynam,
370 	getbyid,
371 	getbynameid
372 };
373 
374 nss_backend_t *
375 _nss_nis_exec_attr_constr(const char *dummy1,
376     const char *dummy2,
377     const char *dummy3,
378     const char *dummy4,
379     const char *dummy5,
380     const char *dummy6,
381     const char *dummy7)
382 {
383 	return (_nss_nis_constr(execattr_ops,
384 		sizeof (execattr_ops)/sizeof (execattr_ops[0]),
385 		NIS_MAP_EXECATTR));
386 }
387