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
_print_execstr(execstr_t * exec)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
_exec_ldap_exec2ent(ns_ldap_entry_t * entry,nss_XbyY_args_t * argp)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
_nss_ldap_exec2str(ldap_backend_ptr be,nss_XbyY_args_t * argp)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
_exec_process_val(ldap_backend_ptr be,nss_XbyY_args_t * argp)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
get_wild(ldap_backend_ptr be,nss_XbyY_args_t * argp,int getby_flag)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
exec_attr_process_val(ldap_backend_ptr be,nss_XbyY_args_t * argp)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
getbynam(ldap_backend_ptr be,void * a)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
getbyid(ldap_backend_ptr be,void * a)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
getbynameid(ldap_backend_ptr be,void * a)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 *
_nss_ldap_exec_attr_constr(const char * dummy1,const char * dummy2,const char * dummy3,const char * dummy4,const char * dummy5,const char * dummy6,const char * dummy7)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