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
;
331 ns_ldap_error_t
**errorp
= NULL
;
332 ns_ldap_error_t
*error
= NULL
;
333 void **paramVal
= NULL
;
335 _ns_parse_state_t state
= P_INIT
;
341 return (NS_LDAP_INVALID_PARAM
);
344 return (NS_LDAP_INVALID_PARAM
);
346 ptr
= (ns_ldap_search_desc_t
*)
347 calloc(1, sizeof (ns_ldap_search_desc_t
));
349 return (NS_LDAP_MEMORY
);
353 /* Get the default scope */
354 if ((rc
= __ns_ldap_getParam(NS_LDAP_SEARCH_SCOPE_P
,
355 ¶mVal
, errorp
)) != NS_LDAP_SUCCESS
) {
356 (void) __ns_ldap_freeError(errorp
);
357 __ns_ldap_freeASearchDesc(ptr
);
359 return (NS_LDAP_MEMORY
);
361 if (paramVal
&& *paramVal
)
362 ptr
->scope
= * (ScopeType_t
*)(*paramVal
);
364 ptr
->scope
= NS_LDAP_SCOPE_ONELEVEL
;
365 (void) __ns_ldap_freeParam(¶mVal
);
368 for (/* none */; state
!= P_EXIT
&& sptr
&& *sptr
; sptr
++) {
372 if (*sptr
== QUESTTOK
) {
374 ptr
->basedn
= strdup("");
382 if (*sptr
== SEMITOK
) {
384 ptr
->basedn
= strdup("");
392 /* prepare to copy DN */
393 i
= strlen(sptr
) + 1;
394 ptr
->basedn
= dptr
= (char *)calloc(i
, sizeof (char));
399 if (*sptr
== BSLTOK
) {
400 if (*(sptr
+1) == '\0') {
405 if (*(sptr
+1) == QUOTETOK
||
406 *(sptr
+1) == BSLTOK
) {
413 } else if (*sptr
== QUOTETOK
) {
422 if (*sptr
== SEMITOK
) {
423 /* No filter and no more SSD */
427 /* prepare to copy DN */
428 i
= strlen(sptr
) + 1;
429 ptr
->filter
= dptr
= (char *)calloc(i
, sizeof (char));
434 if (*sptr
== BSLTOK
) {
435 if (*(sptr
+1) == '\0') {
440 if (*(sptr
+1) == QUOTETOK
||
441 *(sptr
+1) == BSLTOK
) {
448 } else if (*sptr
== QUOTETOK
) {
458 if (*sptr
== SEMITOK
) {
463 if (strncasecmp(sptr
, "base", 4) == 0) {
465 ptr
->scope
= NS_LDAP_SCOPE_BASE
;
466 } else if (strncasecmp(sptr
, "one", 3) == 0) {
467 ptr
->scope
= NS_LDAP_SCOPE_ONELEVEL
;
469 } else if (strncasecmp(sptr
, "sub", 3) == 0) {
470 ptr
->scope
= NS_LDAP_SCOPE_SUBTREE
;
473 if (*sptr
== '\0' || (*sptr
== SEMITOK
)) {
479 if (*sptr
!= QUESTTOK
) {
491 if (*sptr
== BSLTOK
) {
492 if (*(sptr
+1) == '\0') {
496 if (*(sptr
+1) == QUOTETOK
||
497 *(sptr
+1) == BSLTOK
) {
503 /* fall through to char copy */
504 } else if (*sptr
== QUOTETOK
) {
510 /* else fall through to char copy */
513 if (wasquoted
&& *sptr
!= QUESTTOK
) {
514 /* error past end of quoted string */
518 if (*sptr
== BSLTOK
) {
519 if (*(sptr
+1) == '\0') {
523 if (*(sptr
+1) == SEMITOK
||
524 *(sptr
+1) == QUESTTOK
||
525 *(sptr
+1) == QUOTETOK
||
526 *(sptr
+1) == BSLTOK
) {
530 /* fall through to char copy */
531 } else if (*sptr
== QUOTETOK
) {
535 } else if (*sptr
== QUESTTOK
) {
536 /* if filter error */
537 if (state
== P_FILTER
) {
541 /* end of basedn goto scope */
545 } else if (*sptr
== SEMITOK
) {
546 /* end of current SSD */
552 /* normal character to copy */
556 if (*sptr
== SEMITOK
) {
560 __ns_ldap_freeASearchDesc(ptr
);
563 return (NS_LDAP_CONFIG
);
564 default: /* error should never arrive here */
566 __ns_ldap_freeASearchDesc(ptr
);
569 return (NS_LDAP_CONFIG
);
571 __ns_ldap_freeASearchDesc(ptr
);
574 return (NS_LDAP_MEMORY
);
579 __ns_ldap_freeASearchDesc(ptr
);
582 return (NS_LDAP_INVALID_PARAM
);
585 if (empty
|| strlen(ptr
->basedn
) == 0) {
587 /* get default base */
588 rc
= __s_api_getDNs(&dns
, service
, &error
);
589 if (rc
!= NS_LDAP_SUCCESS
) {
591 __s_api_free2dArray(dns
);
594 (void) __ns_ldap_freeError(&error
);
595 __ns_ldap_freeASearchDesc(ptr
);
597 return (NS_LDAP_MEMORY
);
599 ptr
->basedn
= strdup(dns
[0]);
600 __s_api_free2dArray(dns
);
606 return (NS_LDAP_SUCCESS
);
611 * Build up the service descriptor array
613 #define NS_SDESC_MAX 4
616 __ns_ldap_saveSearchDesc(ns_ldap_search_desc_t
***sdlist
,
617 int *cnt
, int *max
, ns_ldap_search_desc_t
*ret
)
619 ns_ldap_search_desc_t
**tmplist
;
621 if (*sdlist
== NULL
) {
624 *sdlist
= (ns_ldap_search_desc_t
**)
625 calloc(*max
, sizeof (ns_ldap_search_desc_t
*));
628 } else if (*cnt
+1 >= *max
) {
629 *max
+= NS_SDESC_MAX
;
630 tmplist
= (ns_ldap_search_desc_t
**)
631 reallocarray(*sdlist
, *max
,
632 sizeof (ns_ldap_search_desc_t
*));
638 (*sdlist
)[*cnt
] = ret
;
640 (*sdlist
)[*cnt
] = NULL
;
646 * Exported Search Descriptor Routines
649 int __ns_ldap_getSearchDescriptors(
651 ns_ldap_search_desc_t
***desc
,
652 ns_ldap_error_t
**errorp
)
657 void **paramVal
= NULL
;
658 char **sdl
, *srv
, **sdl_save
;
659 char errstr
[2 * MAXERROR
];
660 ns_ldap_search_desc_t
**sdlist
;
664 ns_ldap_search_desc_t
*ret
;
666 if ((desc
== NULL
) || (errorp
== NULL
))
667 return (NS_LDAP_INVALID_PARAM
);
672 rc
= __ns_ldap_getParam(NS_LDAP_SERVICE_SEARCH_DESC_P
,
673 (void ***)¶m
, errorp
);
674 if (rc
!= NS_LDAP_SUCCESS
) {
677 sdl
= (char **)param
;
682 cfg
= __s_api_get_default_config();
685 (void) snprintf(errstr
, sizeof (errstr
),
686 gettext("No configuration information available."));
687 MKERROR(LOG_ERR
, *errorp
, NS_CONFIG_NOTLOADED
, strdup(errstr
),
689 return (NS_LDAP_CONFIG
);
693 __s_api_release_config(cfg
);
695 /* If using version1 or no sd's process SEARCH_DN if available */
696 if (vers
== NS_LDAP_V1
&& param
== NULL
) {
697 rc
= __s_api_get_search_DNs_v1(&sdl
, service
, errorp
);
698 if (rc
!= NS_LDAP_SUCCESS
|| sdl
== NULL
) {
702 /* Convert a SEARCH_DN to a search descriptor */
703 for (; *sdl
; sdl
++) {
704 ret
= (ns_ldap_search_desc_t
*)
705 calloc(1, sizeof (ns_ldap_search_desc_t
));
707 (void) __ns_ldap_freeSearchDescriptors(&sdlist
);
708 __s_api_free2dArray(sdl_save
);
709 return (NS_LDAP_MEMORY
);
711 ret
->basedn
= strdup(*sdl
);
712 if (ret
->basedn
== NULL
) {
714 (void) __ns_ldap_freeASearchDesc(ret
);
715 (void) __ns_ldap_freeSearchDescriptors(&sdlist
);
716 __s_api_free2dArray(sdl_save
);
717 return (NS_LDAP_MEMORY
);
721 if ((rc
= __ns_ldap_getParam(NS_LDAP_SEARCH_SCOPE_P
,
722 ¶mVal
, errorp
)) != NS_LDAP_SUCCESS
) {
723 (void) __ns_ldap_freeASearchDesc(ret
);
724 (void) __ns_ldap_freeSearchDescriptors(&sdlist
);
725 __s_api_free2dArray(sdl_save
);
728 if (paramVal
&& *paramVal
)
729 ret
->scope
= * (ScopeType_t
*)(*paramVal
);
731 ret
->scope
= NS_LDAP_SCOPE_ONELEVEL
;
732 (void) __ns_ldap_freeParam(¶mVal
);
735 rc
= __ns_ldap_saveSearchDesc(&sdlist
, &cnt
, &max
, ret
);
737 (void) __ns_ldap_freeASearchDesc(ret
);
738 (void) __ns_ldap_freeSearchDescriptors(&sdlist
);
739 __s_api_free2dArray(sdl_save
);
740 return (NS_LDAP_MEMORY
);
743 __s_api_free2dArray(sdl_save
);
745 return (NS_LDAP_SUCCESS
);
748 if (sdl
== NULL
|| service
== NULL
) {
749 (void) __ns_ldap_freeParam(¶m
);
752 return (NS_LDAP_SUCCESS
);
754 slen
= strlen(service
);
756 /* Process the version2 sd's */
757 for (; *sdl
; sdl
++) {
759 if (strncasecmp(service
, srv
, slen
) != 0)
762 if (*srv
!= COLONTOK
)
765 while (srv
!= NULL
&& *srv
!= '\0') {
767 rc
= __s_api_parseASearchDesc(service
, &srv
, &ret
);
768 if (rc
!= NS_LDAP_SUCCESS
) {
769 (void) __ns_ldap_freeSearchDescriptors(&sdlist
);
770 (void) snprintf(errstr
, (2 * MAXERROR
), gettext(
771 "Invalid serviceSearchDescriptor (%s). "
772 "Illegal configuration"), *sdl
);
773 (void) __ns_ldap_freeParam(¶m
);
775 MKERROR(LOG_ERR
, *errorp
, NS_CONFIG_SYNTAX
,
780 rc
= __ns_ldap_saveSearchDesc(
781 &sdlist
, &cnt
, &max
, ret
);
784 (void) __ns_ldap_freeSearchDescriptors(&sdlist
);
785 (void) __ns_ldap_freeParam(¶m
);
787 return (NS_LDAP_MEMORY
);
792 (void) __ns_ldap_freeParam(¶m
);
795 return (NS_LDAP_SUCCESS
);
799 __ns_ldap_freeSearchDescriptors(ns_ldap_search_desc_t
***desc
)
801 ns_ldap_search_desc_t
**dptr
;
802 ns_ldap_search_desc_t
*ptr
;
805 return (NS_LDAP_SUCCESS
);
806 for (dptr
= *desc
; (ptr
= *dptr
) != NULL
; dptr
++) {
807 __ns_ldap_freeASearchDesc(ptr
);
812 return (NS_LDAP_SUCCESS
);
819 * Exported Attribute/Objectclass mapping functions.
823 * This function is not supported.
826 int __ns_ldap_getAttributeMaps(
828 ns_ldap_attribute_map_t
***maps
,
829 ns_ldap_error_t
**errorp
)
832 return (NS_LDAP_OP_FAILED
);
836 __ns_ldap_freeAttributeMaps(ns_ldap_attribute_map_t
***maps
)
838 ns_ldap_attribute_map_t
**dptr
;
839 ns_ldap_attribute_map_t
*ptr
;
843 return (NS_LDAP_SUCCESS
);
844 for (dptr
= *maps
; (ptr
= *dptr
) != NULL
; dptr
++) {
847 ptr
->origAttr
= NULL
;
849 if (ptr
->mappedAttr
) {
850 for (cpp
= ptr
->mappedAttr
; (cp
= *cpp
) != NULL
; cpp
++)
852 free(ptr
->mappedAttr
);
853 ptr
->mappedAttr
= NULL
;
860 return (NS_LDAP_SUCCESS
);
863 char **__ns_ldap_getMappedAttributes(
865 const char *origAttribute
)
867 ns_config_t
*ptr
= __s_api_loadrefresh_config();
874 hp
= ns_get_hash(ptr
, NS_HASH_AMAP
, service
, origAttribute
);
876 if (hp
== NULL
|| hp
->h_map
== NULL
)
879 ret
= __s_api_cp2dArray(hp
->h_map
->map
);
880 __s_api_release_config(ptr
);
884 char **__ns_ldap_getOrigAttribute(
886 const char *mappedAttribute
)
888 ns_config_t
*ptr
= __s_api_loadrefresh_config();
895 hp
= ns_get_hash(ptr
, NS_HASH_RAMAP
, service
, mappedAttribute
);
897 if (hp
== NULL
|| hp
->h_map
== NULL
)
900 ret
= __s_api_cp2dArray(hp
->h_map
->map
);
901 __s_api_release_config(ptr
);
906 * This function is not supported.
909 int __ns_ldap_getObjectClassMaps(
911 ns_ldap_objectclass_map_t
***maps
,
912 ns_ldap_error_t
**errorp
)
915 return (NS_LDAP_OP_FAILED
);
919 __ns_ldap_freeObjectClassMaps(ns_ldap_objectclass_map_t
***maps
)
921 ns_ldap_objectclass_map_t
**dptr
;
922 ns_ldap_objectclass_map_t
*ptr
;
925 return (NS_LDAP_SUCCESS
);
926 for (dptr
= *maps
; (ptr
= *dptr
) != NULL
; dptr
++) {
933 ptr
->mappedOC
= NULL
;
940 return (NS_LDAP_SUCCESS
);
943 char **__ns_ldap_getMappedObjectClass(
945 const char *origObjectClass
)
947 ns_config_t
*ptr
= __s_api_loadrefresh_config();
954 hp
= ns_get_hash(ptr
, NS_HASH_OMAP
, service
, origObjectClass
);
956 if (hp
== NULL
|| hp
->h_map
== NULL
)
959 ret
= __s_api_cp2dArray(hp
->h_map
->map
);
960 __s_api_release_config(ptr
);
964 char **__ns_ldap_getOrigObjectClass(
966 const char *mappedObjectClass
)
968 ns_config_t
*ptr
= __s_api_loadrefresh_config();
975 hp
= ns_get_hash(ptr
, NS_HASH_ROMAP
, service
, mappedObjectClass
);
977 if (hp
== NULL
|| hp
->h_map
== NULL
)
980 ret
= __s_api_cp2dArray(hp
->h_map
->map
);
981 __s_api_release_config(ptr
);
985 char **__ns_ldap_mapAttributeList(
987 const char * const *origAttrList
)
989 const char * const *opp
;
993 if (origAttrList
== NULL
)
997 for (i
= 0; *opp
; i
++, opp
++)
999 cpp
= (char **)calloc(i
+1, sizeof (char *));
1004 for (i
= 0; *opp
; i
++, opp
++) {
1005 npp
= __ns_ldap_getMappedAttributes(service
, *opp
);
1006 if (npp
&& npp
[0]) {
1007 cpp
[i
] = strdup(npp
[0]);
1008 __s_api_free2dArray(npp
);
1010 if (cpp
[i
] == NULL
) {
1011 __s_api_free2dArray(cpp
);
1015 cpp
[i
] = strdup(*opp
);
1016 if (cpp
[i
] == NULL
) {
1017 __s_api_free2dArray(cpp
);
1026 __ns_ldap_mapAttribute(
1027 const char *service
,
1028 const char *origAttr
)
1033 if (origAttr
== NULL
)
1036 npp
= __ns_ldap_getMappedAttributes(service
, origAttr
);
1037 if (npp
&& npp
[0]) {
1038 mappedAttr
= strdup(npp
[0]);
1039 __s_api_free2dArray(npp
);
1041 mappedAttr
= strdup(origAttr
);
1043 return (mappedAttr
);