xref: /illumos-gate/usr/src/lib/libnsl/nss/getexecattr.c (revision f67ca41a3fe371a8ac34045eb45b3c5449ee601c)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2006 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 "mt.h"
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <sys/types.h>
33 #include <nss_dbdefs.h>
34 #include <string.h>
35 #include <strings.h>
36 #include <sys/systeminfo.h>
37 #include <thread.h>
38 #include <synch.h>
39 #include <nsswitch.h>
40 #include <prof_attr.h>
41 #include <exec_attr.h>
42 
43 /* externs from libc */
44 extern void _nss_db_state_destr(struct nss_db_state *);
45 
46 /* externs from parse.c */
47 extern char *_strtok_escape(char *, char *, char **);
48 extern char *_strdup_null(char *);
49 /* extern from getprofattr.c */
50 extern int str2profattr(const char *, int, void *, char *, int);
51 
52 char *_exec_wild_id(char *, const char *);
53 execstr_t *_dup_execstr(execstr_t *);
54 void _free_execstr(execstr_t *);
55 
56 static char *_nsw_search_path = NULL;
57 
58 /*
59  * Unsynchronized, but it affects only efficiency, not correctness
60  */
61 
62 static DEFINE_NSS_DB_ROOT(exec_root);
63 static DEFINE_NSS_GETENT(context);
64 
65 void
66 _nss_initf_execattr(nss_db_params_t *p)
67 {
68 	p->name = NSS_DBNAM_EXECATTR;
69 	p->config_name    = NSS_DBNAM_PROFATTR; /* use config for "prof_attr" */
70 }
71 
72 void
73 _nsw_initf_execattr(nss_db_params_t *p)
74 {
75 	p->name = NSS_DBNAM_EXECATTR;
76 	p->flags |= NSS_USE_DEFAULT_CONFIG;
77 	p->default_config = _nsw_search_path;
78 }
79 
80 void
81 _nsw_initf_profattr(nss_db_params_t *p)
82 {
83 	p->name = NSS_DBNAM_PROFATTR;
84 	p->flags |= NSS_USE_DEFAULT_CONFIG;
85 	p->default_config = _nsw_search_path;
86 }
87 
88 /*
89  * Return values: 0 = success, 1 = parse error, 2 = erange ... The structure
90  * pointer passed in is a structure in the caller's space wherein the field
91  * pointers would be set to areas in the buffer if need be. instring and buffer
92  * should be separate areas.
93  */
94 int
95 str2execattr(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
96 {
97 	char		*last = NULL;
98 	char		*sep = KV_TOKEN_DELIMIT;
99 	execstr_t	*exec = (execstr_t *)ent;
100 
101 	if (lenstr >= buflen)
102 		return (NSS_STR_PARSE_ERANGE);
103 
104 	if (instr != buffer)
105 		(void) strncpy(buffer, instr, buflen);
106 
107 	/*
108 	 * Remove newline that nis (yp_match) puts at the
109 	 * end of the entry it retrieves from the map.
110 	 */
111 	if (buffer[lenstr] == '\n') {
112 		buffer[lenstr] = '\0';
113 	}
114 
115 	/* quick exit do not entry fill if not needed */
116 	if (ent == (void *)NULL)
117 		return (NSS_STR_PARSE_SUCCESS);
118 
119 	exec->name = _strtok_escape(buffer, sep, &last);
120 	exec->policy = _strtok_escape(NULL, sep, &last);
121 	exec->type = _strtok_escape(NULL, sep, &last);
122 	exec->res1 = _strtok_escape(NULL, sep, &last);
123 	exec->res2 = _strtok_escape(NULL, sep, &last);
124 	exec->id = _strtok_escape(NULL, sep, &last);
125 	exec->attr = _strtok_escape(NULL, sep, &last);
126 	exec->next = NULL;
127 
128 	return (NSS_STR_PARSE_SUCCESS);
129 }
130 
131 
132 void
133 _setexecattr(void)
134 {
135 	nss_setent(&exec_root, _nss_initf_execattr, &context);
136 }
137 
138 
139 void
140 _endexecattr(void)
141 {
142 	nss_endent(&exec_root, _nss_initf_execattr, &context);
143 	nss_delete(&exec_root);
144 }
145 
146 
147 execstr_t *
148 _getexecattr(execstr_t *result, char *buffer, int buflen, int *errnop)
149 {
150 	nss_status_t    res;
151 	nss_XbyY_args_t arg;
152 
153 	NSS_XbyY_INIT(&arg, result, buffer, buflen, str2execattr);
154 	res = nss_getent(&exec_root, _nss_initf_execattr, &context, &arg);
155 	arg.status = res;
156 	*errnop = arg.h_errno;
157 
158 	return ((execstr_t *)NSS_XbyY_FINI(&arg));
159 }
160 
161 execstr_t *
162 _getexecprof(char *name,
163     char *type,
164     char *id,
165     int search_flag,
166     execstr_t *result,
167     char *buffer,
168     int buflen,
169     int *errnop)
170 {
171 	int		getby_flag;
172 	char		policy_buf[BUFSIZ];
173 	const char	*empty = NULL;
174 	nss_status_t	res = NSS_NOTFOUND;
175 	nss_XbyY_args_t	arg;
176 	_priv_execattr	_priv_exec;
177 	static mutex_t	_nsw_exec_lock = DEFAULTMUTEX;
178 
179 	NSS_XbyY_INIT(&arg, result, buffer, buflen, str2execattr);
180 
181 	_priv_exec.name = (name == NULL) ? empty : (const char *)name;
182 	_priv_exec.type = (type == NULL) ? empty : (const char *)type;
183 	_priv_exec.id = (id == NULL) ? empty : (const char *)id;
184 #ifdef SI_SECPOLICY
185 	if (sysinfo(SI_SECPOLICY, policy_buf, BUFSIZ) == -1)
186 #endif	/* SI_SECPOLICY */
187 	(void) strncpy(policy_buf, DEFAULT_POLICY, BUFSIZ);
188 
189 retry_policy:
190 	_priv_exec.policy = policy_buf;
191 	_priv_exec.search_flag = search_flag;
192 	_priv_exec.head_exec = NULL;
193 	_priv_exec.prev_exec = NULL;
194 
195 	if ((name != NULL) && (id != NULL)) {
196 		getby_flag = NSS_DBOP_EXECATTR_BYNAMEID;
197 	} else if (name != NULL) {
198 		getby_flag = NSS_DBOP_EXECATTR_BYNAME;
199 	} else if (id != NULL) {
200 		getby_flag = NSS_DBOP_EXECATTR_BYID;
201 	}
202 
203 	arg.key.attrp = &(_priv_exec);
204 
205 	switch (getby_flag) {
206 	case NSS_DBOP_EXECATTR_BYID:
207 		res = nss_search(&exec_root, _nss_initf_execattr, getby_flag,
208 		    &arg);
209 		break;
210 	case NSS_DBOP_EXECATTR_BYNAMEID:
211 	case NSS_DBOP_EXECATTR_BYNAME:
212 		{
213 			char			pbuf[NSS_BUFLEN_PROFATTR];
214 			profstr_t		prof;
215 			nss_status_t		pres;
216 			nss_XbyY_args_t		parg;
217 			enum __nsw_parse_err	pserr;
218 			struct __nsw_lookup	*lookups = NULL;
219 			struct __nsw_switchconfig *conf = NULL;
220 
221 			if (conf = __nsw_getconfig(NSS_DBNAM_PROFATTR, &pserr))
222 				if ((lookups = conf->lookups) == NULL)
223 					goto out;
224 			NSS_XbyY_INIT(&parg, &prof, pbuf, NSS_BUFLEN_PROFATTR,
225 			    str2profattr);
226 			parg.key.name = name;
227 			do {
228 				/*
229 				 * search the exec_attr entry only in the scope
230 				 * that we find the profile in.
231 				 * if conf = NULL, search in local files only,
232 				 * as we were not able to read nsswitch.conf.
233 				 */
234 				DEFINE_NSS_DB_ROOT(prof_root);
235 				if (mutex_lock(&_nsw_exec_lock) != 0)
236 					goto out;
237 				_nsw_search_path = (conf == NULL)
238 				    ? NSS_FILES_ONLY
239 				    : lookups->service_name;
240 				pres = nss_search(&prof_root,
241 				    _nsw_initf_profattr,
242 				    NSS_DBOP_PROFATTR_BYNAME, &parg);
243 				if (pres == NSS_SUCCESS) {
244 					DEFINE_NSS_DB_ROOT(pexec_root);
245 					res = nss_search(&pexec_root,
246 					    _nsw_initf_execattr, getby_flag,
247 					    &arg);
248 					if (pexec_root.s != NULL)
249 						_nss_db_state_destr(
250 							pexec_root.s);
251 				}
252 				if (prof_root.s != NULL)
253 					_nss_db_state_destr(prof_root.s);
254 				(void) mutex_unlock(&_nsw_exec_lock);
255 				if ((pres == NSS_SUCCESS) || (conf == NULL))
256 					break;
257 			} while (lookups && (lookups = lookups->next));
258 		}
259 		break;
260 	default:
261 		break;
262 	}
263 
264 out:
265 	/*
266 	 * If we can't find an entry for the current default policy
267 	 * fall back to the old "suser" policy.  The nameservice is
268 	 * shared between different OS releases.
269 	 */
270 	if (res == NSS_NOTFOUND && strcmp(policy_buf, DEFAULT_POLICY) == 0) {
271 		(void) strlcpy(policy_buf, SUSER_POLICY, BUFSIZ);
272 		goto retry_policy;
273 	}
274 
275 	arg.status = res;
276 	*errnop = res;
277 	return ((execstr_t *)NSS_XbyY_FINI(&arg));
278 }
279 
280 
281 int
282 _doexeclist(nss_XbyY_args_t *argp)
283 {
284 	int		status = 1;
285 	_priv_execattr	*_priv_exec = (_priv_execattr *)(argp->key.attrp);
286 	execstr_t	*exec = (execstr_t *)((argp->buf.result));
287 
288 	if (_priv_exec->head_exec == NULL) {
289 		if (_priv_exec->head_exec = _dup_execstr(exec))
290 			_priv_exec->prev_exec = _priv_exec->head_exec;
291 		else
292 			status = 0;
293 	} else {
294 		if (_priv_exec->prev_exec->next = _dup_execstr(exec))
295 			_priv_exec->prev_exec = _priv_exec->prev_exec->next;
296 		else
297 			status = 0;
298 	}
299 	(void) memset(argp->buf.buffer, NULL, argp->buf.buflen);
300 
301 	return (status);
302 
303 }
304 
305 
306 /*
307  * Converts id to a wildcard string. e.g.:
308  *   For type = KV_COMMAND: /usr/ccs/bin/what ---> /usr/ccs/bin/\* ---> \*
309  *   For type = KV_ACTION: Dtfile;*;*;*;0 ---> *;*;*;*;*
310  *
311  * Returns NULL if id is already a wild-card.
312  */
313 char *
314 _exec_wild_id(char *id, const char *type)
315 {
316 	char	c_id = '/';
317 	char	*pchar = NULL;
318 
319 	if ((id == NULL) || (type == NULL))
320 		return (NULL);
321 
322 	if (strcmp(type, KV_ACTION) == 0) {
323 		return ((strcmp(id, KV_ACTION_WILDCARD) == 0) ? NULL :
324 		    KV_ACTION_WILDCARD);
325 	} else if (strcmp(type, KV_COMMAND) == 0) {
326 		if ((pchar = rindex(id, c_id)) == NULL)
327 			/*
328 			 * id = \*
329 			 */
330 			return (NULL);
331 		else if (*(++pchar) == KV_WILDCHAR)
332 			/*
333 			 * id = /usr/ccs/bin/\*
334 			 */
335 			return (pchar);
336 		/*
337 		 * id = /usr/ccs/bin/what
338 		 */
339 		(void) strcpy(pchar, KV_WILDCARD);
340 		return (id);
341 	}
342 
343 	return (NULL);
344 
345 }
346 
347 
348 execstr_t *
349 _dup_execstr(execstr_t *old_exec)
350 {
351 	execstr_t *new_exec = NULL;
352 
353 	if (old_exec == NULL)
354 		return (NULL);
355 	if ((new_exec = malloc(sizeof (execstr_t))) != NULL) {
356 		new_exec->name = _strdup_null(old_exec->name);
357 		new_exec->type = _strdup_null(old_exec->type);
358 		new_exec->policy = _strdup_null(old_exec->policy);
359 		new_exec->res1 = _strdup_null(old_exec->res1);
360 		new_exec->res2 = _strdup_null(old_exec->res2);
361 		new_exec->id = _strdup_null(old_exec->id);
362 		new_exec->attr = _strdup_null(old_exec->attr);
363 		new_exec->next = old_exec->next;
364 	}
365 	return (new_exec);
366 }
367 
368 void
369 _free_execstr(execstr_t *exec)
370 {
371 	if (exec != NULL) {
372 		free(exec->name);
373 		free(exec->type);
374 		free(exec->policy);
375 		free(exec->res1);
376 		free(exec->res2);
377 		free(exec->id);
378 		free(exec->attr);
379 		_free_execstr(exec->next);
380 		free(exec);
381 	}
382 }
383 
384 void
385 _exec_cleanup(nss_status_t res, nss_XbyY_args_t *argp)
386 {
387 	_priv_execattr	*_priv_exec = (_priv_execattr *)(argp->key.attrp);
388 
389 	if (res == NSS_SUCCESS) {
390 		if (_priv_exec->head_exec != NULL) {
391 			argp->buf.result = _priv_exec->head_exec;
392 			argp->returnval = argp->buf.result;
393 		}
394 	} else {
395 		if (_priv_exec->head_exec != NULL)
396 			_free_execstr(_priv_exec->head_exec);
397 		argp->returnval = NULL;
398 	}
399 }
400