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
)
311 * Parse a service descriptor
312 * and create a service descriptor struct
314 * serviceid:[base][?[scope][?[filter]]];[[base][?[scope][?[filter]]]]
316 * [base][?[scope][?[filter]]]
319 typedef enum _ns_parse_state
{
320 P_ERROR
, P_INIT
, P_BASEDN
, P_SCOPE
,
321 P_INIFILTER
, P_FILTER
, P_END
, P_EXIT
, P_MEMERR
326 __s_api_parseASearchDesc(const char *service
,
327 char **cur
, ns_ldap_search_desc_t
**ret
)
329 ns_ldap_search_desc_t
*ptr
;
333 ns_ldap_error_t
**errorp
= NULL
;
334 ns_ldap_error_t
*error
= NULL
;
335 void **paramVal
= NULL
;
337 _ns_parse_state_t state
= P_INIT
;
343 return (NS_LDAP_INVALID_PARAM
);
346 return (NS_LDAP_INVALID_PARAM
);
348 ptr
= (ns_ldap_search_desc_t
*)
349 calloc(1, sizeof (ns_ldap_search_desc_t
));
351 return (NS_LDAP_MEMORY
);
355 /* Get the default scope */
356 if ((rc
= __ns_ldap_getParam(NS_LDAP_SEARCH_SCOPE_P
,
357 ¶mVal
, errorp
)) != NS_LDAP_SUCCESS
) {
358 (void) __ns_ldap_freeError(errorp
);
359 __ns_ldap_freeASearchDesc(ptr
);
361 return (NS_LDAP_MEMORY
);
363 if (paramVal
&& *paramVal
)
364 ptr
->scope
= * (ScopeType_t
*)(*paramVal
);
366 ptr
->scope
= NS_LDAP_SCOPE_ONELEVEL
;
367 (void) __ns_ldap_freeParam(¶mVal
);
370 for (/* none */; state
!= P_EXIT
&& sptr
&& *sptr
; sptr
++) {
374 if (*sptr
== QUESTTOK
) {
376 ptr
->basedn
= strdup("");
384 if (*sptr
== SEMITOK
) {
386 ptr
->basedn
= strdup("");
394 /* prepare to copy DN */
395 i
= strlen(sptr
) + 1;
396 ptr
->basedn
= dptr
= (char *)calloc(i
, sizeof (char));
401 if (*sptr
== BSLTOK
) {
402 if (*(sptr
+1) == '\0') {
407 if (*(sptr
+1) == QUOTETOK
||
408 *(sptr
+1) == BSLTOK
) {
415 } else if (*sptr
== QUOTETOK
) {
424 if (*sptr
== SEMITOK
) {
425 /* No filter and no more SSD */
429 /* prepare to copy DN */
430 i
= strlen(sptr
) + 1;
431 ptr
->filter
= dptr
= (char *)calloc(i
, sizeof (char));
436 if (*sptr
== BSLTOK
) {
437 if (*(sptr
+1) == '\0') {
442 if (*(sptr
+1) == QUOTETOK
||
443 *(sptr
+1) == BSLTOK
) {
450 } else if (*sptr
== QUOTETOK
) {
460 if (*sptr
== SEMITOK
) {
465 if (strncasecmp(sptr
, "base", 4) == 0) {
467 ptr
->scope
= NS_LDAP_SCOPE_BASE
;
468 } else if (strncasecmp(sptr
, "one", 3) == 0) {
469 ptr
->scope
= NS_LDAP_SCOPE_ONELEVEL
;
471 } else if (strncasecmp(sptr
, "sub", 3) == 0) {
472 ptr
->scope
= NS_LDAP_SCOPE_SUBTREE
;
475 if (*sptr
== '\0' || (*sptr
== SEMITOK
)) {
481 if (*sptr
!= QUESTTOK
) {
493 if (*sptr
== BSLTOK
) {
494 if (*(sptr
+1) == '\0') {
498 if (*(sptr
+1) == QUOTETOK
||
499 *(sptr
+1) == BSLTOK
) {
505 /* fall through to char copy */
506 } else if (*sptr
== QUOTETOK
) {
512 /* else fall through to char copy */
515 if (wasquoted
&& *sptr
!= QUESTTOK
) {
516 /* error past end of quoted string */
520 if (*sptr
== BSLTOK
) {
521 if (*(sptr
+1) == '\0') {
525 if (*(sptr
+1) == SEMITOK
||
526 *(sptr
+1) == QUESTTOK
||
527 *(sptr
+1) == QUOTETOK
||
528 *(sptr
+1) == BSLTOK
) {
532 /* fall through to char copy */
533 } else if (*sptr
== QUOTETOK
) {
537 } else if (*sptr
== QUESTTOK
) {
538 /* if filter error */
539 if (state
== P_FILTER
) {
543 /* end of basedn goto scope */
547 } else if (*sptr
== SEMITOK
) {
548 /* end of current SSD */
554 /* normal character to copy */
558 if (*sptr
== SEMITOK
) {
562 __ns_ldap_freeASearchDesc(ptr
);
565 return (NS_LDAP_CONFIG
);
566 default: /* error should never arrive here */
568 __ns_ldap_freeASearchDesc(ptr
);
571 return (NS_LDAP_CONFIG
);
573 __ns_ldap_freeASearchDesc(ptr
);
576 return (NS_LDAP_MEMORY
);
581 __ns_ldap_freeASearchDesc(ptr
);
584 return (NS_LDAP_INVALID_PARAM
);
587 if (empty
|| strlen(ptr
->basedn
) == 0) {
590 /* get default base */
591 rc
= __s_api_getDNs(&dns
, service
, &error
);
592 if (rc
!= NS_LDAP_SUCCESS
) {
594 __s_api_free2dArray(dns
);
597 (void) __ns_ldap_freeError(&error
);
598 __ns_ldap_freeASearchDesc(ptr
);
600 return (NS_LDAP_MEMORY
);
602 ptr
->basedn
= strdup(dns
[0]);
603 __s_api_free2dArray(dns
);
609 return (NS_LDAP_SUCCESS
);
614 * Build up the service descriptor array
616 #define NS_SDESC_MAX 4
619 __ns_ldap_saveSearchDesc(ns_ldap_search_desc_t
***sdlist
,
620 int *cnt
, int *max
, ns_ldap_search_desc_t
*ret
)
622 ns_ldap_search_desc_t
**tmplist
;
624 if (*sdlist
== NULL
) {
627 *sdlist
= (ns_ldap_search_desc_t
**)
628 calloc(*max
, sizeof (ns_ldap_search_desc_t
*));
631 } else if (*cnt
+1 >= *max
) {
632 *max
+= NS_SDESC_MAX
;
633 tmplist
= (ns_ldap_search_desc_t
**)
634 realloc((void *)(*sdlist
),
635 *max
* sizeof (ns_ldap_search_desc_t
*));
641 (*sdlist
)[*cnt
] = ret
;
643 (*sdlist
)[*cnt
] = NULL
;
649 * Exported Search Descriptor Routines
652 int __ns_ldap_getSearchDescriptors(
654 ns_ldap_search_desc_t
***desc
,
655 ns_ldap_error_t
**errorp
)
660 void **paramVal
= NULL
;
661 char **sdl
, *srv
, **sdl_save
;
662 char errstr
[2 * MAXERROR
];
663 ns_ldap_search_desc_t
**sdlist
;
667 ns_ldap_search_desc_t
*ret
;
669 if ((desc
== NULL
) || (errorp
== NULL
))
670 return (NS_LDAP_INVALID_PARAM
);
675 rc
= __ns_ldap_getParam(NS_LDAP_SERVICE_SEARCH_DESC_P
,
676 (void ***)¶m
, errorp
);
677 if (rc
!= NS_LDAP_SUCCESS
) {
680 sdl
= (char **)param
;
685 cfg
= __s_api_get_default_config();
688 (void) snprintf(errstr
, sizeof (errstr
),
689 gettext("No configuration information available."));
690 MKERROR(LOG_ERR
, *errorp
, NS_CONFIG_NOTLOADED
, strdup(errstr
),
692 return (NS_LDAP_CONFIG
);
696 __s_api_release_config(cfg
);
698 /* If using version1 or no sd's process SEARCH_DN if available */
699 if (vers
== NS_LDAP_V1
&& param
== NULL
) {
700 rc
= __s_api_get_search_DNs_v1(&sdl
, service
, errorp
);
701 if (rc
!= NS_LDAP_SUCCESS
|| sdl
== NULL
) {
705 /* Convert a SEARCH_DN to a search descriptor */
706 for (; *sdl
; sdl
++) {
707 ret
= (ns_ldap_search_desc_t
*)
708 calloc(1, sizeof (ns_ldap_search_desc_t
));
710 (void) __ns_ldap_freeSearchDescriptors(&sdlist
);
711 __s_api_free2dArray(sdl_save
);
712 return (NS_LDAP_MEMORY
);
714 ret
->basedn
= strdup(*sdl
);
715 if (ret
->basedn
== NULL
) {
717 (void) __ns_ldap_freeASearchDesc(ret
);
718 (void) __ns_ldap_freeSearchDescriptors(&sdlist
);
719 __s_api_free2dArray(sdl_save
);
720 return (NS_LDAP_MEMORY
);
724 if ((rc
= __ns_ldap_getParam(NS_LDAP_SEARCH_SCOPE_P
,
725 ¶mVal
, errorp
)) != NS_LDAP_SUCCESS
) {
726 (void) __ns_ldap_freeASearchDesc(ret
);
727 (void) __ns_ldap_freeSearchDescriptors(&sdlist
);
728 __s_api_free2dArray(sdl_save
);
731 if (paramVal
&& *paramVal
)
732 ret
->scope
= * (ScopeType_t
*)(*paramVal
);
734 ret
->scope
= NS_LDAP_SCOPE_ONELEVEL
;
735 (void) __ns_ldap_freeParam(¶mVal
);
738 rc
= __ns_ldap_saveSearchDesc(&sdlist
, &cnt
, &max
, ret
);
740 (void) __ns_ldap_freeASearchDesc(ret
);
741 (void) __ns_ldap_freeSearchDescriptors(&sdlist
);
742 __s_api_free2dArray(sdl_save
);
743 return (NS_LDAP_MEMORY
);
746 __s_api_free2dArray(sdl_save
);
748 return (NS_LDAP_SUCCESS
);
751 if (sdl
== NULL
|| service
== NULL
) {
752 (void) __ns_ldap_freeParam(¶m
);
755 return (NS_LDAP_SUCCESS
);
757 slen
= strlen(service
);
759 /* Process the version2 sd's */
760 for (; *sdl
; sdl
++) {
762 if (strncasecmp(service
, srv
, slen
) != 0)
765 if (*srv
!= COLONTOK
)
768 while (srv
!= NULL
&& *srv
!= NULL
) {
770 rc
= __s_api_parseASearchDesc(service
, &srv
, &ret
);
771 if (rc
!= NS_LDAP_SUCCESS
) {
772 (void) __ns_ldap_freeSearchDescriptors(&sdlist
);
773 (void) snprintf(errstr
, (2 * MAXERROR
), gettext(
774 "Invalid serviceSearchDescriptor (%s). "
775 "Illegal configuration"), *sdl
);
776 (void) __ns_ldap_freeParam(¶m
);
778 MKERROR(LOG_ERR
, *errorp
, NS_CONFIG_SYNTAX
,
779 strdup(errstr
), NULL
);
783 rc
= __ns_ldap_saveSearchDesc(
784 &sdlist
, &cnt
, &max
, ret
);
787 (void) __ns_ldap_freeSearchDescriptors(&sdlist
);
788 (void) __ns_ldap_freeParam(¶m
);
790 return (NS_LDAP_MEMORY
);
795 (void) __ns_ldap_freeParam(¶m
);
798 return (NS_LDAP_SUCCESS
);
802 __ns_ldap_freeSearchDescriptors(ns_ldap_search_desc_t
***desc
)
804 ns_ldap_search_desc_t
**dptr
;
805 ns_ldap_search_desc_t
*ptr
;
808 return (NS_LDAP_SUCCESS
);
809 for (dptr
= *desc
; (ptr
= *dptr
) != NULL
; dptr
++) {
810 __ns_ldap_freeASearchDesc(ptr
);
815 return (NS_LDAP_SUCCESS
);
822 * Exported Attribute/Objectclass mapping functions.
826 * This function is not supported.
829 int __ns_ldap_getAttributeMaps(
831 ns_ldap_attribute_map_t
***maps
,
832 ns_ldap_error_t
**errorp
)
835 return (NS_LDAP_OP_FAILED
);
839 __ns_ldap_freeAttributeMaps(ns_ldap_attribute_map_t
***maps
)
841 ns_ldap_attribute_map_t
**dptr
;
842 ns_ldap_attribute_map_t
*ptr
;
846 return (NS_LDAP_SUCCESS
);
847 for (dptr
= *maps
; (ptr
= *dptr
) != NULL
; dptr
++) {
850 ptr
->origAttr
= NULL
;
852 if (ptr
->mappedAttr
) {
853 for (cpp
= ptr
->mappedAttr
; (cp
= *cpp
) != NULL
; cpp
++)
855 free(ptr
->mappedAttr
);
856 ptr
->mappedAttr
= NULL
;
863 return (NS_LDAP_SUCCESS
);
866 char **__ns_ldap_getMappedAttributes(
868 const char *origAttribute
)
870 ns_config_t
*ptr
= __s_api_loadrefresh_config();
877 hp
= ns_get_hash(ptr
, NS_HASH_AMAP
, service
, origAttribute
);
879 if (hp
== NULL
|| hp
->h_map
== NULL
)
882 ret
= __s_api_cp2dArray(hp
->h_map
->map
);
883 __s_api_release_config(ptr
);
887 char **__ns_ldap_getOrigAttribute(
889 const char *mappedAttribute
)
891 ns_config_t
*ptr
= __s_api_loadrefresh_config();
898 hp
= ns_get_hash(ptr
, NS_HASH_RAMAP
, service
, mappedAttribute
);
900 if (hp
== NULL
|| hp
->h_map
== NULL
)
903 ret
= __s_api_cp2dArray(hp
->h_map
->map
);
904 __s_api_release_config(ptr
);
909 * This function is not supported.
912 int __ns_ldap_getObjectClassMaps(
914 ns_ldap_objectclass_map_t
***maps
,
915 ns_ldap_error_t
**errorp
)
918 return (NS_LDAP_OP_FAILED
);
922 __ns_ldap_freeObjectClassMaps(ns_ldap_objectclass_map_t
***maps
)
924 ns_ldap_objectclass_map_t
**dptr
;
925 ns_ldap_objectclass_map_t
*ptr
;
928 return (NS_LDAP_SUCCESS
);
929 for (dptr
= *maps
; (ptr
= *dptr
) != NULL
; dptr
++) {
936 ptr
->mappedOC
= NULL
;
943 return (NS_LDAP_SUCCESS
);
946 char **__ns_ldap_getMappedObjectClass(
948 const char *origObjectClass
)
950 ns_config_t
*ptr
= __s_api_loadrefresh_config();
957 hp
= ns_get_hash(ptr
, NS_HASH_OMAP
, service
, origObjectClass
);
959 if (hp
== NULL
|| hp
->h_map
== NULL
)
962 ret
= __s_api_cp2dArray(hp
->h_map
->map
);
963 __s_api_release_config(ptr
);
967 char **__ns_ldap_getOrigObjectClass(
969 const char *mappedObjectClass
)
971 ns_config_t
*ptr
= __s_api_loadrefresh_config();
978 hp
= ns_get_hash(ptr
, NS_HASH_ROMAP
, service
, mappedObjectClass
);
980 if (hp
== NULL
|| hp
->h_map
== NULL
)
983 ret
= __s_api_cp2dArray(hp
->h_map
->map
);
984 __s_api_release_config(ptr
);
988 char **__ns_ldap_mapAttributeList(
990 const char * const *origAttrList
)
992 const char * const *opp
;
996 if (origAttrList
== NULL
)
1000 for (i
= 0; *opp
; i
++, opp
++)
1002 cpp
= (char **)calloc(i
+1, sizeof (char *));
1007 for (i
= 0; *opp
; i
++, opp
++) {
1008 npp
= __ns_ldap_getMappedAttributes(service
, *opp
);
1009 if (npp
&& npp
[0]) {
1010 cpp
[i
] = strdup(npp
[0]);
1011 __s_api_free2dArray(npp
);
1013 if (cpp
[i
] == NULL
) {
1014 __s_api_free2dArray(cpp
);
1018 cpp
[i
] = strdup(*opp
);
1019 if (cpp
[i
] == NULL
) {
1020 __s_api_free2dArray(cpp
);
1029 __ns_ldap_mapAttribute(
1030 const char *service
,
1031 const char *origAttr
)
1036 if (origAttr
== NULL
)
1039 npp
= __ns_ldap_getMappedAttributes(service
, origAttr
);
1040 if (npp
&& npp
[0]) {
1041 mappedAttr
= strdup(npp
[0]);
1042 __s_api_free2dArray(npp
);
1044 mappedAttr
= strdup(origAttr
);
1046 return (mappedAttr
);