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 2004 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 <sys/types.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <nss_dbdefs.h>
34 #include <deflt.h>
35 #include <exec_attr.h>
36 #include <user_attr.h>
37 #include <auth_attr.h>
38 #include <prof_attr.h>
39 #include <getxby_door.h>
40 #include <sys/mman.h>
41 
42 
43 /* Externs from libnsl */
44 extern execstr_t *_getexecattr(execstr_t *, char *, int, int *);
45 extern void _setexecattr(void);
46 extern void _endexecattr(void);
47 extern execstr_t *_getexecprof(const char *, const char *, const char *, int,
48     execstr_t *, char *, int, int *);
49 extern userstr_t *_getusernam(const char *, userstr_t *, char *, int, int *);
50 extern userstr_t *_getuserattr(userstr_t *, char *, int, int *);
51 extern char *_strtok_escape(char *, char *, char **);
52 extern char *_strdup_null(char *);
53 
54 static execattr_t *userprof(const char *, const char *, const char *, int);
55 static execattr_t *get_tail(execattr_t *);
56 static execattr_t *execstr2attr(execstr_t *);
57 static execstr_t *process_getexec(execstr_t *, char *, int, nsc_data_t *);
58 
59 execattr_t *
60 getexecattr()
61 {
62 	int		err = 0;
63 	char		buf[NSS_BUFLEN_EXECATTR];
64 	execstr_t	exec;
65 	execstr_t	*tmp;
66 
67 	tmp = _getexecattr(&exec, buf, NSS_BUFLEN_EXECATTR, &err);
68 
69 	return (execstr2attr(tmp));
70 }
71 
72 
73 execattr_t *
74 getexecprof(const char *name, const char *type, const char *id, int search_flag)
75 {
76 	int		len_unique;
77 	int		err = 0;
78 	int		ndata = 0;
79 	int		adata = 0;
80 	char		unique[NSS_BUFLEN_EXECATTR];
81 	char		buf[NSS_BUFLEN_EXECATTR];
82 	execattr_t	*head = (execattr_t *)NULL;
83 	execattr_t	*prev = (execattr_t *)NULL;
84 	execstr_t	exec;
85 	execstr_t	*tmp;
86 	execstr_t	*resptr = (execstr_t *)NULL;
87 	nsc_data_t	*sptr = (nsc_data_t *)NULL;
88 	union {
89 		nsc_data_t 	s_d;
90 		char		s_b[NSS_BUFLEN_EXECATTR];
91 	} space;
92 
93 	(void) memset(unique, 0, NSS_BUFLEN_EXECATTR);
94 	(void) memset(&exec, 0, sizeof (execstr_t));
95 	(void) memset(&space, 0, sizeof (space));
96 
97 	if ((search_flag != GET_ONE) && (search_flag != GET_ALL)) {
98 		return ((execattr_t *)NULL);
99 	}
100 
101 	if ((name == NULL) && (type == NULL) && (id == NULL)) {
102 		setexecattr();
103 		switch (search_flag) {
104 		case GET_ONE:
105 			head = getexecattr();
106 			break;
107 		case GET_ALL:
108 			head = getexecattr();
109 			prev = head;
110 			while (prev != NULL) {
111 				prev->next = getexecattr();
112 				prev = prev->next;
113 			};
114 			break;
115 		default:
116 			head = (execattr_t *)NULL;
117 			break;
118 		}
119 		endexecattr();
120 		return (head);
121 	}
122 
123 #ifdef PIC
124 	/*
125 	 * If the search criteria is completely specified
126 	 * and we only want a single entry,
127 	 * then attempt to look up the entry using the nscd.
128 	 * Only commands are cached.
129 	 */
130 	if (name && type && (strcmp(type, KV_COMMAND) == 0) && id &&
131 	    (search_flag == GET_ONE)) {
132 		if (snprintf(unique, NSS_BUFLEN_EXECATTR, "%s:%s:%s",
133 		    name, type, id) >= NSS_BUFLEN_EXECATTR) {
134 			errno = ERANGE;
135 			return ((execattr_t *)NULL);
136 		}
137 		len_unique = strlen(unique);
138 		if ((len_unique >= (sizeof (space) - sizeof (nsc_data_t)))) {
139 			errno = ERANGE;
140 			return ((execattr_t *)NULL);
141 		}
142 		ndata = sizeof (space);
143 		adata = len_unique + sizeof (nsc_call_t) + 1;
144 		space.s_d.nsc_call.nsc_callnumber = GETEXECID;
145 		(void) strcpy(space.s_d.nsc_call.nsc_u.name, unique);
146 		sptr = &space.s_d;
147 
148 		switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) {
149 		case SUCCESS:	/* positive cache hit */
150 			break;
151 		case NOTFOUND:	/* negative cache hit */
152 			return ((execattr_t *)NULL);
153 		default:
154 			resptr = _getexecprof(name, type, id, search_flag,
155 			    &exec, buf, NSS_BUFLEN_EXECATTR, &err);
156 			return (execstr2attr(resptr));
157 		}
158 		resptr = process_getexec(&exec, buf, NSS_BUFLEN_EXECATTR,
159 		    sptr);
160 
161 		/*
162 		 * check if doors reallocated the memory underneath us
163 		 * if they did munmap it or suffer a memory leak
164 		 */
165 		if (sptr != &space.s_d)
166 			(void) munmap((void *)sptr, ndata);
167 
168 		return (execstr2attr(resptr));
169 	} /* end if (name && type && id && search_flag == GET_ONE) */
170 #endif	/* PIC */
171 
172 	tmp = _getexecprof(name,
173 	    type,
174 	    id,
175 	    search_flag,
176 	    &exec,
177 	    buf,
178 	    NSS_BUFLEN_EXECATTR,
179 	    &err);
180 
181 	return (execstr2attr(tmp));
182 }
183 
184 
185 execattr_t *
186 getexecuser(const char *username, const char *type, const char *id,
187     int search_flag)
188 {
189 	int		err = 0;
190 	char		buf[NSS_BUFLEN_USERATTR];
191 	userstr_t	user;
192 	userstr_t	*utmp;
193 	execattr_t	*head = (execattr_t *)NULL;
194 	execattr_t	*prev = (execattr_t *)NULL;
195 	execattr_t	*new = (execattr_t *)NULL;
196 
197 	if ((search_flag != GET_ONE) && (search_flag != GET_ALL)) {
198 		return ((execattr_t *)NULL);
199 	}
200 
201 	if (username == NULL) {
202 		setuserattr();
203 		/* avoid userstr2attr mallocs by calling libnsl directly */
204 		utmp = _getuserattr(&user, buf, NSS_BUFLEN_USERATTR, &err);
205 		if (utmp == NULL) {
206 			return (head);
207 		}
208 		switch (search_flag) {
209 		case GET_ONE:
210 			head = userprof((const char *)(utmp->name), type, id,
211 			    search_flag);
212 			break;
213 		case GET_ALL:
214 			head = userprof((const char *)(utmp->name), type, id,
215 			    search_flag);
216 			if (head != NULL) {
217 				prev = get_tail(head);
218 			}
219 			while ((utmp = _getuserattr(&user,
220 				    buf, NSS_BUFLEN_USERATTR, &err)) != NULL) {
221 				if ((new =
222 				    userprof((const char *)(utmp->name),
223 				    type, id, search_flag)) != NULL) {
224 					if (prev != NULL) {
225 						prev->next = new;
226 						prev = get_tail(prev->next);
227 					} else {
228 						head = new;
229 						prev = get_tail(head);
230 					}
231 				}
232 			}
233 			break;
234 		default:
235 			head = (execattr_t *)NULL;
236 			break;
237 		}
238 		enduserattr();
239 	} else {
240 		head = userprof(username, type, id, search_flag);
241 	}
242 
243 	return (head);
244 }
245 
246 
247 execattr_t *
248 match_execattr(execattr_t *exec, const char *profname, const char *type,
249     const char *id)
250 {
251 	execattr_t	*execp = (execattr_t *)NULL;
252 
253 	for (execp = exec; execp != NULL; execp = execp->next) {
254 		if ((profname && execp->name &&
255 		    (strcmp(profname, execp->name) != 0)) ||
256 		    (type && execp->type && (strcmp(type, execp->type) != 0)) ||
257 		    (id && execp->id && (strcmp(id, execp->id) != 0)))
258 			continue;
259 	}
260 
261 	return (execp);
262 }
263 
264 
265 void
266 setexecattr()
267 {
268 	_setexecattr();
269 }
270 
271 
272 void
273 endexecattr()
274 {
275 	_endexecattr();
276 }
277 
278 
279 void
280 free_execattr(execattr_t *exec)
281 {
282 	if (exec != (execattr_t *)NULL) {
283 		free(exec->name);
284 		free(exec->type);
285 		free(exec->policy);
286 		free(exec->res1);
287 		free(exec->res2);
288 		free(exec->id);
289 		_kva_free(exec->attr);
290 		free_execattr(exec->next);
291 		free(exec);
292 	}
293 }
294 
295 
296 static execattr_t *
297 userprof(const char *username, const char *type, const char *id,
298     int search_flag)
299 {
300 
301 	int		err = 0;
302 	char		*last;
303 	char		*sep = ",";
304 	char		*proflist = (char *)NULL;
305 	char		*profname = (char *)NULL;
306 	char		buf[NSS_BUFLEN_USERATTR];
307 	char		pwdb[NSS_BUFLEN_PASSWD];
308 	kva_t		*user_attr;
309 	userstr_t	user;
310 	userstr_t	*utmp;
311 	execattr_t	*exec;
312 	execattr_t	*head = (execattr_t *)NULL;
313 	execattr_t	*prev = (execattr_t *)NULL;
314 	struct passwd	pwd;
315 
316 	char		*profArray[MAXPROFS];
317 	int		profcnt = 0;
318 	int		i;
319 
320 	/*
321 	 * Check if specified username is valid user
322 	 */
323 	if (getpwnam_r(username, &pwd, pwdb, sizeof (pwdb)) == NULL) {
324 		return (head);
325 	}
326 
327 	utmp = _getusernam(username, &user, buf, NSS_BUFLEN_USERATTR, &err);
328 	if (utmp != NULL) {
329 		proflist = NULL;
330 		user_attr = _str2kva(user.attr, KV_ASSIGN, KV_DELIMITER);
331 		if ((proflist = kva_match(user_attr, "profiles")) != NULL) {
332 			/* Get the list of profiles for this user */
333 			for (profname = _strtok_escape(proflist, sep, &last);
334 			    profname != NULL;
335 			    profname = _strtok_escape(NULL, sep, &last)) {
336 				getproflist(profname, profArray, &profcnt);
337 			}
338 		}
339 	}
340 
341 	/* Get the list of default profiles */
342 	if (defopen(AUTH_POLICY) == NULL) {
343 		proflist = defread(DEF_PROF);
344 		(void) defopen(NULL);
345 	}
346 	if (proflist != NULL) {
347 		for (profname = _strtok_escape(proflist, sep, &last);
348 		    profname != NULL;
349 		    profname = _strtok_escape(NULL, sep, &last)) {
350 			getproflist(profname, profArray, &profcnt);
351 		}
352 	}
353 
354 	if (profcnt == 0) {
355 		return (head);
356 	}
357 
358 	/* Get execs from the list of profiles */
359 	for (i = 0; i < profcnt; i++) {
360 		profname = profArray[i];
361 		if ((exec = getexecprof(profname, type, id, search_flag)) !=
362 		    NULL) {
363 			if (search_flag == GET_ONE) {
364 				head = exec;
365 				break;
366 			} else if (search_flag == GET_ALL) {
367 				if (head == NULL) {
368 					head = exec;
369 					prev = get_tail(head);
370 				} else {
371 					prev->next = exec;
372 					prev = get_tail(exec);
373 				}
374 			}
375 		}
376 	}
377 	free_proflist(profArray, profcnt);
378 	return (head);
379 }
380 
381 
382 static execattr_t *
383 get_tail(execattr_t *exec)
384 {
385 	execattr_t *i_exec = (execattr_t *)NULL;
386 	execattr_t *j_exec = (execattr_t *)NULL;
387 
388 	if (exec != NULL) {
389 		if (exec->next == NULL) {
390 			j_exec = exec;
391 		} else {
392 			for (i_exec = exec->next; i_exec != NULL;
393 			    i_exec = i_exec->next) {
394 				j_exec = i_exec;
395 			}
396 		}
397 	}
398 
399 	return (j_exec);
400 }
401 
402 
403 static execattr_t *
404 execstr2attr(execstr_t *es)
405 {
406 	execattr_t	*newexec;
407 
408 	if (es == NULL) {
409 		return ((execattr_t *)NULL);
410 	}
411 	if ((newexec = (execattr_t *)malloc(sizeof (execattr_t))) == NULL) {
412 		return ((execattr_t *)NULL);
413 	}
414 
415 	newexec->name = _do_unescape(es->name);
416 	newexec->policy = _do_unescape(es->policy);
417 	newexec->type = _do_unescape(es->type);
418 	newexec->res1 =  _do_unescape(es->res1);
419 	newexec->res2 = _do_unescape(es->res2);
420 	newexec->id = _do_unescape(es->id);
421 	newexec->attr = _str2kva(es->attr, KV_ASSIGN, KV_DELIMITER);
422 	if (es->next) {
423 		newexec->next = execstr2attr((execstr_t *)(es->next));
424 	} else {
425 		newexec->next = (execattr_t *)NULL;
426 	}
427 	return (newexec);
428 }
429 
430 
431 static execstr_t *
432 process_getexec(
433 	execstr_t *result,
434 	char *buffer,
435 	int buflen,
436 	nsc_data_t *sptr)
437 {
438 	char *fixed;
439 #ifdef	_LP64
440 	execstr_t exec64;
441 
442 	fixed = (char *)(((uintptr_t)buffer + 7) & ~7);
443 #else
444 	fixed = (char *)(((uintptr_t)buffer + 3) & ~3);
445 #endif
446 	buflen -= fixed - buffer;
447 	buffer = fixed;
448 
449 	if (sptr->nsc_ret.nsc_return_code != SUCCESS)
450 		return ((execstr_t *)NULL);
451 
452 #ifdef	_LP64
453 	if (sptr->nsc_ret.nsc_bufferbytesused - (int)sizeof (execstr32_t)
454 	    > buflen)
455 #else
456 	if (sptr->nsc_ret.nsc_bufferbytesused - (int)sizeof (execstr_t)
457 	    > buflen)
458 #endif
459 	{
460 		errno = ERANGE;
461 		return ((execstr_t *)NULL);
462 	}
463 
464 #ifdef	_LP64
465 	(void) memcpy(buffer, (sptr->nsc_ret.nsc_u.buff + sizeof (execstr32_t)),
466 	    (sptr->nsc_ret.nsc_bufferbytesused - sizeof (execstr32_t)));
467 	exec64.name = (char *)(sptr->nsc_ret.nsc_u.exec.name +
468 	    (uintptr_t)buffer);
469 	exec64.type = (char *)(sptr->nsc_ret.nsc_u.exec.type +
470 	    (uintptr_t)buffer);
471 	exec64.policy = (char *)(sptr->nsc_ret.nsc_u.exec.policy +
472 	    (uintptr_t)buffer);
473 	exec64.res1 = (char *)(sptr->nsc_ret.nsc_u.exec.res1 +
474 	    (uintptr_t)buffer);
475 	exec64.res2 = (char *)(sptr->nsc_ret.nsc_u.exec.res2 +
476 	    (uintptr_t)buffer);
477 	exec64.id = (char *)(sptr->nsc_ret.nsc_u.exec.id +
478 	    (uintptr_t)buffer);
479 	exec64.attr = (char *)(sptr->nsc_ret.nsc_u.exec.attr +
480 	    (uintptr_t)buffer);
481 	exec64.next = (execstr_t *)NULL;
482 	*result = exec64;
483 #else
484 	sptr->nsc_ret.nsc_u.exec.name += (uintptr_t)buffer;
485 	sptr->nsc_ret.nsc_u.exec.type += (uintptr_t)buffer;
486 	sptr->nsc_ret.nsc_u.exec.policy += (uintptr_t)buffer;
487 	sptr->nsc_ret.nsc_u.exec.res1 += (uintptr_t)buffer;
488 	sptr->nsc_ret.nsc_u.exec.res2 += (uintptr_t)buffer;
489 	sptr->nsc_ret.nsc_u.exec.id += (uintptr_t)buffer;
490 	sptr->nsc_ret.nsc_u.exec.attr += (uintptr_t)buffer;
491 	sptr->nsc_ret.nsc_u.exec.next = (execstr_t *)NULL;
492 	*result = sptr->nsc_ret.nsc_u.exec;
493 	(void) memcpy(buffer, (sptr->nsc_ret.nsc_u.buff + sizeof (execstr_t)),
494 	    (sptr->nsc_ret.nsc_bufferbytesused - sizeof (execstr_t)));
495 #endif
496 	return (result);
497 }
498 
499 
500 #ifdef DEBUG
501 void
502 print_execattr(execattr_t *exec)
503 {
504 	extern void print_kva(kva_t *);
505 	char *empty = "empty";
506 
507 	if (exec != NULL) {
508 		printf("name=%s\n", exec->name ? exec->name : empty);
509 		printf("policy=%s\n", exec->policy ? exec->policy : empty);
510 		printf("type=%s\n", exec->type ? exec->type : empty);
511 		printf("res1=%s\n", exec->res1 ? exec->res1 : empty);
512 		printf("res2=%s\n", exec->res2 ? exec->res2 : empty);
513 		printf("id=%s\n", exec->id ? exec->id : empty);
514 		printf("attr=\n");
515 		print_kva(exec->attr);
516 		fflush(stdout);
517 		if (exec->next) {
518 			print_execattr(exec->next);
519 		}
520 	} else {
521 		printf("NULL\n");
522 	}
523 }
524 #endif  /* DEBUG */
525