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]
22 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
30 #include "ns_internal.h"
33 * Calculate a hash for a string
34 * Based on elf_hash algorithm, hash is case insensitive
35 * Uses tolower instead of _tolower because of I18N
39 ns_hash(const char *str
)
41 unsigned int hval
= 0;
46 hval
= (hval
<< 4) + tolower(*str
++);
47 if ((g
= (hval
& 0xf0000000)) != 0)
51 return ((unsigned long)hval
);
55 * Scan a hash table hit for a matching hash entry.
56 * Assume service and str are non-NULL.
60 ns_scan_hash(ns_hashtype_t type
, const char *service
,
61 const char *str
, ns_hash_t
*idx
)
64 if (idx
->h_type
== type
&&
65 strcasecmp(service
, idx
->h_map
->service
) == 0 &&
66 strcasecmp(str
, idx
->h_map
->orig
) == 0) {
71 return ((ns_hash_t
*)NULL
);
75 * Find an entry in the hash table
79 ns_get_hash(const ns_config_t
*config
,
80 ns_hashtype_t type
, const char *service
, const char *str
)
82 ns_hash_t
*idx
, *hashp
;
85 if (config
== NULL
|| service
== NULL
|| str
== NULL
)
88 hash
= ns_hash(str
) % NS_HASH_MAX
;
89 idx
= config
->hashTbl
[hash
];
90 hashp
= ns_scan_hash(type
, service
, str
, idx
);
100 ns_free_map(ns_mapping_t
*mapp
)
108 mapp
->service
= NULL
;
115 for (ptr
= mapp
->map
; *ptr
; ptr
++)
124 * Remove a hash table entry.
125 * This function is not MT safe.
129 ns_free_hash(ns_hash_t
*p
)
142 * destroy the hash table.
143 * This function is not MT safe.
147 __s_api_destroy_hash(ns_config_t
*config
)
154 for (i
= 0; i
< NS_HASH_MAX
; i
++) {
155 next
= config
->hashTbl
[i
];
156 while (next
!= NULL
) {
157 next
= ns_free_hash(next
);
159 config
->hashTbl
[i
] = NULL
;
164 * Add a hash entry to the hash table.
165 * This function is not MT safe.
166 * Assume map, map->orig, map->service are non-NULL.
170 __s_api_add_map2hash(ns_config_t
*config
, ns_hashtype_t type
,
173 ns_hash_t
*idx
, *newp
;
177 return (NS_HASH_RC_CONFIG_ERROR
);
179 hash
= ns_hash(map
->orig
) % NS_HASH_MAX
;
180 idx
= config
->hashTbl
[hash
];
182 ns_scan_hash(type
, map
->service
, map
->orig
, idx
) != NULL
) {
183 return (NS_HASH_RC_EXISTED
);
186 newp
= (ns_hash_t
*)malloc(sizeof (ns_hash_t
));
188 return (NS_HASH_RC_NO_MEMORY
);
192 config
->hashTbl
[hash
] = newp
;
193 newp
->h_llnext
= config
->llHead
;
194 config
->llHead
= newp
;
195 return (NS_HASH_RC_SUCCESS
);
200 * Parse an attribute map string.
201 * Assume space is the only legal whitespace.
202 * attributeMap syntax:
203 * attributeMap = serviceId ":" origAttribute "="
205 * origAttribute = attribute
206 * attributes = wattribute *( space wattribute )
207 * wattribute = whsp newAttribute whsp
208 * newAttribute = descr | "*NULL*"
211 * objectclassMap syntax:
212 * objectclassMap = serviceId ":" origObjectclass "="
214 * origObjectclass = objectclass
215 * objectclass = keystring
219 __s_api_parse_map(char *cp
, char **sid
, char **origA
, char ***mapA
)
221 char *sptr
, *dptr
, **mapp
;
229 dptr
= strchr(sptr
, COLONTOK
);
231 return (NS_HASH_RC_SYNTAX_ERROR
);
233 *sid
= (char *)malloc(i
);
235 return (NS_HASH_RC_NO_MEMORY
);
236 (void) strlcpy(*sid
, sptr
, i
);
239 dptr
= strchr(sptr
, TOKENSEPARATOR
);
243 return (NS_HASH_RC_SYNTAX_ERROR
);
246 *origA
= (char *)malloc(i
);
247 if (*origA
== NULL
) {
250 return (NS_HASH_RC_NO_MEMORY
);
252 (void) strlcpy(*origA
, sptr
, i
);
256 for (dptr
= sptr
; *dptr
; dptr
++) {
257 if (*dptr
== SPACETOK
) {
259 while (*(dptr
+1) == SPACETOK
)
263 *mapA
= (char **)calloc(max
+1, sizeof (char *));
269 return (NS_HASH_RC_NO_MEMORY
);
274 while (*sptr
== SPACETOK
)
277 while (*dptr
&& *dptr
!= SPACETOK
)
280 *mapp
= (char *)malloc(i
);
286 __s_api_free2dArray(*mapA
);
288 return (NS_HASH_RC_NO_MEMORY
);
290 (void) strlcpy(*mapp
, sptr
, i
);
294 return (NS_HASH_RC_SUCCESS
);
299 __ns_ldap_freeASearchDesc(ns_ldap_search_desc_t
*ptr
)
309 * Parse a service descriptor
310 * and create a service descriptor struct
312 * serviceid:[base][?[scope][?[filter]]];[[base][?[scope][?[filter]]]]
314 * [base][?[scope][?[filter]]]
317 typedef enum _ns_parse_state
{
318 P_ERROR
, P_INIT
, P_BASEDN
, P_SCOPE
,
319 P_INIFILTER
, P_FILTER
, P_END
, P_EXIT
, P_MEMERR
324 __s_api_parseASearchDesc(const char *service
,
325 char **cur
, ns_ldap_search_desc_t
**ret
)
327 ns_ldap_search_desc_t
*ptr
;
330 ns_ldap_error_t
**errorp
= NULL
;
331 ns_ldap_error_t
*error
= NULL
;
332 void **paramVal
= NULL
;
334 _ns_parse_state_t state
= P_INIT
;
340 return (NS_LDAP_INVALID_PARAM
);
343 return (NS_LDAP_INVALID_PARAM
);
345 ptr
= (ns_ldap_search_desc_t
*)
346 calloc(1, sizeof (ns_ldap_search_desc_t
));
348 return (NS_LDAP_MEMORY
);
352 /* Get the default scope */
353 if ((rc
= __ns_ldap_getParam(NS_LDAP_SEARCH_SCOPE_P
,
354 ¶mVal
, errorp
)) != NS_LDAP_SUCCESS
) {
355 (void) __ns_ldap_freeError(errorp
);
356 __ns_ldap_freeASearchDesc(ptr
);
358 return (NS_LDAP_MEMORY
);
360 if (paramVal
&& *paramVal
)
361 ptr
->scope
= * (ScopeType_t
*)(*paramVal
);
363 ptr
->scope
= NS_LDAP_SCOPE_ONELEVEL
;
364 (void) __ns_ldap_freeParam(¶mVal
);
367 for (/* none */; state
!= P_EXIT
&& sptr
&& *sptr
; sptr
++) {
371 if (*sptr
== QUESTTOK
) {
373 ptr
->basedn
= strdup("");
381 if (*sptr
== SEMITOK
) {
383 ptr
->basedn
= strdup("");
391 /* prepare to copy DN */
392 i
= strlen(sptr
) + 1;
393 ptr
->basedn
= dptr
= (char *)calloc(i
, sizeof (char));
398 if (*sptr
== BSLTOK
) {
399 if (*(sptr
+1) == '\0') {
404 if (*(sptr
+1) == QUOTETOK
||
405 *(sptr
+1) == BSLTOK
) {
412 } else if (*sptr
== QUOTETOK
) {
421 if (*sptr
== SEMITOK
) {
422 /* No filter and no more SSD */
426 /* prepare to copy DN */
427 i
= strlen(sptr
) + 1;
428 ptr
->filter
= dptr
= (char *)calloc(i
, sizeof (char));
433 if (*sptr
== BSLTOK
) {
434 if (*(sptr
+1) == '\0') {
439 if (*(sptr
+1) == QUOTETOK
||
440 *(sptr
+1) == BSLTOK
) {
447 } else if (*sptr
== QUOTETOK
) {
456 if (*sptr
== SEMITOK
) {
461 if (strncasecmp(sptr
, "base", 4) == 0) {
463 ptr
->scope
= NS_LDAP_SCOPE_BASE
;
464 } else if (strncasecmp(sptr
, "one", 3) == 0) {
465 ptr
->scope
= NS_LDAP_SCOPE_ONELEVEL
;
467 } else if (strncasecmp(sptr
, "sub", 3) == 0) {
468 ptr
->scope
= NS_LDAP_SCOPE_SUBTREE
;
471 if (*sptr
== '\0' || (*sptr
== SEMITOK
)) {
477 if (*sptr
!= QUESTTOK
) {
489 if (*sptr
== BSLTOK
) {
490 if (*(sptr
+1) == '\0') {
494 if (*(sptr
+1) == QUOTETOK
||
495 *(sptr
+1) == BSLTOK
) {
501 /* fall through to char copy */
502 } else if (*sptr
== QUOTETOK
) {
508 /* else fall through to char copy */
511 if (wasquoted
&& *sptr
!= QUESTTOK
) {
512 /* error past end of quoted string */
516 if (*sptr
== BSLTOK
) {
517 if (*(sptr
+1) == '\0') {
521 if (*(sptr
+1) == SEMITOK
||
522 *(sptr
+1) == QUESTTOK
||
523 *(sptr
+1) == QUOTETOK
||
524 *(sptr
+1) == BSLTOK
) {
528 /* fall through to char copy */
529 } else if (*sptr
== QUOTETOK
) {
533 } else if (*sptr
== QUESTTOK
) {
534 /* if filter error */
535 if (state
== P_FILTER
) {
539 /* end of basedn goto scope */
543 } else if (*sptr
== SEMITOK
) {
544 /* end of current SSD */
550 /* normal character to copy */
554 if (*sptr
== SEMITOK
) {
558 __ns_ldap_freeASearchDesc(ptr
);
561 return (NS_LDAP_CONFIG
);
562 default: /* error should never arrive here */
564 __ns_ldap_freeASearchDesc(ptr
);
567 return (NS_LDAP_CONFIG
);
569 __ns_ldap_freeASearchDesc(ptr
);
572 return (NS_LDAP_MEMORY
);
577 __ns_ldap_freeASearchDesc(ptr
);
580 return (NS_LDAP_INVALID_PARAM
);
583 if (empty
|| strlen(ptr
->basedn
) == 0) {
585 /* get default base */
586 rc
= __s_api_getDNs(&dns
, service
, &error
);
587 if (rc
!= NS_LDAP_SUCCESS
) {
589 __s_api_free2dArray(dns
);
592 (void) __ns_ldap_freeError(&error
);
593 __ns_ldap_freeASearchDesc(ptr
);
595 return (NS_LDAP_MEMORY
);
597 ptr
->basedn
= strdup(dns
[0]);
598 __s_api_free2dArray(dns
);
604 return (NS_LDAP_SUCCESS
);
609 * Build up the service descriptor array
611 #define NS_SDESC_MAX 4
614 __ns_ldap_saveSearchDesc(ns_ldap_search_desc_t
***sdlist
,
615 int *cnt
, int *max
, ns_ldap_search_desc_t
*ret
)
617 ns_ldap_search_desc_t
**tmplist
;
619 if (*sdlist
== NULL
) {
622 *sdlist
= (ns_ldap_search_desc_t
**)
623 calloc(*max
, sizeof (ns_ldap_search_desc_t
*));
626 } else if (*cnt
+1 >= *max
) {
627 *max
+= NS_SDESC_MAX
;
628 tmplist
= (ns_ldap_search_desc_t
**)
629 reallocarray(*sdlist
, *max
,
630 sizeof (ns_ldap_search_desc_t
*));
636 (*sdlist
)[*cnt
] = ret
;
638 (*sdlist
)[*cnt
] = NULL
;
644 * Exported Search Descriptor Routines
647 int __ns_ldap_getSearchDescriptors(
649 ns_ldap_search_desc_t
***desc
,
650 ns_ldap_error_t
**errorp
)
655 void **paramVal
= NULL
;
656 char **sdl
, *srv
, **sdl_save
;
657 char errstr
[2 * MAXERROR
];
658 ns_ldap_search_desc_t
**sdlist
;
662 ns_ldap_search_desc_t
*ret
;
664 if ((desc
== NULL
) || (errorp
== NULL
))
665 return (NS_LDAP_INVALID_PARAM
);
670 rc
= __ns_ldap_getParam(NS_LDAP_SERVICE_SEARCH_DESC_P
,
671 (void ***)¶m
, errorp
);
672 if (rc
!= NS_LDAP_SUCCESS
) {
675 sdl
= (char **)param
;
680 cfg
= __s_api_get_default_config();
683 (void) snprintf(errstr
, sizeof (errstr
),
684 gettext("No configuration information available."));
685 MKERROR(LOG_ERR
, *errorp
, NS_CONFIG_NOTLOADED
, strdup(errstr
),
687 return (NS_LDAP_CONFIG
);
691 __s_api_release_config(cfg
);
693 /* If using version1 or no sd's process SEARCH_DN if available */
694 if (vers
== NS_LDAP_V1
&& param
== NULL
) {
695 rc
= __s_api_get_search_DNs_v1(&sdl
, service
, errorp
);
696 if (rc
!= NS_LDAP_SUCCESS
|| sdl
== NULL
) {
700 /* Convert a SEARCH_DN to a search descriptor */
701 for (; *sdl
; sdl
++) {
702 ret
= (ns_ldap_search_desc_t
*)
703 calloc(1, sizeof (ns_ldap_search_desc_t
));
705 (void) __ns_ldap_freeSearchDescriptors(&sdlist
);
706 __s_api_free2dArray(sdl_save
);
707 return (NS_LDAP_MEMORY
);
709 ret
->basedn
= strdup(*sdl
);
710 if (ret
->basedn
== NULL
) {
712 (void) __ns_ldap_freeASearchDesc(ret
);
713 (void) __ns_ldap_freeSearchDescriptors(&sdlist
);
714 __s_api_free2dArray(sdl_save
);
715 return (NS_LDAP_MEMORY
);
719 if ((rc
= __ns_ldap_getParam(NS_LDAP_SEARCH_SCOPE_P
,
720 ¶mVal
, errorp
)) != NS_LDAP_SUCCESS
) {
721 (void) __ns_ldap_freeASearchDesc(ret
);
722 (void) __ns_ldap_freeSearchDescriptors(&sdlist
);
723 __s_api_free2dArray(sdl_save
);
726 if (paramVal
&& *paramVal
)
727 ret
->scope
= * (ScopeType_t
*)(*paramVal
);
729 ret
->scope
= NS_LDAP_SCOPE_ONELEVEL
;
730 (void) __ns_ldap_freeParam(¶mVal
);
733 rc
= __ns_ldap_saveSearchDesc(&sdlist
, &cnt
, &max
, ret
);
735 (void) __ns_ldap_freeASearchDesc(ret
);
736 (void) __ns_ldap_freeSearchDescriptors(&sdlist
);
737 __s_api_free2dArray(sdl_save
);
738 return (NS_LDAP_MEMORY
);
741 __s_api_free2dArray(sdl_save
);
743 return (NS_LDAP_SUCCESS
);
746 if (sdl
== NULL
|| service
== NULL
) {
747 (void) __ns_ldap_freeParam(¶m
);
750 return (NS_LDAP_SUCCESS
);
752 slen
= strlen(service
);
754 /* Process the version2 sd's */
755 for (; *sdl
; sdl
++) {
757 if (strncasecmp(service
, srv
, slen
) != 0)
760 if (*srv
!= COLONTOK
)
763 while (srv
!= NULL
&& *srv
!= '\0') {
765 rc
= __s_api_parseASearchDesc(service
, &srv
, &ret
);
766 if (rc
!= NS_LDAP_SUCCESS
) {
767 (void) __ns_ldap_freeSearchDescriptors(&sdlist
);
768 (void) snprintf(errstr
, (2 * MAXERROR
), gettext(
769 "Invalid serviceSearchDescriptor (%s). "
770 "Illegal configuration"), *sdl
);
771 (void) __ns_ldap_freeParam(¶m
);
773 MKERROR(LOG_ERR
, *errorp
, NS_CONFIG_SYNTAX
,
778 rc
= __ns_ldap_saveSearchDesc(
779 &sdlist
, &cnt
, &max
, ret
);
782 (void) __ns_ldap_freeSearchDescriptors(&sdlist
);
783 (void) __ns_ldap_freeParam(¶m
);
785 return (NS_LDAP_MEMORY
);
790 (void) __ns_ldap_freeParam(¶m
);
793 return (NS_LDAP_SUCCESS
);
797 __ns_ldap_freeSearchDescriptors(ns_ldap_search_desc_t
***desc
)
799 ns_ldap_search_desc_t
**dptr
;
800 ns_ldap_search_desc_t
*ptr
;
803 return (NS_LDAP_SUCCESS
);
804 for (dptr
= *desc
; (ptr
= *dptr
) != NULL
; dptr
++) {
805 __ns_ldap_freeASearchDesc(ptr
);
810 return (NS_LDAP_SUCCESS
);
817 * Exported Attribute/Objectclass mapping functions.
821 * This function is not supported.
824 int __ns_ldap_getAttributeMaps(
826 ns_ldap_attribute_map_t
***maps
,
827 ns_ldap_error_t
**errorp
)
830 return (NS_LDAP_OP_FAILED
);
834 __ns_ldap_freeAttributeMaps(ns_ldap_attribute_map_t
***maps
)
836 ns_ldap_attribute_map_t
**dptr
;
837 ns_ldap_attribute_map_t
*ptr
;
841 return (NS_LDAP_SUCCESS
);
842 for (dptr
= *maps
; (ptr
= *dptr
) != NULL
; dptr
++) {
845 ptr
->origAttr
= NULL
;
847 if (ptr
->mappedAttr
) {
848 for (cpp
= ptr
->mappedAttr
; (cp
= *cpp
) != NULL
; cpp
++)
850 free(ptr
->mappedAttr
);
851 ptr
->mappedAttr
= NULL
;
858 return (NS_LDAP_SUCCESS
);
861 char **__ns_ldap_getMappedAttributes(
863 const char *origAttribute
)
865 ns_config_t
*ptr
= __s_api_loadrefresh_config();
872 hp
= ns_get_hash(ptr
, NS_HASH_AMAP
, service
, origAttribute
);
874 if (hp
== NULL
|| hp
->h_map
== NULL
)
877 ret
= __s_api_cp2dArray(hp
->h_map
->map
);
878 __s_api_release_config(ptr
);
882 char **__ns_ldap_getOrigAttribute(
884 const char *mappedAttribute
)
886 ns_config_t
*ptr
= __s_api_loadrefresh_config();
893 hp
= ns_get_hash(ptr
, NS_HASH_RAMAP
, service
, mappedAttribute
);
895 if (hp
== NULL
|| hp
->h_map
== NULL
)
898 ret
= __s_api_cp2dArray(hp
->h_map
->map
);
899 __s_api_release_config(ptr
);
904 * This function is not supported.
907 int __ns_ldap_getObjectClassMaps(
909 ns_ldap_objectclass_map_t
***maps
,
910 ns_ldap_error_t
**errorp
)
913 return (NS_LDAP_OP_FAILED
);
917 __ns_ldap_freeObjectClassMaps(ns_ldap_objectclass_map_t
***maps
)
919 ns_ldap_objectclass_map_t
**dptr
;
920 ns_ldap_objectclass_map_t
*ptr
;
923 return (NS_LDAP_SUCCESS
);
924 for (dptr
= *maps
; (ptr
= *dptr
) != NULL
; dptr
++) {
931 ptr
->mappedOC
= NULL
;
938 return (NS_LDAP_SUCCESS
);
941 char **__ns_ldap_getMappedObjectClass(
943 const char *origObjectClass
)
945 ns_config_t
*ptr
= __s_api_loadrefresh_config();
952 hp
= ns_get_hash(ptr
, NS_HASH_OMAP
, service
, origObjectClass
);
954 if (hp
== NULL
|| hp
->h_map
== NULL
)
957 ret
= __s_api_cp2dArray(hp
->h_map
->map
);
958 __s_api_release_config(ptr
);
962 char **__ns_ldap_getOrigObjectClass(
964 const char *mappedObjectClass
)
966 ns_config_t
*ptr
= __s_api_loadrefresh_config();
973 hp
= ns_get_hash(ptr
, NS_HASH_ROMAP
, service
, mappedObjectClass
);
975 if (hp
== NULL
|| hp
->h_map
== NULL
)
978 ret
= __s_api_cp2dArray(hp
->h_map
->map
);
979 __s_api_release_config(ptr
);
983 char **__ns_ldap_mapAttributeList(
985 const char * const *origAttrList
)
987 const char * const *opp
;
991 if (origAttrList
== NULL
)
995 for (i
= 0; *opp
; i
++, opp
++)
997 cpp
= (char **)calloc(i
+1, sizeof (char *));
1002 for (i
= 0; *opp
; i
++, opp
++) {
1003 npp
= __ns_ldap_getMappedAttributes(service
, *opp
);
1004 if (npp
&& npp
[0]) {
1005 cpp
[i
] = strdup(npp
[0]);
1006 __s_api_free2dArray(npp
);
1008 if (cpp
[i
] == NULL
) {
1009 __s_api_free2dArray(cpp
);
1013 cpp
[i
] = strdup(*opp
);
1014 if (cpp
[i
] == NULL
) {
1015 __s_api_free2dArray(cpp
);
1024 __ns_ldap_mapAttribute(
1025 const char *service
,
1026 const char *origAttr
)
1031 if (origAttr
== NULL
)
1034 npp
= __ns_ldap_getMappedAttributes(service
, origAttr
);
1035 if (npp
&& npp
[0]) {
1036 mappedAttr
= strdup(npp
[0]);
1037 __s_api_free2dArray(npp
);
1039 mappedAttr
= strdup(origAttr
);
1041 return (mappedAttr
);