dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / fs.d / autofs / ns_ldap.c
blobab27d26cea667e31a8335600cd6a3a46c2edf92d
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * ns_ldap.c
24 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <syslog.h>
31 #include <string.h>
32 #include <ctype.h>
33 #include <nsswitch.h>
34 #include <sys/param.h>
35 #include <sys/types.h>
36 #include <rpc/rpc.h>
37 #include <rpcsvc/nfs_prot.h>
38 #include <sys/errno.h>
39 #include <libintl.h>
40 #include "automount.h"
41 #include "../../../lib/libsldap/common/ns_sldap.h"
44 * LDAP schema used for automounter:
46 * automountMapName: mapname i.e. auto_home, etc.
47 * automountKey: contains the key i.e. the mount point
48 * automountInformation: contains the mount options and remote mount location
49 * description: an optional description (not used by automounter)
51 * For example, if auto_direct has the following line of data:
53 * /work -rw,intr,nosuid,noquota hosta:/export/work
55 * Then this would map to the the following LDAP entry:
57 * dn: automountKey=/work,automountMapName=auto_direct,...
58 * automountKey: /work
59 * automountInformation: -rw,intr,nosuid,noquota hosta:/export/work
60 * objectclass: top
61 * objectclass: automount
63 * In this container:
65 * dn: automountMapName=auto_direct,...
66 * automountMapName: auto_direct
67 * objectClass: top
68 * objectClass: automountMap
70 * Note that the schema can be mapped and SSD's can be used to relocate
71 * the default location of these entries.
75 #define CAPCHAR '%'
76 #define MAXERROR 4000
78 static char *automountKey = NULL;
79 static char *automountInformation = NULL;
80 static char *defaultFilter = NULL;
81 static int encode = 0;
83 static int mastermap_callback_ldap();
84 static int directmap_callback();
85 static int ldap_err(int);
86 static int ldap_match();
87 static int readdir_callback();
89 struct loadmaster_cbdata {
90 char *ptr1;
91 char **ptr2;
92 char ***ptr3;
95 struct loaddirect_cbdata {
96 char *ptr1;
97 char *ptr2;
98 char **ptr3;
99 char ***ptr4;
102 struct dir_cbdata {
103 struct dir_entry **list;
104 struct dir_entry *last;
105 int error;
108 static char *tosunds_str(char *);
109 static char *tounix_str(char *);
111 static int
112 isAttrMapped(char *orig, char *mapped)
114 char **s;
115 char **mappedschema = NULL;
117 mappedschema = __ns_ldap_getMappedAttributes("automount", orig);
118 if (mappedschema == NULL)
119 return (0);
120 if (strcasecmp(mappedschema[0], mapped) != 0) {
121 for (s = mappedschema; *s != NULL; s++)
122 free(*s);
123 free(mappedschema);
124 return (0);
126 for (s = mappedschema; *s != NULL; s++)
127 free(*s);
128 free(mappedschema);
129 return (1);
132 static int
133 isObjectMapped(char *orig, char *mapped)
135 char **s;
136 char **mappedschema = NULL;
138 mappedschema = __ns_ldap_getMappedObjectClass("automount", orig);
139 if (mappedschema == NULL)
140 return (0);
141 if (strcasecmp(mappedschema[0], mapped) != 0) {
142 for (s = mappedschema; *s != NULL; s++)
143 free(*s);
144 free(mappedschema);
145 return (0);
147 for (s = mappedschema; *s != NULL; s++)
148 free(*s);
149 free(mappedschema);
150 return (1);
153 void
154 init_ldap(char **stack, char ***stkptr)
157 * Check for version of the profile the client is using
159 * For version 1 profiles we do encoding of attributes
160 * and use nisMap and nisObject schema for backward compatibility.
162 * For version 2 profiles we don't do encoding and use
163 * automountMap and automount as default attributes (which can
164 * then be overridden in libsldap if schema mapping is configured
165 * in the profile).
167 * If profile version is not available, use version 2 as default
168 * and syslog message.
170 int rc, v2 = 1;
171 void **paramVal = NULL;
172 ns_ldap_error_t *errorp = NULL;
173 struct __nsw_switchconfig *conf = NULL;
174 struct __nsw_lookup *lkp = NULL;
175 enum __nsw_parse_err pserr;
176 int ldap_configured = 0;
179 /* get nsswitch info of "automount */
180 conf = __nsw_getconfig("automount", &pserr);
182 /* find out if LDAP backend is configured */
183 if (conf != NULL) {
184 for (lkp = conf->lookups; lkp != NULL; lkp = lkp->next) {
185 if (strcmp(lkp->service_name, "ldap") == 0) {
186 ldap_configured = 1;
187 break;
190 /* free conf at the end of "if" bracket */
191 (void) __nsw_freeconfig(conf);
194 /* if ldap is not configured, init_ldap is a no op */
195 if (!ldap_configured)
196 return;
198 rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P, &paramVal, &errorp);
199 if (rc != NS_LDAP_SUCCESS || !paramVal || !*paramVal) {
200 syslog(LOG_ERR, "Can not determine version of LDAP profile"
201 " that is used (%d, %s). Using version 2 profile"
202 " defaults", rc, (errorp && errorp->message ?
203 errorp->message : ""));
204 (void) __ns_ldap_freeError(&errorp);
205 } else {
206 if (strcasecmp(*paramVal, NS_LDAP_VERSION_1) == 0)
207 v2 = 0;
208 (void) __ns_ldap_freeParam(&paramVal);
211 if (v2) {
212 if (trace > 1)
213 trace_prt(1, "init_ldap: setting up for version 2\n");
214 automountKey = "automountKey";
215 automountInformation = "automountInformation";
216 defaultFilter = "(&(objectClass=automount)(automountKey=%s))";
218 /* check for automountMapName mapped to nisMapName */
219 if (!isAttrMapped("automountMapName", "nisMapName"))
220 return;
222 /* check for automountKey mapped to cn */
223 if (!isAttrMapped("automountKey", "cn"))
224 return;
226 /* check for automountInformation mapped to nisMapEntry */
227 if (!isAttrMapped("automountInformation", "nisMapEntry"))
228 return;
230 /* check for automountMap mapped to nisMap */
231 if (!isObjectMapped("automountMap", "nisMap"))
232 return;
234 /* check for automount mapped to nisObject */
235 if (!isObjectMapped("automount", "nisObject"))
236 return;
238 if (trace > 1)
239 trace_prt(1, "init_ldap: encode = TRUE\n");
240 encode = 1;
241 } else {
242 if (trace > 1) {
243 trace_prt(1, "init_ldap: setting up for version 1\n");
244 trace_prt(1, "init_ldap: encode = TRUE\n");
246 encode = 1;
247 automountKey = "cn";
248 automountInformation = "nisMapEntry";
249 defaultFilter = "(&(objectClass=nisObject)(cn=%s))";
253 /*ARGSUSED*/
255 getmapent_ldap(char *key, char *map, struct mapline *ml,
256 char **stack, char ***stkptr, bool_t *iswildcard, bool_t isrestricted)
258 char *ldap_line = NULL;
259 char *lp;
260 int ldap_len, len;
261 int nserr;
263 if (trace > 1)
264 trace_prt(1, "getmapent_ldap called\n");
266 if (trace > 1) {
267 trace_prt(1, "getmapent_ldap: key=[ %s ]\n", key);
270 if (iswildcard)
271 *iswildcard = FALSE;
272 nserr = ldap_match(map, key, &ldap_line, &ldap_len);
273 if (nserr) {
274 if (nserr == __NSW_NOTFOUND) {
275 /* Try the default entry "*" */
276 if ((nserr = ldap_match(map, "\\2a", &ldap_line,
277 &ldap_len)))
278 goto done;
279 else {
280 if (iswildcard)
281 *iswildcard = TRUE;
283 } else
284 goto done;
288 * at this point we are sure that ldap_match
289 * succeeded so massage the entry by
290 * 1. ignoring # and beyond
291 * 2. trim the trailing whitespace
293 if (lp = strchr(ldap_line, '#'))
294 *lp = '\0';
295 len = strlen(ldap_line);
296 if (len == 0) {
297 nserr = __NSW_NOTFOUND;
298 goto done;
300 lp = &ldap_line[len - 1];
301 while (lp > ldap_line && isspace(*lp))
302 *lp-- = '\0';
303 if (lp == ldap_line) {
304 nserr = __NSW_NOTFOUND;
305 goto done;
307 (void) strncpy(ml->linebuf, ldap_line, LINESZ);
308 unquote(ml->linebuf, ml->lineqbuf);
309 nserr = __NSW_SUCCESS;
310 done:
311 if (ldap_line)
312 free((char *)ldap_line);
314 if (trace > 1)
315 trace_prt(1, "getmapent_ldap: exiting ...\n");
317 return (nserr);
320 static int
321 ldap_match(char *map, char *key, char **ldap_line, int *ldap_len)
323 char searchfilter[LDAP_FILT_MAXSIZ];
324 int res, attr_found;
325 ns_ldap_result_t *result = NULL;
326 ns_ldap_error_t *errp = NULL;
327 ns_ldap_entry_t *entry = NULL;
328 char *ldapkey;
329 int i;
331 if (trace > 1) {
332 trace_prt(1, "ldap_match called\n");
333 trace_prt(1, "ldap_match: key =[ %s ]\n", key);
337 * need to handle uppercase characters in the key because LDAP
338 * searches are case insensitive. Note, key = attribute automountKey.
340 if (encode)
341 ldapkey = tosunds_str(key);
342 else
343 ldapkey = key;
345 if (trace > 1) {
346 trace_prt(1, "ldap_match: ldapkey =[ %s ]\n", ldapkey);
349 (void) sprintf(searchfilter, defaultFilter, ldapkey);
351 if (trace > 1)
352 trace_prt(1, " ldap_match: Requesting list for %s in %s\n",
353 searchfilter, map);
355 res = __ns_ldap_list(map, searchfilter, NULL,
356 NULL, NULL, 0, &result, &errp, NULL, NULL);
358 if (trace > 1) {
359 if (res != NS_LDAP_SUCCESS)
360 trace_prt(1,
361 " ldap_match: __ns_ldap_list FAILED (%d)\n", res);
362 else
363 trace_prt(1, " ldap_match: __ns_ldap_list OK\n");
366 if (res != NS_LDAP_SUCCESS && res != NS_LDAP_NOTFOUND) {
367 if (errp) {
368 if (verbose) {
369 char errstr[MAXERROR];
370 (void) sprintf(errstr,
371 gettext("ldap server can't list map,"
372 " '%s': '%s' - '%d'."),
373 map, errp->message, errp->status);
374 syslog(LOG_ERR, errstr);
376 __ns_ldap_freeError(&errp);
377 } else {
378 if (verbose) {
379 char *errmsg;
380 __ns_ldap_err2str(res, &errmsg);
381 syslog(LOG_ERR, errmsg);
384 if (result)
385 __ns_ldap_freeResult(&result);
386 return (ldap_err(res));
389 if (res == NS_LDAP_NOTFOUND || result == NULL ||
390 result->entries_count == 0 || result->entry->attr_count == 0) {
391 if (trace > 1)
392 trace_prt(1, " ldap_match: no entries found\n");
393 if (errp)
394 __ns_ldap_freeError(&errp);
395 if (result)
396 __ns_ldap_freeResult(&result);
397 return (__NSW_NOTFOUND);
401 * get value of attribute nisMapEntry. This attribute contains a
402 * list of mount options AND mount location for a particular mount
403 * point (key).
404 * For example:
406 * key: /work
407 * ^^^^^
408 * (mount point)
410 * nisMapEntry: -rw,intr,nosuid,noquota hosta:/export/work
411 * ^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^
412 * ( mount options ) (remote mount location)
415 attr_found = 0;
416 entry = result->entry;
417 for (i = 0; i < entry->attr_count; i++) {
418 ns_ldap_attr_t *attr;
420 attr = entry->attr_pair[i];
421 if (strcasecmp(attr->attrname, automountInformation) == 0) {
422 char *attrval;
424 attr_found = 1;
425 if (encode)
426 attrval = tounix_str(attr->attrvalue[0]);
427 else
428 attrval = attr->attrvalue[0];
429 *ldap_len = strlen(key) + strlen(attrval);
432 * so check for the length; it should be less than
433 * LINESZ
435 if ((*ldap_len + 2) > LINESZ) {
436 syslog(LOG_ERR,
437 "ldap server map %s, entry for %s"
438 " is too long %d chars (max %d)",
439 map, key, (*ldap_len + 2), LINESZ);
440 __ns_ldap_freeResult(&result);
441 return (__NSW_UNAVAIL);
443 *ldap_line = (char *)malloc(*ldap_len + 2);
444 if (*ldap_line == NULL) {
445 syslog(LOG_ERR, "ldap_match: malloc failed");
446 __ns_ldap_freeResult(&result);
447 return (__NSW_UNAVAIL);
450 (void) sprintf(*ldap_line, "%s", attrval);
452 break;
456 __ns_ldap_freeError(&errp);
457 __ns_ldap_freeResult(&result);
459 if (!attr_found)
460 return (__NSW_NOTFOUND);
462 if (trace > 1)
463 trace_prt(1, " ldap_match: found: %s\n", *ldap_line);
465 return (__NSW_SUCCESS);
469 loadmaster_ldap(char *mapname, char *defopts, char **stack, char ***stkptr)
471 char searchfilter[LDAP_FILT_MAXSIZ];
472 int res;
473 ns_ldap_result_t *result = NULL;
474 ns_ldap_error_t *errp = NULL;
475 struct loadmaster_cbdata master_cbdata;
477 if (trace > 1)
478 trace_prt(1, "loadmaster_ldap called\n");
480 master_cbdata.ptr1 = defopts;
481 master_cbdata.ptr2 = stack;
482 master_cbdata.ptr3 = stkptr;
484 /* filter gets all the entries for the specified mapname */
485 (void) sprintf(searchfilter, defaultFilter, "*");
487 if (trace > 1)
488 trace_prt(1, "loadmaster_ldap: Requesting list for %s in %s\n",
489 searchfilter, mapname);
491 res = __ns_ldap_list(mapname, searchfilter, NULL, NULL, NULL,
492 0, &result, &errp, mastermap_callback_ldap,
493 (void *) &master_cbdata);
495 if (trace > 1)
496 trace_prt(1,
497 "loadmaster_ldap: __ns_ldap_list just returned: %d\n",
498 res);
500 if (res != NS_LDAP_SUCCESS) {
501 if (errp) {
502 char errstr[MAXERROR];
503 if (verbose) {
504 (void) sprintf(errstr, gettext(
505 "ldap server can't list map,"
506 "'%s': '%s' - '%d'."),
507 mapname, errp->message, errp->status);
508 syslog(LOG_ERR, errstr);
510 __ns_ldap_freeError(&errp);
511 } else {
512 if (verbose) {
513 char *errmsg;
514 __ns_ldap_err2str(res, &errmsg);
515 syslog(LOG_ERR, errmsg);
518 if (result)
519 __ns_ldap_freeResult(&result);
520 return (ldap_err(res));
523 if (trace > 1)
524 trace_prt(1,
525 "loadmaster_ldap: calling __ns_ldap_freeResult...\n");
527 __ns_ldap_freeResult(&result);
529 if (trace > 1)
530 trace_prt(1,
531 "loadmaster_ldap: about to return __NSW_SUCCESS...\n");
533 return (__NSW_SUCCESS);
537 loaddirect_ldap(char *nsmap, char *localmap, char *opts,
538 char **stack, char ***stkptr)
540 char searchfilter[LDAP_FILT_MAXSIZ];
541 int res;
542 ns_ldap_result_t *result = NULL;
543 ns_ldap_error_t *errp = NULL;
544 struct loaddirect_cbdata direct_cbdata;
546 if (trace > 1) {
547 trace_prt(1, "loaddirect_ldap called\n");
550 direct_cbdata.ptr1 = opts;
551 direct_cbdata.ptr2 = localmap;
552 direct_cbdata.ptr3 = stack;
553 direct_cbdata.ptr4 = stkptr;
555 /* filter gets all the entries for the specified mapname */
556 (void) sprintf(searchfilter, defaultFilter, "*");
558 if (trace > 1)
559 trace_prt(1, "loaddirect_ldap: Requesting list for %s in %s\n",
560 searchfilter, nsmap);
562 res = __ns_ldap_list(nsmap, searchfilter, NULL, NULL,
563 NULL, 0, &result, &errp,
564 directmap_callback, (void *) &direct_cbdata);
567 if (res != NS_LDAP_SUCCESS) {
568 if (errp) {
569 char errstr[MAXERROR];
570 if (verbose) {
571 (void) sprintf(errstr,
572 gettext("ldap server can't list map,"
573 " '%s': '%s' - '%d'."),
574 nsmap, errp->message, errp->status);
575 syslog(LOG_ERR, errstr);
577 __ns_ldap_freeError(&errp);
578 } else {
579 if (verbose) {
580 char *errmsg;
581 __ns_ldap_err2str(res, &errmsg);
582 syslog(LOG_ERR, errmsg);
585 if (result)
586 __ns_ldap_freeResult(&result);
587 return (ldap_err(res));
590 __ns_ldap_freeResult(&result);
591 return (__NSW_SUCCESS);
594 static int
595 ldap_err(int err)
597 if (trace > 1)
598 trace_prt(1, "ldap_err called\n");
600 switch (err) {
602 case NS_LDAP_SUCCESS:
603 return (__NSW_SUCCESS);
605 case NS_LDAP_NOTFOUND:
606 return (__NSW_NOTFOUND);
608 case NS_LDAP_PARTIAL:
609 return (__NSW_TRYAGAIN);
611 default:
612 return (__NSW_UNAVAIL);
616 static int
617 mastermap_callback_ldap(ns_ldap_entry_t *entry, void *udata)
619 char *key, *contents, *pmap, *opts;
620 char dir[LINESZ], map[LINESZ], qbuff[LINESZ];
621 char cont_temp[LINESZ], key_temp[LINESZ];
622 int key_len, contents_len;
623 struct loadmaster_cbdata *temp = (struct loadmaster_cbdata *)udata;
624 char *defopts = temp->ptr1;
625 char **stack = temp->ptr2;
626 char ***stkptr = temp->ptr3;
627 int i;
629 if (trace > 1) {
630 trace_prt(1, "mastermap_callback_ldap called\n");
631 trace_prt(1, "mastermap_callback_ldap: entry=%x\n", entry);
632 if (entry) {
633 trace_prt(1,
634 "mastermap_callback_ldap: entry->attr_count=[ %d ]\n",
635 entry->attr_count);
640 * For the current entry, obtain the values of the cn and the
641 * nisMapEntry attributes and the length of each value (cn=key,
642 * nisMapEntry=contents).
643 * We skip the description. Even though LDAP allows for multiple
644 * values per attribute, we take only the 1st value for each
645 * attribute because the automount data is organized as such.
647 key_len = 0;
648 contents_len = 0;
649 key = NULL;
650 contents = NULL;
651 for (i = 0; i < entry->attr_count; i++) {
652 ns_ldap_attr_t *attr;
654 attr = entry->attr_pair[i];
655 if (trace > 1) {
656 trace_prt(1,
657 "mastermap_callback_ldap: attr[%d]: %s=%s\n",
658 i, attr->attrname, attr->attrvalue[0]);
660 if (strcasecmp(attr->attrname, automountInformation) == 0) {
661 if (encode)
662 (void) strncpy(cont_temp,
663 tounix_str(attr->attrvalue[0]), LINESZ);
664 else
665 (void) strncpy(cont_temp, attr->attrvalue[0],
666 LINESZ);
667 contents = cont_temp;
668 contents_len = strlen(contents);
669 if (trace > 1) {
670 trace_prt(1,
671 "mastermap_callback_ldap: contents=[ %s ],"
672 " contents_len=[ %d ]\n",
673 contents, contents_len);
676 if (strcasecmp(attr->attrname, automountKey) == 0) {
677 if (encode)
678 (void) strncpy(key_temp,
679 tounix_str(attr->attrvalue[0]), LINESZ);
680 else
681 (void) strncpy(key_temp, attr->attrvalue[0],
682 LINESZ);
683 key = key_temp;
684 key_len = strlen(key);
685 if (trace > 1) {
686 trace_prt(1,
687 "mastermap_callback_ldap: key=[ %s ],"
688 " key_len=[ %d ]\n",
689 key, key_len);
694 if (key_len >= LINESZ || contents_len >= LINESZ)
695 return (0);
696 if (key_len < 2 || contents_len < 2)
697 return (0);
699 while (isspace(*contents))
700 contents++;
701 if (contents == NULL)
702 return (0);
703 if (isspace(*key) || *key == '#')
704 return (0);
706 (void) strncpy(dir, key, key_len);
707 dir[key_len] = '\0';
708 if (trace > 1)
709 trace_prt(1, "mastermap_callback_ldap: dir= [ %s ]\n", dir);
710 for (i = 0; i < LINESZ; i++)
711 qbuff[i] = ' ';
712 if (macro_expand("", dir, qbuff, sizeof (dir))) {
713 syslog(LOG_ERR,
714 "%s in ldap server map: entry too long (max %d chars)",
715 dir, sizeof (dir) - 1);
716 return (0);
718 (void) strncpy(map, contents, contents_len);
719 map[contents_len] = '\0';
720 if (trace > 1)
721 trace_prt(1, "mastermap_callback_ldap: map= [ %s ]\n", map);
722 if (macro_expand("", map, qbuff, sizeof (map))) {
723 syslog(LOG_ERR,
724 "%s in ldap server map: entry too long (max %d chars)",
725 map, sizeof (map) - 1);
726 return (0);
728 pmap = map;
729 while (*pmap && isspace(*pmap))
730 pmap++; /* skip blanks in front of map */
731 opts = pmap;
732 while (*opts && !isspace(*opts))
733 opts++;
734 if (*opts) {
735 *opts++ = '\0';
736 while (*opts && isspace(*opts))
737 opts++;
738 if (*opts == '-')
739 opts++;
740 else
741 opts = defopts;
744 * Check for no embedded blanks.
746 if (strcspn(opts, " ") == strlen(opts)) {
747 if (trace > 1)
748 trace_prt(1,
749 "mastermap_callback_ldap: dir=[ %s ], pmap=[ %s ]\n",
750 dir, pmap);
751 dirinit(dir, pmap, opts, 0, stack, stkptr);
752 } else {
753 char *dn = NULL;
755 /* get the value for the dn */
756 for (i = 0; i < entry->attr_count; i++) {
757 ns_ldap_attr_t *attr;
759 attr = entry->attr_pair[i];
760 if (strcasecmp(attr->attrname, "dn")
761 == 0) {
762 dn = attr->attrvalue[0];
763 break;
766 pr_msg(
767 "Warning: invalid entry for %s in ldap server"
768 " dn: %s ignored.\n",
769 dir, dn);
771 if (trace > 1)
772 trace_prt(1, "mastermap_callback_ldap exiting...\n");
773 return (0);
776 static int
777 directmap_callback(ns_ldap_entry_t *entry, void *udata)
779 char *key;
780 char dir[256];
781 int key_len;
782 struct loaddirect_cbdata *temp = (struct loaddirect_cbdata *)udata;
783 char *opts = temp->ptr1;
784 char *localmap = temp->ptr2;
785 char **stack = temp->ptr3;
786 char ***stkptr = temp->ptr4;
787 int i;
790 * For the current entry, obtain the value and length of the cn i.e.
791 * the contents of key and its key length.
793 key_len = 0;
794 key = NULL;
795 for (i = 0; i < entry->attr_count; i++) {
796 ns_ldap_attr_t *attr;
798 attr = entry->attr_pair[i];
799 if (strcasecmp(attr->attrname, automountKey) == 0) {
800 if (encode)
801 key = tounix_str(attr->attrvalue[0]);
802 else
803 key = attr->attrvalue[0];
804 key_len = strlen(key);
805 break;
809 if (key_len >= 100 || key_len < 2)
810 return (0);
812 if (isspace(*key) || *key == '#')
813 return (0);
814 (void) strncpy(dir, key, key_len);
815 dir[key_len] = '\0';
817 dirinit(dir, localmap, opts, 1, stack, stkptr);
819 return (0);
823 getmapkeys_ldap(char *nsmap, struct dir_entry **list, int *error,
824 int *cache_time, char **stack, char ***stkptr)
826 char searchfilter[LDAP_FILT_MAXSIZ];
827 int res;
828 ns_ldap_result_t *result = NULL;
829 ns_ldap_error_t *errp = NULL;
830 struct dir_cbdata readdir_cbdata;
833 if (trace > 1)
834 trace_prt(1, "getmapkeys_ldap called\n");
836 *cache_time = RDDIR_CACHE_TIME;
837 *error = 0;
838 readdir_cbdata.list = list;
839 readdir_cbdata.last = NULL;
841 /* filter gets all the entries for the specified mapname */
842 (void) sprintf(searchfilter, defaultFilter, "*");
844 if (trace > 1)
845 trace_prt(1, "getmapkeys_ldap: Requesting list for %s in %s\n",
846 searchfilter, nsmap);
848 res = __ns_ldap_list(nsmap, searchfilter, NULL, NULL, NULL, 0,
849 &result, &errp, readdir_callback, (void *) &readdir_cbdata);
851 if (trace > 1)
852 trace_prt(1, " getmapkeys_ldap: __ns_ldap_list returned %d\n",
853 res);
855 if (readdir_cbdata.error)
856 *error = readdir_cbdata.error;
858 if (res != NS_LDAP_SUCCESS && res != NS_LDAP_NOTFOUND) {
859 if (errp) {
860 if (verbose) {
861 char errstr[MAXERROR];
862 (void) sprintf(errstr, gettext(
863 "ldap server can't list map,"
864 " '%s': '%s' - '%d'."),
865 nsmap, errp->message, errp->status);
866 syslog(LOG_ERR, errstr);
868 __ns_ldap_freeError(&errp);
869 } else {
870 if (verbose) {
871 char *errmsg;
872 __ns_ldap_err2str(res, &errmsg);
873 syslog(LOG_ERR, errmsg);
876 if (result)
877 __ns_ldap_freeResult(&result);
878 if (*error == 0)
879 *error = ECOMM;
880 return (ldap_err(res));
882 if (result)
883 __ns_ldap_freeResult(&result);
885 return (__NSW_SUCCESS);
888 static int
889 readdir_callback(const ns_ldap_entry_t *entry, const void *udata)
891 char *key;
892 int key_len;
893 struct dir_cbdata *temp = (struct dir_cbdata *)udata;
894 struct dir_entry **list = temp->list;
895 struct dir_entry *last = temp->last;
896 int i;
898 if (trace > 1)
899 trace_prt(1, "readdir_callback called\n");
901 * For the current entry, obtain the value and length of the cn i.e. the
902 * contents of key and its key length.
904 key_len = 0;
905 key = NULL;
907 if (trace > 1)
908 trace_prt(1, "readdir_callback: entry->attr_count=[ %d ]\n",
909 entry->attr_count);
911 for (i = 0; i < entry->attr_count; i++) {
912 ns_ldap_attr_t *attr;
914 attr = entry->attr_pair[i];
916 if (trace > 1)
917 trace_prt(1,
918 "readdir_callback: attr->attrname=[ %s ]\n",
919 attr->attrname);
921 if (strcasecmp(attr->attrname, automountKey) == 0) {
922 if (encode)
923 key = tounix_str(attr->attrvalue[0]);
924 else
925 key = attr->attrvalue[0];
926 key_len = strlen(key);
928 if (trace > 1)
929 trace_prt(1,
930 "readdir_callback: key=[ %s ], key_len=[ %d ]\n",
931 key, key_len);
933 break;
937 if (key_len >= 100 || key_len < 2)
938 return (0);
940 if (isspace(*key) || *key == '#')
941 return (0);
944 * Wildcard entry should be ignored - following entries should continue
945 * to be read to corroborate with the way we search for entries in
946 * LDAP, i.e., first for an exact key match and then a wildcard
947 * if there's no exact key match.
949 if (key[0] == '*' && key[1] == '\0')
950 return (0);
952 if (add_dir_entry(key, list, &last)) {
953 temp->error = ENOMEM;
954 return (1);
957 temp->last = last;
958 temp->error = 0;
960 if (trace > 1)
961 trace_prt(1, "readdir_callback returning 0...\n");
963 return (0);
967 * Puts CAPCHAR in front of uppercase characters or surrounds a set of
968 * contiguous uppercase characters with CAPCHARS and square brackets.
970 * For example (assuming CAPCHAR = '%'):
972 * if str = Abc, it returns %Abc
973 * if str = ABc, it returns %[AB]c
974 * if str = AbC, it returns %Ab%C
977 static char *
978 tosunds_str(char *str)
980 static char buf[BUFSIZ];
981 int i, j, er = FALSE;
982 #ifdef NEWCAP
983 int openBracket = FALSE, closeBracket = FALSE;
984 #endif
986 (void) memset(buf, 0, BUFSIZ);
988 j = 0;
989 for (i = 0; i < strlen(str); i++) {
990 /* Check the current element */
991 if (isupper(str[i])) {
992 #ifdef NEWCAP
993 /* check the next element */
994 if (isupper(str[i+1])) {
995 if (openBracket == FALSE) {
996 openBracket = TRUE;
997 buf[j] = CAPCHAR;
998 buf[j+1] = '[';
999 j += 2;
1001 } else {
1002 if (openBracket == FALSE) {
1003 buf[j] = CAPCHAR;
1004 j++;
1005 } else {
1006 openBracket = FALSE;
1007 closeBracket = TRUE;
1010 #else
1011 buf[j++] = CAPCHAR;
1012 #endif
1014 buf[j] = str[i];
1015 j++;
1017 #ifdef NEWCAP
1018 if (closeBracket == TRUE) {
1019 closeBracket = FALSE;
1020 buf[j] = ']';
1021 j++;
1023 #endif
1024 if (j >= BUFSIZ) {
1025 er = TRUE;
1026 break;
1030 if (er) {
1031 syslog(LOG_ERR, "Buffer size exceeded.");
1032 (void) memset(buf, 0, BUFSIZ);
1033 } else
1034 buf[j] = '\0';
1036 return (buf);
1041 * Reverses what tosunds_str() did
1043 static char *
1044 tounix_str(char *str)
1046 static char buf[BUFSIZ];
1047 int i, j;
1048 int openBracket = FALSE;
1050 (void) memset(buf, 0, BUFSIZ);
1051 j = 0;
1053 for (i = 0; i < strlen(str); i++) {
1054 if (str[i] == '%') {
1055 if (isupper(str[i+1])) {
1056 i += 1;
1057 } else if ((str[i+1] == '[') && (isupper(str[i+2]))) {
1058 i += 2;
1059 openBracket = TRUE;
1061 } else if (str[i] == ']') {
1062 if ((isupper(str[i-1])) && (openBracket == TRUE))
1063 i += 1;
1064 openBracket = FALSE;
1066 buf[j] = str[i];
1067 j++;
1069 return (buf);