xref: /illumos-gate/usr/src/lib/nsswitch/ldap/common/getexecattr.c (revision dd72704bd9e794056c558153663c739e2012d721)
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  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  * Copyright 2021 Joyent, Inc.
25  */
26 
27 #include <secdb.h>
28 #include <exec_attr.h>
29 #include "ldap_common.h"
30 
31 
32 /* exec_attr attributes filters */
33 #define	ISWILD(x)		(x == NULL) ? "*" : x
34 #define	_EXEC_NAME		"cn"
35 #define	_EXEC_POLICY		"SolarisKernelSecurityPolicy"
36 #define	_EXEC_TYPE		"SolarisProfileType"
37 #define	_EXEC_RES1		"SolarisAttrRes1"
38 #define	_EXEC_RES2		"SolarisAttrRes2"
39 #define	_EXEC_ID		"SolarisProfileId"
40 #define	_EXEC_ATTRS		"SolarisAttrKeyValue"
41 #define	_EXEC_GETEXECNAME	"(&(objectClass=SolarisExecAttr)(cn=%s)"\
42 				"(SolarisKernelSecurityPolicy=%s)"\
43 				"(SolarisProfileType=%s))"
44 #define	_EXEC_GETEXECNAME_SSD	"(&(%%s)(cn=%s)"\
45 				"(SolarisKernelSecurityPolicy=%s)"\
46 				"(SolarisProfileType=%s))"
47 #define	_EXEC_GETEXECID		"(&(objectClass=SolarisExecAttr)"\
48 				"(SolarisProfileId=%s)"\
49 				"(SolarisKernelSecurityPolicy=%s)"\
50 				"(SolarisProfileType=%s))"
51 #define	_EXEC_GETEXECID_SSD	"(&(%%s)"\
52 				"(SolarisProfileId=%s)"\
53 				"(SolarisKernelSecurityPolicy=%s)"\
54 				"(SolarisProfileType=%s))"
55 #define	_EXEC_GETEXECNAMEID	"(&(objectClass=SolarisExecAttr)(cn=%s)"\
56 				"(SolarisProfileId=%s)"\
57 				"(SolarisKernelSecurityPolicy=%s)"\
58 				"(SolarisProfileType=%s))"
59 #define	_EXEC_GETEXECNAMEID_SSD	"(&(%%s)(cn=%s)"\
60 				"(SolarisProfileId=%s)"\
61 				"(SolarisKernelSecurityPolicy=%s)"\
62 				"(SolarisProfileType=%s))"
63 
64 
65 /* from libnsl */
66 extern int _doexeclist(nss_XbyY_args_t *);
67 extern char *_exec_wild_id(char *, const char *);
68 extern void _exec_cleanup(nss_status_t, nss_XbyY_args_t *);
69 
70 
71 static const char *exec_attrs[] = {
72 	_EXEC_NAME,
73 	_EXEC_POLICY,
74 	_EXEC_TYPE,
75 	_EXEC_RES1,
76 	_EXEC_RES2,
77 	_EXEC_ID,
78 	_EXEC_ATTRS,
79 	(char *)NULL
80 };
81 
82 
83 #ifdef	DEBUG
84 static void
85 _print_execstr(execstr_t *exec)
86 {
87 
88 	(void) fprintf(stdout, "      exec-name: [%s]\n", exec->name);
89 	if (exec->policy != (char *)NULL) {
90 		(void) fprintf(stdout, "      policy: [%s]\n", exec->policy);
91 	}
92 	if (exec->type != (char *)NULL) {
93 		(void) fprintf(stdout, "      type: [%s]\n", exec->type);
94 	}
95 	if (exec->res1 != (char *)NULL) {
96 		(void) fprintf(stdout, "      res1: [%s]\n", exec->res1);
97 	}
98 	if (exec->res2 != (char *)NULL) {
99 		(void) fprintf(stdout, "      res2: [%s]\n", exec->res2);
100 	}
101 	if (exec->id != (char *)NULL) {
102 		(void) fprintf(stdout, "      id: [%s]\n", exec->id);
103 	}
104 	if (exec->attr != (char *)NULL) {
105 		(void) fprintf(stdout, "      attr: [%s]\n", exec->attr);
106 	}
107 	if (exec->next != (execstr_t *)NULL) {
108 		(void) fprintf(stdout, "      next: [%s]\n", exec->next->name);
109 		(void) fprintf(stdout, "\n");
110 		_print_execstr(exec->next);
111 	}
112 }
113 #endif	/* DEBUG */
114 
115 
116 static int
117 _exec_ldap_exec2ent(ns_ldap_entry_t *entry, nss_XbyY_args_t *argp)
118 {
119 
120 	int			i;
121 	unsigned long		len = 0L;
122 	int			buflen = (int)0;
123 	char			*nullstring = (char *)NULL;
124 	char			*buffer = (char *)NULL;
125 	char			*ceiling = (char *)NULL;
126 	execstr_t		*exec = (execstr_t *)NULL;
127 	ns_ldap_attr_t		*attrptr;
128 
129 	buffer = argp->buf.buffer;
130 	buflen = (size_t)argp->buf.buflen;
131 	(void) memset(argp->buf.buffer, 0, buflen);
132 	exec = (execstr_t *)(argp->buf.result);
133 	ceiling = buffer + buflen;
134 	exec->name = (char *)NULL;
135 	exec->policy = (char *)NULL;
136 	exec->type = (char *)NULL;
137 	exec->res1 = (char *)NULL;
138 	exec->res2 = (char *)NULL;
139 	exec->id = (char *)NULL;
140 	exec->attr = (char *)NULL;
141 
142 	for (i = 0; i < entry->attr_count; i++) {
143 		attrptr = entry->attr_pair[i];
144 		if (attrptr == NULL) {
145 			return ((int)NSS_STR_PARSE_PARSE);
146 		}
147 		if (strcasecmp(attrptr->attrname, _EXEC_NAME) == 0) {
148 			if ((attrptr->attrvalue[0] == NULL) ||
149 			    (len = strlen(attrptr->attrvalue[0])) < 1) {
150 				return ((int)NSS_STR_PARSE_PARSE);
151 			}
152 			exec->name = buffer;
153 			buffer += len + 1;
154 			if (buffer >= ceiling) {
155 				return ((int)NSS_STR_PARSE_ERANGE);
156 			}
157 			(void) strcpy(exec->name, attrptr->attrvalue[0]);
158 			continue;
159 		}
160 		if (strcasecmp(attrptr->attrname, _EXEC_POLICY) == 0) {
161 			if ((attrptr->attrvalue[0] == NULL) ||
162 			    (len = strlen(attrptr->attrvalue[0])) < 1) {
163 				exec->policy = nullstring;
164 			} else {
165 				exec->policy = buffer;
166 				buffer += len + 1;
167 				if (buffer >= ceiling) {
168 					return ((int)NSS_STR_PARSE_ERANGE);
169 				}
170 				(void) strcpy(exec->policy,
171 				    attrptr->attrvalue[0]);
172 			}
173 			continue;
174 		}
175 		if (strcasecmp(attrptr->attrname, _EXEC_TYPE) == 0) {
176 			if ((attrptr->attrvalue[0] == NULL) ||
177 			    (len = strlen(attrptr->attrvalue[0])) < 1) {
178 				exec->type = nullstring;
179 			} else {
180 				exec->type = buffer;
181 				buffer += len + 1;
182 				if (buffer >= ceiling) {
183 					return ((int)NSS_STR_PARSE_ERANGE);
184 				}
185 				(void) strcpy(exec->type,
186 				    attrptr->attrvalue[0]);
187 			}
188 			continue;
189 		}
190 		if (strcasecmp(attrptr->attrname, _EXEC_RES1) == 0) {
191 			if ((attrptr->attrvalue[0] == NULL) ||
192 			    (len = strlen(attrptr->attrvalue[0])) < 1) {
193 				exec->res1 = nullstring;
194 			} else {
195 				exec->res1 = buffer;
196 				buffer += len + 1;
197 				if (buffer >= ceiling) {
198 					return ((int)NSS_STR_PARSE_ERANGE);
199 				}
200 				(void) strcpy(exec->res1,
201 				    attrptr->attrvalue[0]);
202 			}
203 			continue;
204 		}
205 		if (strcasecmp(attrptr->attrname, _EXEC_RES2) == 0) {
206 			if ((attrptr->attrvalue[0] == NULL) ||
207 			    (len = strlen(attrptr->attrvalue[0])) < 1) {
208 				exec->res2 = nullstring;
209 			} else {
210 				exec->res2 = buffer;
211 				buffer += len + 1;
212 				if (buffer >= ceiling) {
213 					return ((int)NSS_STR_PARSE_ERANGE);
214 				}
215 				(void) strcpy(exec->res2,
216 				    attrptr->attrvalue[0]);
217 			}
218 			continue;
219 		}
220 		if (strcasecmp(attrptr->attrname, _EXEC_ID) == 0) {
221 			if ((attrptr->attrvalue[0] == NULL) ||
222 			    (len = strlen(attrptr->attrvalue[0])) < 1) {
223 				exec->id = nullstring;
224 			} else {
225 				exec->id = buffer;
226 				buffer += len + 1;
227 				if (buffer >= ceiling) {
228 					return ((int)NSS_STR_PARSE_ERANGE);
229 				}
230 				(void) strcpy(exec->id, attrptr->attrvalue[0]);
231 			}
232 			continue;
233 		}
234 		if (strcasecmp(attrptr->attrname, _EXEC_ATTRS) == 0) {
235 			if ((attrptr->attrvalue[0] == NULL) ||
236 			    (len = strlen(attrptr->attrvalue[0])) < 1) {
237 				exec->attr = nullstring;
238 			} else {
239 				exec->attr = buffer;
240 				buffer += len + 1;
241 				if (buffer >= ceiling) {
242 					return ((int)NSS_STR_PARSE_ERANGE);
243 				}
244 				(void) strcpy(exec->attr,
245 				    attrptr->attrvalue[0]);
246 			}
247 			continue;
248 		}
249 	}
250 
251 	exec->next = (execstr_t *)NULL;
252 
253 #ifdef	DEBUG
254 	(void) fprintf(stdout, "\n[getexecattr.c: _exec_ldap_exec2ent]\n");
255 	_print_execstr(exec);
256 #endif	/* DEBUG */
257 
258 	return ((int)NSS_STR_PARSE_SUCCESS);
259 }
260 
261 
262 /*
263  * place the results from ldap object structure into the file format
264  * returns NSS_STR_PARSE_{SUCCESS, ERANGE, PARSE}
265  */
266 static int
267 _nss_ldap_exec2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
268 {
269 	int			status = NSS_STR_PARSE_SUCCESS;
270 	ns_ldap_result_t	*result = be->result;
271 	int			len;
272 	char			*buffer, **name, **policy, **type;
273 	char			**res1, **res2, **id, **attr;
274 	char			*policy_str, *type_str, *res1_str, *res2_str;
275 	char			*id_str, *attr_str;
276 
277 	if (result == NULL)
278 		return (NSS_STR_PARSE_PARSE);
279 
280 	(void) memset(argp->buf.buffer, 0, argp->buf.buflen);
281 
282 	name = __ns_ldap_getAttr(result->entry, _EXEC_NAME);
283 	if (name == NULL || name[0] == NULL ||
284 	    (strlen(name[0]) < 1)) {
285 		status = NSS_STR_PARSE_PARSE;
286 		goto result_exec2str;
287 	}
288 
289 	policy = __ns_ldap_getAttr(result->entry, _EXEC_POLICY);
290 
291 	if (policy == NULL || policy[0] == NULL)
292 		policy_str = _NO_VALUE;
293 	else
294 		policy_str = policy[0];
295 
296 	type = __ns_ldap_getAttr(result->entry, _EXEC_TYPE);
297 	if (type == NULL || type[0] == NULL)
298 		type_str = _NO_VALUE;
299 	else
300 		type_str = type[0];
301 
302 	res1 = __ns_ldap_getAttr(result->entry, _EXEC_RES1);
303 	if (res1 == NULL || res1[0] == NULL)
304 		res1_str = _NO_VALUE;
305 	else
306 		res1_str = res1[0];
307 
308 	res2 = __ns_ldap_getAttr(result->entry, _EXEC_RES2);
309 	if (res2 == NULL || res2[0] == NULL)
310 		res2_str = _NO_VALUE;
311 	else
312 		res2_str = res2[0];
313 
314 	id = __ns_ldap_getAttr(result->entry, _EXEC_ID);
315 	if (id == NULL || id[0] == NULL)
316 		id_str = _NO_VALUE;
317 	else
318 		id_str = id[0];
319 
320 	attr = __ns_ldap_getAttr(result->entry, _EXEC_ATTRS);
321 	if (attr == NULL || attr[0] == NULL)
322 		attr_str = _NO_VALUE;
323 	else
324 		attr_str = attr[0];
325 
326 	/* 7 = 6 ':' + 1 '\0' */
327 	len = strlen(name[0]) + strlen(policy_str) + strlen(type_str) +
328 	    strlen(res1_str) + strlen(res2_str) + strlen(id_str) +
329 	    strlen(attr_str) + 7;
330 
331 	if (len > argp->buf.buflen) {
332 		status = NSS_STR_PARSE_ERANGE;
333 		goto  result_exec2str;
334 	}
335 	if (argp->buf.result != NULL) {
336 		if ((be->buffer = calloc(1, len)) == NULL) {
337 			status = NSS_STR_PARSE_PARSE;
338 			goto result_exec2str;
339 		}
340 		buffer = be->buffer;
341 	} else
342 		buffer = argp->buf.buffer;
343 
344 	(void) snprintf(buffer, len, "%s:%s:%s:%s:%s:%s:%s",
345 	    name[0], policy_str, type_str, res1_str,
346 	    res2_str, id_str, attr_str);
347 	/* The front end marshaller does not need the trailing null */
348 	if (argp->buf.result != NULL)
349 		be->buflen = strlen(buffer);
350 result_exec2str:
351 	(void) __ns_ldap_freeResult(&be->result);
352 	return (status);
353 }
354 
355 
356 static nss_status_t
357 _exec_process_val(ldap_backend_ptr be, nss_XbyY_args_t *argp)
358 {
359 	int			status;
360 	nss_status_t		nss_stat = NSS_UNAVAIL;
361 	ns_ldap_attr_t		*attrptr;
362 	ns_ldap_entry_t		*entry;
363 	ns_ldap_result_t	*result = be->result;
364 	_priv_execattr	*_priv_exec = (_priv_execattr *)(argp->key.attrp);
365 
366 	argp->returnval = NULL;
367 	attrptr = getattr(result, 0);
368 	if (attrptr == NULL) {
369 		(void) __ns_ldap_freeResult(&be->result);
370 		return (nss_stat);
371 	}
372 	for (entry = result->entry; entry != NULL; entry = entry->next) {
373 		status = _exec_ldap_exec2ent(entry, argp);
374 		switch (status) {
375 		case NSS_STR_PARSE_SUCCESS:
376 			argp->returnval = argp->buf.result;
377 			nss_stat = NSS_SUCCESS;
378 			if (IS_GET_ALL(_priv_exec->search_flag)) {
379 				if (_doexeclist(argp) == 0) {
380 					nss_stat = NSS_UNAVAIL;
381 				}
382 			}
383 			break;
384 		case NSS_STR_PARSE_ERANGE:
385 			argp->erange = 1;
386 			nss_stat = NSS_NOTFOUND;
387 			break;
388 		case NSS_STR_PARSE_PARSE:
389 			nss_stat = NSS_NOTFOUND;
390 			break;
391 		default:
392 			nss_stat = NSS_UNAVAIL;
393 			break;
394 		}
395 
396 		if (IS_GET_ONE(_priv_exec->search_flag) ||
397 		    (nss_stat != NSS_SUCCESS)) {
398 			break;
399 		}
400 	}
401 
402 	return (nss_stat);
403 }
404 
405 
406 /*
407  * Check if we have either an exact match or a wild-card entry for that id.
408  */
409 static nss_status_t
410 get_wild(ldap_backend_ptr be, nss_XbyY_args_t *argp, int getby_flag)
411 {
412 	char		*dup_id = NULL;
413 	char		*wild_id;
414 	char		searchfilter[SEARCHFILTERLEN];
415 	char		userdata[SEARCHFILTERLEN];
416 	char		name[SEARCHFILTERLEN];
417 	char		id[SEARCHFILTERLEN];
418 	int		ret;
419 	nss_status_t	nss_stat = NSS_NOTFOUND;
420 	_priv_execattr	*_priv_exec = (_priv_execattr *)(argp->key.attrp);
421 	const char	*policy = _priv_exec->policy;
422 	const char	*type = _priv_exec->type;
423 
424 	if ((policy != NULL && strpbrk(policy, "*()\\") != NULL) ||
425 	    type != NULL && strpbrk(type, "*()\\") != NULL)
426 		return ((nss_status_t)NSS_NOTFOUND);
427 
428 	if (_priv_exec->id != NULL)
429 		dup_id = strdup(_priv_exec->id);
430 
431 	switch (getby_flag) {
432 	case NSS_DBOP_EXECATTR_BYNAMEID:
433 		if (_ldap_filter_name(name, _priv_exec->name,
434 		    sizeof (name)) != 0)
435 			goto go_out;
436 		break;
437 	}
438 
439 	wild_id = dup_id;
440 	do {
441 		if (wild_id != NULL) {
442 			if (_ldap_filter_name(id, wild_id, sizeof (id)) != 0)
443 				goto go_out;
444 		} else
445 			(void) strlcpy(id, "*", sizeof (id));
446 
447 		switch (getby_flag) {
448 		case NSS_DBOP_EXECATTR_BYID:
449 			ret = snprintf(searchfilter, sizeof (searchfilter),
450 			    _EXEC_GETEXECID, id, ISWILD(policy), ISWILD(type));
451 			if (ret >= sizeof (searchfilter) || ret < 0)
452 				goto go_out;
453 			ret = snprintf(userdata, sizeof (userdata),
454 			    _EXEC_GETEXECID_SSD, id, ISWILD(policy),
455 			    ISWILD(type));
456 			if (ret >= sizeof (userdata) || ret < 0)
457 				goto go_out;
458 			break;
459 
460 		case NSS_DBOP_EXECATTR_BYNAMEID:
461 			ret = snprintf(searchfilter, sizeof (searchfilter),
462 			    _EXEC_GETEXECNAMEID, name, id,
463 			    ISWILD(policy), ISWILD(type));
464 			if (ret >= sizeof (searchfilter) || ret < 0)
465 				goto go_out;
466 			ret = snprintf(userdata, sizeof (userdata),
467 			    _EXEC_GETEXECNAMEID_SSD, name, id,
468 			    ISWILD(policy), ISWILD(type));
469 			if (ret >= sizeof (userdata) || ret < 0)
470 				goto go_out;
471 			break;
472 
473 		default:
474 			goto go_out;
475 		}
476 		nss_stat = _nss_ldap_nocb_lookup(be, argp, _EXECATTR,
477 		    searchfilter, NULL, _merge_SSD_filter, userdata);
478 		if (nss_stat == NSS_SUCCESS)
479 			break;
480 	} while ((wild_id = _exec_wild_id(wild_id, type)) != NULL);
481 
482 go_out:
483 	free(dup_id);
484 
485 	return (nss_stat);
486 }
487 
488 static nss_status_t
489 exec_attr_process_val(ldap_backend_ptr be, nss_XbyY_args_t *argp)
490 {
491 	_priv_execattr	*_priv_exec = (_priv_execattr *)(argp->key.attrp);
492 	int		stat, nss_stat = NSS_SUCCESS;
493 
494 	if (IS_GET_ONE(_priv_exec->search_flag)) {
495 		/* ns_ldap_entry_t -> file format */
496 		stat = (*be->ldapobj2str)(be, argp);
497 
498 		if (stat == NSS_STR_PARSE_SUCCESS) {
499 			if (argp->buf.result != NULL) {
500 				/* file format -> execstr_t */
501 				stat = (*argp->str2ent)(be->buffer,
502 				    be->buflen,
503 				    argp->buf.result,
504 				    argp->buf.buffer,
505 				    argp->buf.buflen);
506 				if (stat == NSS_STR_PARSE_SUCCESS) {
507 					argp->returnval = argp->buf.result;
508 					argp->returnlen = 1; /* irrelevant */
509 					nss_stat = NSS_SUCCESS;
510 				} else {
511 					argp->returnval = NULL;
512 					argp->returnlen = 0;
513 					nss_stat = NSS_NOTFOUND;
514 				}
515 			} else {
516 				/* return file format in argp->buf.buffer */
517 				argp->returnval = argp->buf.buffer;
518 				argp->returnlen = strlen(argp->buf.buffer);
519 				nss_stat = NSS_SUCCESS;
520 			}
521 		} else {
522 			argp->returnval = NULL;
523 			argp->returnlen = 0;
524 			nss_stat = NSS_NOTFOUND;
525 		}
526 	} else {
527 		/* GET_ALL */
528 		nss_stat = _exec_process_val(be, argp);
529 		_exec_cleanup(nss_stat, argp);
530 	}
531 
532 	return (nss_stat);
533 
534 }
535 
536 static nss_status_t
537 getbynam(ldap_backend_ptr be, void *a)
538 {
539 	char		searchfilter[SEARCHFILTERLEN];
540 	char		userdata[SEARCHFILTERLEN];
541 	char		name[SEARCHFILTERLEN];
542 	int		ret;
543 	nss_status_t	nss_stat;
544 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
545 	_priv_execattr	*_priv_exec = (_priv_execattr *)(argp->key.attrp);
546 	const char	*policy = _priv_exec->policy;
547 	const char	*type = _priv_exec->type;
548 
549 	if (policy != NULL && strpbrk(policy, "*()\\") != NULL ||
550 	    type != NULL && strpbrk(type, "*()\\") != NULL ||
551 	    _ldap_filter_name(name, _priv_exec->name, sizeof (name)) != 0)
552 		return ((nss_status_t)NSS_NOTFOUND);
553 	ret = snprintf(searchfilter, sizeof (searchfilter),
554 	    _EXEC_GETEXECNAME, name, ISWILD(policy), ISWILD(type));
555 	if (ret >= sizeof (searchfilter) || ret < 0)
556 		return ((nss_status_t)NSS_NOTFOUND);
557 	ret = snprintf(userdata, sizeof (userdata),
558 	    _EXEC_GETEXECNAME_SSD, name, ISWILD(policy), ISWILD(type));
559 	if (ret >= sizeof (userdata) || ret < 0)
560 		return ((nss_status_t)NSS_NOTFOUND);
561 
562 	nss_stat = _nss_ldap_nocb_lookup(be, argp, _EXECATTR,
563 	    searchfilter, NULL, _merge_SSD_filter, userdata);
564 
565 	if (nss_stat ==  NSS_SUCCESS)
566 		nss_stat = exec_attr_process_val(be, argp);
567 
568 	return (nss_stat);
569 }
570 
571 static nss_status_t
572 getbyid(ldap_backend_ptr be, void *a)
573 {
574 	nss_status_t	nss_stat = NSS_SUCCESS;
575 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
576 
577 	nss_stat = get_wild(be, argp, NSS_DBOP_EXECATTR_BYID);
578 
579 	if (nss_stat ==  NSS_SUCCESS)
580 		nss_stat = exec_attr_process_val(be, argp);
581 
582 	return (nss_stat);
583 }
584 
585 
586 static nss_status_t
587 getbynameid(ldap_backend_ptr be, void *a)
588 {
589 	nss_status_t	nss_stat;
590 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
591 
592 	nss_stat = get_wild(be, argp, NSS_DBOP_EXECATTR_BYNAMEID);
593 
594 	if (nss_stat ==  NSS_SUCCESS)
595 		nss_stat = exec_attr_process_val(be, argp);
596 
597 	return (nss_stat);
598 }
599 
600 
601 static ldap_backend_op_t execattr_ops[] = {
602 	_nss_ldap_destr,
603 	_nss_ldap_endent,
604 	_nss_ldap_setent,
605 	_nss_ldap_getent,
606 	getbynam,
607 	getbyid,
608 	getbynameid
609 };
610 
611 
612 /*ARGSUSED0*/
613 nss_backend_t *
614 _nss_ldap_exec_attr_constr(const char *dummy1,
615     const char *dummy2,
616     const char *dummy3,
617     const char *dummy4,
618     const char *dummy5,
619     const char *dummy6,
620     const char *dummy7)
621 {
622 #ifdef	DEBUG
623 	(void) fprintf(stdout,
624 	    "\n[getexecattr.c: _nss_ldap_exec_attr_constr]\n");
625 #endif
626 	return ((nss_backend_t *)_nss_ldap_constr(execattr_ops,
627 	    sizeof (execattr_ops)/sizeof (execattr_ops[0]), _EXECATTR,
628 	    exec_attrs, _nss_ldap_exec2str));
629 }
630