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) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
27 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <sys/sockio.h>
40 #include <netinet/in.h>
41 #include <arpa/inet.h>
48 #include "ns_internal.h"
49 #include "ns_cache_door.h"
51 #define UDP "/dev/udp"
55 struct in_addr addr
, netmask
;
58 static ns_service_map ns_def_map
[] = {
59 { "passwd", "ou=people,", NULL
},
60 { "shadow", "ou=people,", "passwd" },
61 { "user_attr", "ou=people,", "passwd" },
62 { "audit_user", "ou=people,", "passwd" },
63 { "group", "ou=group,", NULL
},
64 { "rpc", "ou=rpc,", NULL
},
65 { "project", "ou=projects,", NULL
},
66 { "protocols", "ou=protocols,", NULL
},
67 { "networks", "ou=networks,", NULL
},
68 { "netmasks", "ou=networks,", "networks" },
69 { "netgroup", "ou=netgroup,", NULL
},
70 { "aliases", "ou=aliases,", NULL
},
71 { "Hosts", "ou=Hosts,", NULL
},
72 { "ipnodes", "ou=Hosts,", "hosts" },
73 { "Services", "ou=Services,", NULL
},
74 { "bootparams", "ou=ethers,", "ethers" },
75 { "ethers", "ou=ethers,", NULL
},
76 { "auth_attr", "ou=SolarisAuthAttr,", NULL
},
77 { "prof_attr", "ou=SolarisProfAttr,", NULL
},
78 { "exec_attr", "ou=SolarisProfAttr,", "prof_attr" },
79 { "profile", "ou=profile,", NULL
},
80 { "printers", "ou=printers,", NULL
},
81 { "automount", "", NULL
},
82 { "tnrhtp", "ou=ipTnet,", NULL
},
83 { "tnrhdb", "ou=ipTnet,", "tnrhtp" },
88 static char ** parseDN(const char *val
, const char *service
);
89 static char ** sortServerNet(char **srvlist
);
90 static char ** sortServerPref(char **srvlist
, char **preflist
,
91 boolean_t flag
, int version
, int *error
);
94 * FUNCTION: s_api_printResult
95 * Given a ns_ldap_result structure print it.
98 __s_api_printResult(ns_ldap_result_t
*result
)
101 ns_ldap_entry_t
*curEntry
;
105 (void) fprintf(stderr
, "__s_api_printResult START\n");
107 (void) printf("--------------------------------------\n");
108 if (result
== NULL
) {
109 (void) printf("No result\n");
112 (void) printf("entries_count %d\n", result
->entries_count
);
113 curEntry
= result
->entry
;
114 for (i
= 0; i
< result
->entries_count
; i
++) {
116 (void) printf("entry %d has attr_count = %d \n", i
,
117 curEntry
->attr_count
);
118 for (j
= 0; j
< curEntry
->attr_count
; j
++) {
119 (void) printf("entry %d has attr_pair[%d] = %s \n",
120 i
, j
, curEntry
->attr_pair
[j
]->attrname
);
121 for (k
= 0; k
< 20 &&
122 curEntry
->attr_pair
[j
]->attrvalue
[k
]; k
++)
123 (void) printf("entry %d has attr_pair[%d]->"
124 "attrvalue[%d] = %s \n", i
, j
, k
,
125 curEntry
->attr_pair
[j
]->attrvalue
[k
]);
127 (void) printf("\n--------------------------------------\n");
128 curEntry
= curEntry
->next
;
134 * FUNCTION: __s_api_getSearchScope
136 * Retrieve the search scope for ldap search from the config module.
138 * RETURN VALUES: NS_LDAP_SUCCESS, NS_LDAP_CONFIG
140 * OUTPUT: searchScope, errorp
143 __s_api_getSearchScope(
145 ns_ldap_error_t
**errorp
)
148 char errmsg
[MAXERROR
];
149 void **paramVal
= NULL
;
154 (void) fprintf(stderr
, "__s_api_getSearchScope START\n");
156 if (*searchScope
== 0) {
157 if ((rc
= __ns_ldap_getParam(NS_LDAP_SEARCH_SCOPE_P
,
158 ¶mVal
, errorp
)) != NS_LDAP_SUCCESS
) {
161 if (paramVal
&& *paramVal
)
162 scope
= * (int *)(*paramVal
);
164 scope
= NS_LDAP_SCOPE_ONELEVEL
;
165 (void) __ns_ldap_freeParam(¶mVal
);
167 scope
= *searchScope
;
172 case NS_LDAP_SCOPE_ONELEVEL
:
173 *searchScope
= LDAP_SCOPE_ONELEVEL
;
175 case NS_LDAP_SCOPE_BASE
:
176 *searchScope
= LDAP_SCOPE_BASE
;
178 case NS_LDAP_SCOPE_SUBTREE
:
179 *searchScope
= LDAP_SCOPE_SUBTREE
;
182 (void) snprintf(errmsg
, sizeof (errmsg
),
183 gettext("Invalid search scope!"));
184 MKERROR(LOG_ERR
, *errorp
, NS_CONFIG_FILE
,
185 strdup(errmsg
), NS_LDAP_CONFIG
);
186 return (NS_LDAP_CONFIG
);
189 return (NS_LDAP_SUCCESS
);
193 * FUNCTION: __ns_ldap_dupAuth
195 * Duplicates an authentication structure.
197 * RETURN VALUES: copy of authp or NULL on error
201 __ns_ldap_dupAuth(const ns_cred_t
*authp
)
206 (void) fprintf(stderr
, "__ns_ldap_dupAuth START\n");
211 ap
= (ns_cred_t
*)calloc(1, sizeof (ns_cred_t
));
215 if (authp
->hostcertpath
) {
216 ap
->hostcertpath
= strdup(authp
->hostcertpath
);
217 if (ap
->hostcertpath
== NULL
) {
222 if (authp
->cred
.unix_cred
.userID
) {
223 ap
->cred
.unix_cred
.userID
=
224 strdup(authp
->cred
.unix_cred
.userID
);
225 if (ap
->cred
.unix_cred
.userID
== NULL
) {
226 (void) __ns_ldap_freeCred(&ap
);
230 if (authp
->cred
.unix_cred
.passwd
) {
231 ap
->cred
.unix_cred
.passwd
=
232 strdup(authp
->cred
.unix_cred
.passwd
);
233 if (ap
->cred
.unix_cred
.passwd
== NULL
) {
234 (void) __ns_ldap_freeCred(&ap
);
238 if (authp
->cred
.cert_cred
.nickname
) {
239 ap
->cred
.cert_cred
.nickname
=
240 strdup(authp
->cred
.cert_cred
.nickname
);
241 if (ap
->cred
.cert_cred
.nickname
== NULL
) {
242 (void) __ns_ldap_freeCred(&ap
);
246 ap
->auth
.type
= authp
->auth
.type
;
247 ap
->auth
.tlstype
= authp
->auth
.tlstype
;
248 ap
->auth
.saslmech
= authp
->auth
.saslmech
;
249 ap
->auth
.saslopt
= authp
->auth
.saslopt
;
254 * FUNCTION: __ns_ldap_freeUnixCred
256 * Frees all the memory associated with a UnixCred_t structure.
258 * RETURN VALUES: NS_LDAP_INVALID_PARAM, NS_LDAP_SUCCESS
262 __ns_ldap_freeUnixCred(UnixCred_t
** credp
)
267 (void) fprintf(stderr
, "__ns_ldap_freeUnixCred START\n");
269 if (credp
== NULL
|| *credp
== NULL
)
270 return (NS_LDAP_INVALID_PARAM
);
274 (void) memset(ap
->userID
, 0, strlen(ap
->userID
));
279 (void) memset(ap
->passwd
, 0, strlen(ap
->passwd
));
285 return (NS_LDAP_SUCCESS
);
289 * FUNCTION: __ns_ldap_freeCred
291 * Frees all the memory associated with a ns_cred_t structure.
293 * RETURN VALUES: NS_LDAP_INVALID_PARAM, NS_LDAP_SUCCESS
297 __ns_ldap_freeCred(ns_cred_t
** credp
)
302 (void) fprintf(stderr
, "__ns_ldap_freeCred START\n");
304 if (credp
== NULL
|| *credp
== NULL
)
305 return (NS_LDAP_INVALID_PARAM
);
308 if (ap
->hostcertpath
) {
309 (void) memset(ap
->hostcertpath
, 0,
310 strlen(ap
->hostcertpath
));
311 free(ap
->hostcertpath
);
314 if (ap
->cred
.unix_cred
.userID
) {
315 (void) memset(ap
->cred
.unix_cred
.userID
, 0,
316 strlen(ap
->cred
.unix_cred
.userID
));
317 free(ap
->cred
.unix_cred
.userID
);
320 if (ap
->cred
.unix_cred
.passwd
) {
321 (void) memset(ap
->cred
.unix_cred
.passwd
, 0,
322 strlen(ap
->cred
.unix_cred
.passwd
));
323 free(ap
->cred
.unix_cred
.passwd
);
326 if (ap
->cred
.cert_cred
.nickname
) {
327 (void) memset(ap
->cred
.cert_cred
.nickname
, 0,
328 strlen(ap
->cred
.cert_cred
.nickname
));
329 free(ap
->cred
.cert_cred
.nickname
);
334 return (NS_LDAP_SUCCESS
);
338 * FUNCTION: __s_api_is_auth_matched
340 * Compare an authentication structure.
342 * RETURN VALUES: B_TRUE if matched, B_FALSE otherwise.
343 * INPUT: auth1, auth2
346 __s_api_is_auth_matched(const ns_cred_t
*auth1
,
347 const ns_cred_t
*auth2
)
349 if ((auth1
->auth
.type
!= auth2
->auth
.type
) ||
350 (auth1
->auth
.tlstype
!= auth2
->auth
.tlstype
) ||
351 (auth1
->auth
.saslmech
!= auth2
->auth
.saslmech
) ||
352 (auth1
->auth
.saslopt
!= auth2
->auth
.saslopt
))
355 if ((((auth1
->auth
.type
== NS_LDAP_AUTH_SASL
) &&
356 ((auth1
->auth
.saslmech
== NS_LDAP_SASL_CRAM_MD5
) ||
357 (auth1
->auth
.saslmech
== NS_LDAP_SASL_DIGEST_MD5
))) ||
358 (auth1
->auth
.type
== NS_LDAP_AUTH_SIMPLE
)) &&
359 ((auth1
->cred
.unix_cred
.userID
== NULL
) ||
360 (auth1
->cred
.unix_cred
.passwd
== NULL
) ||
361 ((strcasecmp(auth1
->cred
.unix_cred
.userID
,
362 auth2
->cred
.unix_cred
.userID
) != 0)) ||
363 ((strcmp(auth1
->cred
.unix_cred
.passwd
,
364 auth2
->cred
.unix_cred
.passwd
) != 0))))
371 * FUNCTION: __s_api_getDNs
373 * Retrieves the default base dn for the given
376 * RETURN VALUES: NS_LDAP_SUCCESS, NS_LDAP_MEMORY, NS_LDAP_CONFIG
380 typedef int (*pf
)(const char *, char **, ns_ldap_error_t
**);
385 ns_ldap_error_t
** error
)
388 void **paramVal
= NULL
;
392 pf prepend_auto2dn
= __s_api_prepend_automountmapname_to_dn
;
395 (void) fprintf(stderr
, "__s_api_getDNs START\n");
397 if ((rc
= __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P
,
398 ¶mVal
, error
)) != NS_LDAP_SUCCESS
) {
402 char errmsg
[MAXERROR
];
404 (void) snprintf(errmsg
, sizeof (errmsg
),
405 gettext("BaseDN not defined"));
406 MKERROR(LOG_ERR
, *error
, NS_CONFIG_FILE
, strdup(errmsg
),
408 return (NS_LDAP_CONFIG
);
411 dns
= (char **)calloc(2, sizeof (char *));
413 (void) __ns_ldap_freeParam(¶mVal
);
414 return (NS_LDAP_MEMORY
);
417 if (service
== NULL
) {
418 dns
[0] = strdup((char *)*paramVal
);
419 if (dns
[0] == NULL
) {
420 (void) __ns_ldap_freeParam(¶mVal
);
422 return (NS_LDAP_MEMORY
);
425 for (i
= 0; ns_def_map
[i
].service
!= NULL
; i
++) {
426 if (strcasecmp(service
,
427 ns_def_map
[i
].service
) == 0) {
429 len
= strlen((char *)*paramVal
) +
430 strlen(ns_def_map
[i
].rdn
) + 1;
432 calloc(len
, sizeof (char));
433 if (dns
[0] == NULL
) {
434 (void) __ns_ldap_freeParam(
437 return (NS_LDAP_MEMORY
);
439 (void) strcpy(dns
[0],
441 (void) strcat(dns
[0],
446 if (ns_def_map
[i
].service
== NULL
) {
447 char *p
= (char *)*paramVal
;
451 if (strchr(service
, '=') == NULL
) {
452 /* automount entries */
453 if (strncasecmp(service
, "auto_", 5) == 0) {
457 (void) __ns_ldap_freeParam(
459 return (NS_LDAP_MEMORY
);
461 /* shorten name to avoid cstyle error */
462 rc
= prepend_auto2dn(
463 service
, &buffer
, error
);
464 if (rc
!= NS_LDAP_SUCCESS
) {
467 (void) __ns_ldap_freeParam(
472 /* strlen("nisMapName")+"="+","+'\0' = 13 */
473 buflen
= strlen(service
) + strlen(p
) +
475 buffer
= (char *)malloc(buflen
);
476 if (buffer
== NULL
) {
478 (void) __ns_ldap_freeParam(
480 return (NS_LDAP_MEMORY
);
482 (void) snprintf(buffer
, buflen
,
483 "nisMapName=%s,%s", service
, p
);
486 buflen
= strlen(service
) + strlen(p
) + 2;
487 buffer
= (char *)malloc(buflen
);
488 if (buffer
== NULL
) {
490 (void) __ns_ldap_freeParam(¶mVal
);
491 return (NS_LDAP_MEMORY
);
493 (void) snprintf(buffer
, buflen
,
494 "%s,%s", service
, p
);
500 (void) __ns_ldap_freeParam(¶mVal
);
502 return (NS_LDAP_SUCCESS
);
505 * FUNCTION: __s_api_get_search_DNs_v1
507 * Retrieves the list of search DNS from the V1 profile for the given
510 * RETURN VALUES: NS_LDAP_SUCCESS, NS_LDAP_MEMORY, NS_LDAP_CONFIG
515 __s_api_get_search_DNs_v1(
518 ns_ldap_error_t
** error
)
521 void **paramVal
= NULL
;
522 void **temptr
= NULL
;
526 if ((rc
= __ns_ldap_getParam(NS_LDAP_SEARCH_DN_P
,
527 ¶mVal
, error
)) != NS_LDAP_SUCCESS
) {
531 if (service
&& paramVal
) {
532 for (temptr
= paramVal
; *temptr
!= NULL
; temptr
++) {
533 dns
= parseDN((const char *)(*temptr
),
534 (const char *)service
);
540 (void) __ns_ldap_freeParam(¶mVal
);
542 return (NS_LDAP_SUCCESS
);
548 * Parse a special formated list(val) into an array of char *.
550 * RETURN VALUE: A char * pointer to the new list of dns.
551 * INPUT: val, service
561 char **retVal
= NULL
;
568 char *SSD_service
= NULL
;
571 (void) fprintf(stderr
, "parseDN START\n");
573 if (val
== NULL
|| *val
== '\0')
575 if (service
== NULL
|| *service
== '\0')
579 slen
= strlen(service
);
580 if (strncasecmp(val
, service
, slen
) != 0) {
582 * This routine is only called
583 * to process V1 profile and
584 * for V1 profile, map service
585 * to the corresponding SSD_service
586 * which is associated with a
587 * real container in the LDAP directory
588 * tree, e.g., map "shadow" to
589 * "password". See function
590 * __s_api_get_SSD_from_SSDtoUse_service
591 * for similar service to SSD_service
592 * mapping handling for V2 profile.
594 for (i
= 0; ns_def_map
[i
].service
!= NULL
; i
++) {
595 if (ns_def_map
[i
].SSDtoUse_service
&&
597 ns_def_map
[i
].service
) == 0) {
599 ns_def_map
[i
].SSDtoUse_service
;
604 if (SSD_service
== NULL
)
607 slen
= strlen(SSD_service
);
608 if (strncasecmp(val
, SSD_service
, slen
) != 0)
613 while (*temptr
== SPACETOK
|| *temptr
== TABTOK
)
615 if (*temptr
!= COLONTOK
)
619 temptr2
= strchr(temptr
, OPARATOK
);
623 temptr2
= strchr(temptr2
, CPARATOK
);
630 retVal
= (char **)calloc(valNo
+1, sizeof (char *));
637 for (i
= 0; (i
< valNo
) && (temptr
< valend
); i
++) {
638 temptr
= strchr(temptr
, OPARATOK
);
639 if (temptr
== NULL
) {
640 __s_api_free2dArray(retVal
);
644 temptr2
= strchr(temptr
, CPARATOK
);
645 if (temptr2
== NULL
) {
646 __s_api_free2dArray(retVal
);
649 valSize
= temptr2
- temptr
;
651 retVal
[i
] = (char *)calloc(valSize
+ 1, sizeof (char));
652 if (retVal
[i
] == NULL
) {
653 __s_api_free2dArray(retVal
);
656 (void) strncpy(retVal
[i
], temptr
, valSize
);
657 retVal
[i
][valSize
] = '\0';
658 temptr
= temptr2
+ 1;
666 * __s_api_get_local_interfaces
668 * Returns a pointer to an array of addresses and netmasks of all interfaces
669 * configured on the system.
671 * NOTE: This function is very IPv4 centric.
673 static struct ifinfo
*
674 __s_api_get_local_interfaces()
677 struct ifreq ifreq
, *ifr
;
678 struct ifinfo
*localinfo
;
679 struct in_addr netmask
;
680 struct sockaddr_in
*sin
;
686 if ((fd
= open(UDP
, O_RDONLY
)) < 0)
687 return ((struct ifinfo
*)NULL
);
689 if (ioctl(fd
, SIOCGIFNUM
, (char *)&numifs
) < 0) {
693 buf
= malloc(numifs
* sizeof (struct ifreq
));
696 return ((struct ifinfo
*)NULL
);
698 ifc
.ifc_len
= numifs
* (int)sizeof (struct ifreq
);
700 if (ioctl(fd
, SIOCGIFCONF
, (char *)&ifc
) < 0) {
704 return ((struct ifinfo
*)NULL
);
706 ifr
= (struct ifreq
*)buf
;
707 numifs
= ifc
.ifc_len
/(int)sizeof (struct ifreq
);
708 localinfo
= (struct ifinfo
*)malloc((numifs
+ 1) *
709 sizeof (struct ifinfo
));
710 if (localinfo
== NULL
) {
714 return ((struct ifinfo
*)NULL
);
717 for (i
= 0, n
= numifs
; n
> 0; n
--, ifr
++) {
721 if (ioctl(fd
, SIOCGIFFLAGS
, (char *)&ifreq
) < 0)
724 ifrflags
= ifreq
.ifr_flags
;
725 if (((ifrflags
& IFF_UP
) == 0) ||
726 (ifr
->ifr_addr
.sa_family
!= AF_INET
))
729 if (ioctl(fd
, SIOCGIFNETMASK
, (char *)&ifreq
) < 0)
731 netmask
= ((struct sockaddr_in
*)&ifreq
.ifr_addr
)->sin_addr
;
733 if (ioctl(fd
, SIOCGIFADDR
, (char *)&ifreq
) < 0)
736 sin
= (struct sockaddr_in
*)&ifreq
.ifr_addr
;
738 localinfo
[i
].addr
= sin
->sin_addr
;
739 localinfo
[i
].netmask
= netmask
;
742 localinfo
[i
].addr
.s_addr
= 0;
752 * __s_api_samenet(char *, struct ifinfo *)
754 * Returns 1 if address is on the same subnet of the array of addresses
757 * NOTE: This function is only valid for IPv4 addresses.
760 __s_api_IPv4sameNet(char *addr
, struct ifinfo
*ifs
)
769 if ((addr_raw
= strdup(addr
)) != NULL
) {
772 /* Remove port number. */
773 if ((s
= strchr(addr_raw
, ':')) != NULL
)
776 iaddr
= inet_addr(addr_raw
);
778 /* Loop through interface list to find match. */
779 for (i
= 0; ifs
[i
].addr
.s_addr
!= 0; i
++) {
780 if ((iaddr
& ifs
[i
].netmask
.s_addr
) ==
781 (ifs
[i
].addr
.s_addr
&
782 ifs
[i
].netmask
.s_addr
))
793 * FUNCTION: __s_api_getServers
795 * Retrieve a list of ldap servers from the config module.
797 * RETURN VALUE: NS_LDAP_SUCCESS, NS_LDAP_CONFIG, NS_LDAP_MEMORY
799 * OUTPUT: servers, error
804 ns_ldap_error_t
** error
)
806 void **paramVal
= NULL
;
807 char errmsg
[MAXERROR
];
808 char **sortServers
= NULL
;
809 char **netservers
= NULL
;
810 int rc
= 0, err
= NS_LDAP_CONFIG
, version
= 1;
811 const char *str
, *str1
;
814 (void) fprintf(stderr
, "__s_api_getServers START\n");
817 /* get profile version number */
818 if ((rc
= __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P
,
819 ¶mVal
, error
)) != NS_LDAP_SUCCESS
)
822 if (paramVal
== NULL
|| *paramVal
== NULL
) {
823 (void) snprintf(errmsg
, sizeof (errmsg
),
824 gettext("No file version"));
825 MKERROR(LOG_INFO
, *error
, NS_CONFIG_FILE
, strdup(errmsg
),
827 return (NS_LDAP_CONFIG
);
830 if (strcasecmp((char *)*paramVal
, NS_LDAP_VERSION_1
) == 0)
832 else if (strcasecmp((char *)*paramVal
, NS_LDAP_VERSION_2
) == 0)
835 (void) __ns_ldap_freeParam(¶mVal
);
838 if ((rc
= __ns_ldap_getParam(NS_LDAP_SERVERS_P
,
839 ¶mVal
, error
)) != NS_LDAP_SUCCESS
)
843 * For version 2, default server list could be
846 if ((paramVal
== NULL
|| (char *)*paramVal
== NULL
) &&
848 str
= NULL_OR_STR(__s_api_get_configname(NS_LDAP_SERVERS_P
));
849 (void) snprintf(errmsg
, sizeof (errmsg
),
850 gettext("Unable to retrieve the '%s' list"), str
);
851 MKERROR(LOG_WARNING
, *error
, NS_CONFIG_FILE
, strdup(errmsg
),
853 return (NS_LDAP_CONFIG
);
857 * Get server address(es) and go through them.
859 *servers
= (char **)paramVal
;
862 /* Sort servers based on network. */
864 netservers
= sortServerNet(*servers
);
867 *servers
= netservers
;
869 return (NS_LDAP_MEMORY
);
873 /* Get preferred server list and sort servers based on that. */
874 if ((rc
= __ns_ldap_getParam(NS_LDAP_SERVER_PREF_P
,
875 ¶mVal
, error
)) != NS_LDAP_SUCCESS
) {
877 __s_api_free2dArray(*servers
);
882 if (paramVal
!= NULL
) {
886 if ((rc
= __ns_ldap_getParam(NS_LDAP_PREF_ONLY_P
,
887 &val
, error
)) != NS_LDAP_SUCCESS
) {
889 __s_api_free2dArray(*servers
);
891 (void) __ns_ldap_freeParam(¶mVal
);
895 prefServers
= (char **)paramVal
;
898 if (val
!= NULL
&& (*val
) != NULL
&&
900 sortServers
= sortServerPref(*servers
,
901 prefServers
, B_FALSE
, version
,
904 sortServers
= sortServerPref(*servers
,
905 prefServers
, B_TRUE
, version
,
913 *servers
= sortServers
;
916 __s_api_free2dArray(*servers
);
918 __s_api_free2dArray(prefServers
);
922 (void) __ns_ldap_freeParam(&val
);
924 (void) __ns_ldap_freeParam(¶mVal
);
926 if (*servers
== NULL
) {
927 if (err
== NS_LDAP_CONFIG
) {
928 str
= NULL_OR_STR(__s_api_get_configname(
930 str1
= NULL_OR_STR(__s_api_get_configname(
931 NS_LDAP_SERVER_PREF_P
));
932 (void) snprintf(errmsg
, sizeof (errmsg
),
933 gettext("Unable to generate a new server list "
934 "based on '%s' and/or '%s'"), str
, str1
);
935 MKERROR(LOG_WARNING
, *error
, NS_CONFIG_FILE
,
936 strdup(errmsg
), err
);
939 return (NS_LDAP_MEMORY
);
942 return (NS_LDAP_SUCCESS
);
947 * FUNCTION: sortServerNet
948 * Sort the serverlist based on the distance from client as long
949 * as the list only contains IPv4 addresses. Otherwise do nothing.
952 sortServerNet(char **srvlist
)
957 struct ifinfo
*ifs
= __s_api_get_local_interfaces();
959 char **psrvs
, **retsrvs
;
962 if (srvlist
== NULL
|| srvlist
[0] == NULL
)
965 /* Count the number of servers to sort. */
966 for (count
= 0; srvlist
[count
] != NULL
; count
++) {
967 if (!__s_api_isipv4(srvlist
[count
]))
972 /* Make room for the returned list of servers. */
973 retsrvs
= (char **)calloc(count
, sizeof (char *));
974 if (retsrvs
== NULL
) {
980 retsrvs
[count
- 1] = NULL
;
982 /* Make a temporary list of servers. */
983 psrvs
= (char **)calloc(count
, sizeof (char *));
992 /* Filter servers on the same subnet */
995 if (ipv4only
&& __s_api_IPv4sameNet(*tsrvs
, ifs
)) {
997 retsrvs
[all
++] = *(tsrvs
);
1002 /* Filter remaining servers. */
1005 char **ttsrvs
= psrvs
;
1008 if (strcmp(*tsrvs
, *ttsrvs
) == 0)
1013 if (*ttsrvs
== NULL
)
1014 retsrvs
[all
++] = *(tsrvs
);
1027 * FUNCTION: sortServerPref
1028 * Sort the serverlist based on the preferred server list.
1030 * The sorting algorithm works as follows:
1032 * If version 1, if flag is TRUE, find all the servers in both preflist
1033 * and srvlist, then append other servers in srvlist to this list
1034 * and return the list.
1035 * If flag is FALSE, just return srvlist.
1036 * srvlist can not be empty.
1038 * If version 2, append all the servers in srvlist
1039 * but not in preflist to preflist, and return the merged list.
1040 * If srvlist is empty, just return preflist.
1041 * If preflist is empty, just return srvlist.
1044 sortServerPref(char **srvlist
, char **preflist
,
1045 boolean_t flag
, int version
, int *error
)
1047 int i
, scount
= 0, pcount
= 0;
1048 int all
= 0, dup
= 0;
1053 /* Count the number of servers to sort. */
1054 if (srvlist
&& srvlist
[0])
1055 for (i
= 0; srvlist
[i
] != NULL
; i
++)
1059 if (scount
== 0 && version
== 1) {
1060 *error
= NS_LDAP_CONFIG
;
1064 /* Count the number of preferred servers */
1065 if (preflist
&& preflist
[0])
1066 for (i
= 0; preflist
[i
] != NULL
; i
++)
1070 if (scount
== 0 && pcount
== 0) {
1071 *error
= NS_LDAP_CONFIG
;
1075 /* Make room for the returned list of servers */
1076 retsrvs
= (char **)calloc(scount
+ pcount
+ 1, sizeof (char *));
1077 if (retsrvs
== NULL
) {
1078 *error
= NS_LDAP_MEMORY
;
1083 * if the preferred server list is empty,
1084 * just return a copy of the server list
1089 retsrvs
[all
++] = *(tsrvs
++);
1095 * if the server list is empty,
1096 * just return a copy of the preferred server list
1101 retsrvs
[all
++] = *(tsrvs
++);
1106 /* Make room for the servers whose memory needs to be freed */
1107 dupsrvs
= (char **)calloc(scount
+ pcount
+ 1, sizeof (char *));
1108 if (dupsrvs
== NULL
) {
1110 *error
= NS_LDAP_MEMORY
;
1116 * throw out preferred servers not on server list.
1117 * If version 2, make a copy of the preferred server list.
1122 char **ttsrvs
= srvlist
;
1125 if (strcmp(*tsrvs
, *(ttsrvs
)) == 0)
1129 if (*ttsrvs
!= NULL
)
1130 retsrvs
[all
++] = *tsrvs
;
1132 dupsrvs
[dup
++] = *tsrvs
;
1138 retsrvs
[all
++] = *(tsrvs
++);
1142 * if PREF_ONLY is false, we append the non-preferred servers
1143 * to bottom of list.
1144 * For version 2, always append.
1146 if (flag
== B_TRUE
|| version
!= 1) {
1150 char **ttsrvs
= preflist
;
1153 if (strcmp(*tsrvs
, *ttsrvs
) == 0) {
1158 if (*ttsrvs
== NULL
)
1159 retsrvs
[all
++] = *tsrvs
;
1161 dupsrvs
[dup
++] = *tsrvs
;
1166 /* free memory for duplicate servers */
1168 for (tsrvs
= dupsrvs
; *tsrvs
; tsrvs
++)
1177 * FUNCTION: __s_api_removeBadServers
1178 * Contacts the ldap cache manager for marking the
1179 * problem servers as down, so that the server is
1180 * not contacted until the TTL expires.
1183 __s_api_removeBadServers(char ** Servers
)
1188 if (Servers
== NULL
)
1191 for (host
= Servers
; *host
!= NULL
; host
++) {
1192 if (__s_api_removeServer(*host
) < 0) {
1194 * Couldn't remove server from
1195 * server list. Log a warning.
1197 syslog(LOG_WARNING
, "libsldap: could "
1198 "not remove %s from servers list", *host
);
1204 * FUNCTION: __s_api_free2dArray
1207 __s_api_free2dArray(char ** inarray
)
1212 if (inarray
== NULL
)
1215 for (temptr
= inarray
; *temptr
!= NULL
; temptr
++) {
1222 * FUNCTION: __s_api_cp2dArray
1225 __s_api_cp2dArray(char **inarray
)
1228 char **ttarray
, *ret
;
1231 if (inarray
== NULL
)
1234 for (count
= 0; inarray
[count
] != NULL
; count
++)
1237 newarray
= (char **)calloc(count
+ 1, sizeof (char *));
1238 if (newarray
== NULL
)
1242 for (; *inarray
; inarray
++) {
1243 *(ttarray
++) = ret
= strdup(*inarray
);
1245 __s_api_free2dArray(newarray
);
1253 * FUNCTION: __s_api_isCtrlSupported
1254 * Determines if the passed control is supported by the LDAP sever.
1255 * RETURNS: NS_LDAP_SUCCESS if yes, NS_LDAP_OP_FAIL if not.
1258 __s_api_isCtrlSupported(Connection
*con
, char *ctrlString
)
1263 len
= strlen(ctrlString
);
1264 for (ctrl
= con
->controls
; ctrl
&& *ctrl
; ctrl
++) {
1265 if (strncasecmp(*ctrl
, ctrlString
, len
) == 0)
1266 return (NS_LDAP_SUCCESS
);
1268 return (NS_LDAP_OP_FAILED
);
1272 * FUNCTION: __s_api_toFollowReferrals
1273 * Determines if need to follow referral for an SLDAP API.
1274 * RETURN VALUES: NS_LDAP_SUCCESS, NS_LDAP_INVALID_PARAM, or
1275 * other rc from __ns_ldap_getParam()
1277 * OUTPUT: toFollow, errorp
1280 __s_api_toFollowReferrals(const int flags
,
1282 ns_ldap_error_t
**errorp
)
1284 void **paramVal
= NULL
;
1289 (void) fprintf(stderr
, "__s_api_toFollowReferrals START\n");
1292 /* Either NS_LDAP_NOREF or NS_LDAP_FOLLOWREF not both */
1293 if ((flags
& (NS_LDAP_NOREF
| NS_LDAP_FOLLOWREF
)) ==
1294 (NS_LDAP_NOREF
| NS_LDAP_FOLLOWREF
)) {
1295 return (NS_LDAP_INVALID_PARAM
);
1299 * if the NS_LDAP_NOREF or NS_LDAP_FOLLOWREF is set
1300 * this will take precendence over the values specified
1301 * in the configuration file
1303 if (flags
& (NS_LDAP_NOREF
| NS_LDAP_FOLLOWREF
)) {
1306 rc
= __ns_ldap_getParam(NS_LDAP_SEARCH_REF_P
,
1308 if (rc
!= NS_LDAP_SUCCESS
)
1310 if (paramVal
== NULL
|| *paramVal
== NULL
) {
1311 (void) __ns_ldap_freeParam(¶mVal
);
1313 (void) __ns_ldap_freeError(errorp
);
1315 return (NS_LDAP_SUCCESS
);
1317 iflags
= (* (int *)(*paramVal
));
1318 (void) __ns_ldap_freeParam(¶mVal
);
1321 if (iflags
& NS_LDAP_NOREF
)
1326 return (NS_LDAP_SUCCESS
);
1330 * FUNCTION: __s_api_addRefInfo
1331 * Insert a referral info into a referral info list.
1332 * RETURN VALUES: NS_LDAP_SUCCESS, NS_LDAP_MEMORY, NS_LDAP_OP_FAILED
1333 * INPUT: LDAP URL, pointer to the referral info list,
1334 * search baseDN, search scope, search filter,
1335 * previous connection
1338 __s_api_addRefInfo(ns_referral_info_t
**head
, char *url
,
1339 char *baseDN
, int *scope
,
1340 char *filter
, LDAP
*ld
)
1342 char errmsg
[MAXERROR
], *tmp
;
1343 ns_referral_info_t
*ref
, *tmpref
;
1344 LDAPURLDesc
*ludp
= NULL
;
1346 char *ld_defhost
= NULL
;
1349 (void) fprintf(stderr
, "__s_api_addRefInfo START\n");
1354 return (NS_LDAP_OP_FAILED
);
1357 * log error and return NS_LDAP_SUCCESS
1358 * if one of the following:
1360 * 2. LDAP URL which can not be parsed
1362 if (!ldap_is_ldap_url(url
) ||
1363 ldap_url_parse_nodn(url
, &ludp
) != 0) {
1364 (void) snprintf(errmsg
, MAXERROR
, "%s: %s",
1365 gettext("Invalid or non-LDAP URL when"
1366 " processing referrals URL"),
1368 syslog(LOG_ERR
, "libsldap: %s", errmsg
);
1370 ldap_free_urldesc(ludp
);
1371 return (NS_LDAP_SUCCESS
);
1374 ref
= (ns_referral_info_t
*)calloc(1,
1375 sizeof (ns_referral_info_t
));
1377 ldap_free_urldesc(ludp
);
1378 return (NS_LDAP_MEMORY
);
1382 * we do have a valid URL and we were able to parse it
1383 * however, we still need to find out what hostport to
1384 * use if none were provided in the LDAP URL
1385 * (e.g., ldap:///...)
1387 if ((ludp
->lud_port
== 0) && (ludp
->lud_host
== NULL
)) {
1389 (void) snprintf(errmsg
, MAXERROR
, "%s: %s",
1390 gettext("no LDAP handle when"
1391 " processing referrals URL"),
1393 syslog(LOG_WARNING
, "libsldap: %s", errmsg
);
1394 ldap_free_urldesc(ludp
);
1396 return (NS_LDAP_SUCCESS
);
1398 (void) ldap_get_option(ld
, LDAP_OPT_HOST_NAME
,
1400 if (ld_defhost
== NULL
) {
1401 (void) snprintf(errmsg
, MAXERROR
, "%s: %s",
1402 gettext("not able to retrieve default "
1403 "host when processing "
1406 syslog(LOG_WARNING
, "libsldap: %s", errmsg
);
1407 ldap_free_urldesc(ludp
);
1409 return (NS_LDAP_SUCCESS
);
1411 ref
->refHost
= strdup(ld_defhost
);
1412 if (ref
->refHost
== NULL
) {
1413 ldap_free_urldesc(ludp
);
1415 return (NS_LDAP_MEMORY
);
1422 * 1 for the last '\0'.
1423 * 1 for host and prot separator ":"
1424 * and "[" & "]" for possible ipV6 addressing
1426 hostlen
= strlen(ludp
->lud_host
) +
1427 sizeof (MAXPORTNUMBER_STR
) + 4;
1428 ref
->refHost
= (char *)malloc(hostlen
);
1429 if (ref
->refHost
== NULL
) {
1430 ldap_free_urldesc(ludp
);
1432 return (NS_LDAP_MEMORY
);
1435 if (ludp
->lud_port
!= 0) {
1437 * serverAddr = host:port
1439 * if host is an IPV6 address
1442 tmp
= strstr(url
, ludp
->lud_host
);
1443 if (tmp
&& (tmp
> url
) && *(tmp
- 1) == '[') {
1444 (void) snprintf(ref
->refHost
, hostlen
,
1449 (void) snprintf(ref
->refHost
, hostlen
,
1455 /* serverAddr = host */
1456 (void) snprintf(ref
->refHost
, hostlen
, "%s",
1462 ref
->refDN
= strdup(ludp
->lud_dn
);
1463 if (ref
->refDN
== NULL
) {
1464 ldap_free_urldesc(ludp
);
1467 return (NS_LDAP_MEMORY
);
1471 ref
->refDN
= strdup(baseDN
);
1472 if (ref
->refDN
== NULL
) {
1473 ldap_free_urldesc(ludp
);
1476 return (NS_LDAP_MEMORY
);
1482 ref
->refFilter
= strdup(filter
);
1483 else if (ludp
->lud_filter
)
1484 ref
->refFilter
= strdup(ludp
->lud_filter
);
1486 ref
->refFilter
= strdup("");
1488 if (ref
->refFilter
== NULL
) {
1489 ldap_free_urldesc(ludp
);
1494 return (NS_LDAP_MEMORY
);
1498 * If the scope is specified in the URL use it.
1499 * Note if the scope is missing in the URL, ldap_url_parse_nodn()
1500 * returns the scope BASE. We need to check that the scope of BASE
1501 * is actually present in the URL.
1502 * If the scope is missing in the URL then use the passed-in
1504 * If there is no passed-in scope, then use the scope SUBTREE.
1506 if (ludp
->lud_dn
&& ludp
->lud_scope
!= LDAP_SCOPE_BASE
)
1507 ref
->refScope
= ludp
->lud_scope
;
1508 else if (ludp
->lud_dn
&& strstr(url
, "?base"))
1509 ref
->refScope
= LDAP_SCOPE_BASE
;
1511 ref
->refScope
= *scope
;
1513 ref
->refScope
= LDAP_SCOPE_SUBTREE
;
1517 ldap_free_urldesc(ludp
);
1519 /* insert the referral info */
1521 for (tmpref
= *head
; tmpref
->next
; tmpref
= tmpref
->next
)
1527 return (NS_LDAP_SUCCESS
);
1531 * FUNCTION: __s_api_deleteRefInfo
1532 * Delete a referral info list.
1533 * INPUT: pointer to the referral info list
1536 __s_api_deleteRefInfo(ns_referral_info_t
*head
)
1538 ns_referral_info_t
*ref
, *tmp
;
1541 (void) fprintf(stderr
, "__s_api_deleteRefInfo START\n");
1544 for (ref
= head
; ref
; ) {
1550 free(ref
->refFilter
);
1559 * FUNCTION: __s_api_get_SSD_from_SSDtoUse_service
1561 * Retrieves the Service Search Descriptors which should be used for
1562 * the given service. For example, return all the "passwd" SSDs for
1563 * service "shadow" if no SSD is defined for service "shadow" and
1564 * no filter component is defined in all the "passwd" SSDs. This idea
1565 * of sharing the SSDs defined for some other service is to reduce the
1566 * configuration complexity. For a service, which does not have its own
1567 * entries in the LDAP directory, SSD for it is useless, and should not
1568 * be set. But since this service must share the container with at least
1569 * one other service which does have it own entries, the SSD for
1570 * this other service will be shared by this service.
1571 * This other service is called the SSD-to-use service.
1572 * The static data structure, ns_def_map[], in this file
1573 * defines the SSD-to-use service for all the services supported.
1575 * RETURN VALUES: NS_LDAP_SUCCESS, NS_LDAP_MEMORY, NS_LDAP_INVALID_PARAM
1577 * OUTPUT: *SSDlist, *errorp if error
1580 __s_api_get_SSD_from_SSDtoUse_service(const char *service
,
1581 ns_ldap_search_desc_t
***SSDlist
,
1582 ns_ldap_error_t
**errorp
)
1586 int filter_found
= FALSE
;
1587 char *SSD_service
= NULL
;
1588 char errmsg
[MAXERROR
];
1589 ns_ldap_search_desc_t
**sdlist
;
1590 int auto_service
= FALSE
;
1593 (void) fprintf(stderr
,
1594 "__s_api_get_SSD_from_SSDtoUse_service START\n");
1597 if (SSDlist
== NULL
|| errorp
== NULL
)
1598 return (NS_LDAP_INVALID_PARAM
);
1603 if (service
== NULL
)
1604 return (NS_LDAP_SUCCESS
);
1606 if (strncasecmp(service
, "auto_", 5) == 0)
1607 auto_service
= TRUE
;
1610 * First try to return the configured SSDs for the input server
1612 rc
= __ns_ldap_getSearchDescriptors(service
, SSDlist
, errorp
);
1613 if (rc
!= NS_LDAP_SUCCESS
)
1616 if (*SSDlist
!= NULL
)
1617 return (NS_LDAP_SUCCESS
);
1621 * If service == auto_* and SSD is not found,
1622 * then try automount to see if there is an SSD
1627 rc
= __ns_ldap_getSearchDescriptors(
1628 "automount", SSDlist
, errorp
);
1629 if (rc
!= NS_LDAP_SUCCESS
)
1632 if (*SSDlist
!= NULL
) {
1634 * If SSDlist is found,
1635 * prepend automountMapName to the basedn
1639 rc
= __s_api_prepend_automountmapname(
1644 if (rc
!= NS_LDAP_SUCCESS
) {
1645 (void) __ns_ldap_freeSearchDescriptors(
1656 * Find the SSDtoUse service.
1657 * If none found, flag "found" remains FALSE.
1659 for (i
= 0; ns_def_map
[i
].service
!= NULL
; i
++) {
1660 if (ns_def_map
[i
].SSDtoUse_service
&&
1662 ns_def_map
[i
].service
) == 0) {
1664 SSD_service
= ns_def_map
[i
].SSDtoUse_service
;
1670 return (NS_LDAP_SUCCESS
);
1673 * return the SSDs for SSD_service only if no optional filter
1674 * component is defined in the SSDs
1676 rc
= __ns_ldap_getSearchDescriptors(SSD_service
,
1678 if (rc
!= NS_LDAP_SUCCESS
) {
1681 if (*SSDlist
== NULL
)
1682 return (NS_LDAP_SUCCESS
);
1684 /* check to see if filter defined in SSD */
1685 for (sdlist
= *SSDlist
; *sdlist
; sdlist
++) {
1686 if ((*sdlist
)->filter
&&
1687 strlen((*sdlist
)->filter
) > 0) {
1688 filter_found
= TRUE
;
1693 (void) __ns_ldap_freeSearchDescriptors(SSDlist
);
1695 (void) snprintf(errmsg
, sizeof (errmsg
),
1696 gettext("Service search descriptor for "
1697 "service '%s' contains filter, "
1698 "which can not be used for "
1700 SSD_service
, service
);
1701 MKERROR(LOG_WARNING
, *errorp
, NS_CONFIG_FILE
,
1702 strdup(errmsg
), NS_LDAP_CONFIG
);
1703 return (NS_LDAP_CONFIG
);
1707 return (NS_LDAP_SUCCESS
);
1712 * verify addr is an IPv4 address with the optional [:portno]
1713 * RFC2373 & RFC2732 & RFC2396
1716 __s_api_isipv4(char *addr
)
1718 int i
, seg
, digit
, port
;
1723 digit
= seg
= port
= 0;
1725 for (i
= 0; i
< strlen(addr
); i
++) {
1726 if (isdigit(addr
[i
])) {
1730 if (addr
[i
] == '.') {
1731 if (digit
> 3 || digit
== 0)
1737 if (addr
[i
] == ':') {
1748 if ((seg
== 3 && port
== 0 && digit
> 0 && digit
< 4) ||
1749 (seg
== 4 && port
== 1 && digit
> 0))
1757 * verify addr is an IPv6 address with the optional [IPv6]:portno
1758 * RFC2373 & RFC2732 & RFC2396
1761 __s_api_isipv6(char *addr
)
1763 int i
, col
, digit
, port
, dc
, tc
;
1764 char *laddr
, *c1
, *s
;
1771 digit
= col
= port
= 0;
1772 if (addr
[0] == '[') {
1773 laddr
= strdup(addr
);
1776 c1
= strchr(laddr
, ']');
1777 /* only 1 ']' should be in an addr */
1778 if (!c1
|| (strchr(c1
+1, ']')))
1783 for (i
= 2; i
< strlen(c1
); i
++) {
1784 if (!isdigit(c1
[i
]))
1801 digit
= dc
= tc
= 0;
1802 for (i
= 0; i
< strlen(s
); i
++) {
1803 if (isxdigit(s
[i
])) {
1812 if ((col
> 1) || (i
&& !col
&& !digit
))
1819 if (__s_api_isipv4(&s
[dc
]) && tc
)
1837 * verify addr is a valid hostname with the optional [:portno]
1838 * RFC2373 & RFC2732 & RFC2396
1841 __s_api_ishost(char *addr
)
1843 int i
, seg
, alpha
, digit
, port
;
1848 alpha
= digit
= seg
= port
= 0;
1850 /* must start with alpha character */
1851 if (!isalpha(addr
[0]))
1854 for (i
= 0; i
< strlen(addr
); i
++) {
1855 if (isalpha(addr
[i
]) || (i
&& addr
[i
] == '-')) {
1859 if (isdigit(addr
[i
])) {
1863 if (addr
[i
] == '.') {
1864 if (!alpha
&& !digit
)
1870 if (addr
[i
] == ':') {
1871 if (!alpha
&& !digit
)
1881 if ((port
== 0 && (seg
|| alpha
|| digit
)) ||
1882 (port
== 1 && alpha
== 0 && digit
))
1890 * Prepend automountMapName=auto_xxx to the basedn
1894 int __s_api_prepend_automountmapname(
1895 const char *service
,
1896 ns_ldap_search_desc_t
***SSDlist
,
1897 ns_ldap_error_t
**errorp
)
1900 ns_ldap_search_desc_t
** ssdlist
= NULL
;
1902 if (service
== NULL
|| SSDlist
== NULL
|| *SSDlist
== NULL
)
1903 return (NS_LDAP_INVALID_PARAM
);
1907 for (i
= 0; ssdlist
[i
] != NULL
; i
++) {
1908 rc
= __s_api_prepend_automountmapname_to_dn(
1909 service
, &ssdlist
[i
]->basedn
, errorp
);
1911 if (rc
!= NS_LDAP_SUCCESS
)
1915 return (NS_LDAP_SUCCESS
);
1920 * Prepend automountMapName=auto_xxx to the DN
1921 * Construct a string of
1922 * "automountMapName=auto_xxx,dn"
1924 * If automountMapName is mapped to some other attribute,
1925 * then use the mapping in the setup.
1927 * If a version 1 profile is in use, use nisMapName for
1928 * backward compatibility (i.e. "nisMapName=auto_xxx,dn").
1932 __s_api_prepend_automountmapname_to_dn(
1933 const char *service
,
1935 ns_ldap_error_t
**errorp
)
1937 int rc
, len_s
= 0, len_d
= 0, len
= 0;
1938 char *buffer
= NULL
;
1939 char *default_automountmapname
= "automountMapName";
1940 char *automountmapname
= NULL
;
1941 char **mappedattrs
= NULL
;
1942 char errstr
[MAXERROR
];
1943 void **paramVal
= NULL
;
1945 if (service
== NULL
|| dn
== NULL
|| *dn
== NULL
)
1946 return (NS_LDAP_INVALID_PARAM
);
1948 rc
= __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P
, ¶mVal
, errorp
);
1949 if (rc
!= NS_LDAP_SUCCESS
|| !paramVal
|| !*paramVal
) {
1951 (void) __ns_ldap_freeParam(¶mVal
);
1954 if (strcasecmp(*paramVal
, NS_LDAP_VERSION_1
) == 0) {
1955 automountmapname
= strdup("nisMapName");
1956 (void) __ns_ldap_freeParam(¶mVal
);
1957 if (automountmapname
== NULL
) {
1958 return (NS_LDAP_MEMORY
);
1961 (void) __ns_ldap_freeParam(¶mVal
);
1963 /* Find mapped attribute name of auto_xxx first */
1964 mappedattrs
= __ns_ldap_getMappedAttributes(
1965 service
, default_automountmapname
);
1967 * if mapped attribute name of auto_xxx is not found,
1968 * find the mapped attribute name of automount
1971 if (mappedattrs
== NULL
)
1972 mappedattrs
= __ns_ldap_getMappedAttributes(
1973 "automount", default_automountmapname
);
1976 * if mapped attr is not found, use the default automountmapname
1979 if (mappedattrs
== NULL
) {
1980 automountmapname
= strdup(default_automountmapname
);
1981 if (automountmapname
== NULL
)
1982 return (NS_LDAP_MEMORY
);
1984 if (mappedattrs
[0] != NULL
) {
1986 * Copy it from the mapped attr list
1987 * Assume it's 1 to 1 mapping
1988 * 1 to n does not make sense
1990 automountmapname
= strdup(mappedattrs
[0]);
1991 __s_api_free2dArray(mappedattrs
);
1992 if (automountmapname
== NULL
) {
1993 return (NS_LDAP_MEMORY
);
1998 * automountmapname is mapped to an empty string
2001 __s_api_free2dArray(mappedattrs
);
2003 (void) sprintf(errstr
,
2005 "Attribute automountMapName is "
2006 "mapped to an empty string.\n"));
2008 MKERROR(LOG_WARNING
, *errorp
, NS_CONFIG_SYNTAX
,
2009 strdup(errstr
), NS_LDAP_MEMORY
);
2011 return (NS_LDAP_CONFIG
);
2016 len_s
= strlen(service
);
2017 len_d
= strlen(*dn
);
2018 /* automountMapName + "=" + service + "," + dn + '\0' */
2019 len
= strlen(automountmapname
) + 1 + len_s
+ 1 + len_d
+ 1;
2020 buffer
= (char *)malloc(len
);
2021 if (buffer
== NULL
) {
2022 free(automountmapname
);
2023 return (NS_LDAP_MEMORY
);
2026 (void) snprintf(buffer
, len
, "%s=%s,%s",
2027 automountmapname
, service
, *dn
);
2029 buffer
[len
-1] = '\0';
2031 free(automountmapname
);
2033 /* free the original dn */
2038 return (NS_LDAP_SUCCESS
);
2042 * Map the LDAP error code and error message from LDAP server
2043 * to a password status used for password aging/management.
2045 ns_ldap_passwd_status_t
2046 __s_api_set_passwd_status(int errnum
, char *errmsg
)
2048 syslog(LOG_DEBUG
, "libsldap: got LDAP errnum %d & message: %s ", errnum
,
2049 (errmsg
!= NULL
) ? errmsg
: "error msg not available");
2052 LDAP_INVALID_CREDENTIALS
) {
2059 return (NS_PASSWD_EXPIRED
);
2063 LDAP_UNWILLING_TO_PERFORM
) {
2070 return (NS_PASSWD_EXPIRED
);
2074 * Account inactivated
2077 NS_PWDERR_ACCT_INACTIVATED
))
2078 return (NS_PASSWD_EXPIRED
);
2082 * case 3 (Modify passwd):
2083 * the user is not allow to change
2084 * password; only admin can change it
2087 NS_PWDERR_CHANGE_NOT_ALLOW
))
2088 return (NS_PASSWD_CHANGE_NOT_ALLOWED
);
2092 LDAP_CONSTRAINT_VIOLATION
) {
2095 * the user account is locked due to
2096 * too many login failures.
2099 NS_PWDERR_MAXTRIES
))
2100 return (NS_PASSWD_RETRY_EXCEEDED
);
2102 * case 5 (Modify passwd):
2103 * syntax error: the new password
2104 * has length less than defined
2106 * Not true anymore with strong password
2107 * policies on LDAP server: errmsg that
2108 * contain NS_PWDERR_INVALID_SYNTAX may
2109 * have different meanings.
2110 * To keep compatibility with older password
2111 * policy, check if errmsg is strictly equal
2112 * to NS_PWDERR_INVALID_SYNTAX and if yes only,
2113 * return NS_PASSWD_TOO_SHORT.
2116 NS_PWDERR_INVALID_SYNTAX
) == 0)
2117 return (NS_PASSWD_TOO_SHORT
);
2119 NS_PWDERR_INVALID_SYNTAX
))
2120 return (NS_PASSWD_INVALID_SYNTAX
);
2122 * case 6 (Modify passwd):
2123 * trivial password: same value as
2124 * that of attribute cn, sn, or uid ...
2127 NS_PWDERR_TRIVIAL_PASSWD
))
2128 return (NS_PASSWD_INVALID_SYNTAX
);
2130 * case 7 (Modify passwd):
2131 * re-use one of the old passwords
2135 NS_PWDERR_IN_HISTORY
))
2136 return (NS_PASSWD_IN_HISTORY
);
2138 * case 8 (Modify passwd):
2139 * password not allowed to be
2140 * changed yet; within minimum
2144 NS_PWDERR_WITHIN_MIN_AGE
))
2145 return (NS_PASSWD_WITHIN_MIN_AGE
);
2150 return (NS_PASSWD_GOOD
);
2154 * Determine if the input OID list contains
2155 * one of the password control OIDs, which are:
2156 * LDAP_CONTROL_PWEXPIRED: 2.16.840.1.113730.3.4.4
2157 * LDAP_CONTROL_PWEXPIRING: 2.16.840.1.113730.3.4.5.
2158 * If yes, return 1, if no, 0.
2161 __s_api_contain_passwd_control_oid(char **oids
)
2168 for (oid
= oids
; *oid
; oid
++) {
2169 if (strcmp(*oid
, LDAP_CONTROL_PWEXPIRED
) == 0 ||
2170 strcmp(*oid
, LDAP_CONTROL_PWEXPIRING
) == 0) {
2179 * Determine if the input OID list contains LDAP V3 password less
2180 * account management control OID, which is:
2181 * NS_LDAP_ACCOUNT_USABLE_CONTROL:1.3.6.1.4.1.42.2.27.9.5.8
2182 * If yes, return 1, if no, 0.
2185 __s_api_contain_account_usable_control_oid(char **oids
)
2192 for (oid
= oids
; *oid
; oid
++) {
2193 if (strcmp(*oid
, NS_LDAP_ACCOUNT_USABLE_CONTROL
) == 0) {
2202 * For some databases in name switch, the name and aliases are saved
2203 * as "cn". When the "cn" valuse are retrieved, there is no distinction
2204 * which is the name and which is(are) aliase(s).
2205 * This function is to parse RDN and find the value of the "cn" and
2206 * then find the matching value in "cn" attribute.
2207 * Also see RFC 2307 section 5.6.
2210 * entry: An LDAP entry
2211 * attrptr: A attribute which value appears in RDN
2212 * This should be "cn" for the name switch for now.
2213 * case_ignore: 0 Case sensitive comparison on the attribute value
2214 * 1 Case insensitive comparison
2217 * The value of an attrbute which is used as canonical name
2218 * This is read only and the caller should not try to free it.
2219 * If it's a NULL, it could be either an RDN parsing error
2220 * or RDN value does not match any existing "cn" values.
2222 * dn: cn=xx+ipserviceprotocol=udp,......
2227 * Although the name switch/ldap's rdn is in "cn=xx" or "cn=xx+..."
2228 * format, this function makes no such assumption. If the DN
2229 * is saved as "dn: yy=...+sn=my_canocical_name, ..", then it can still work.
2230 * The comments use "cn" as an example only.
2233 typedef int (*cmpfunc
)(const char *, const char *);
2236 __s_api_get_canonical_name(ns_ldap_entry_t
*entry
, ns_ldap_attr_t
*attrptr
,
2239 char *token
, *lasts
, *value
= NULL
;
2240 char **rdn
= NULL
, **attrs
= NULL
, **values
= NULL
;
2241 char *rdn_attr_value
= NULL
;
2244 if (entry
== NULL
|| attrptr
== NULL
)
2247 /* "values" is read-only */
2248 if ((values
= __ns_ldap_getAttr(entry
, "dn")) == NULL
||
2252 if ((rdn
= ldap_explode_dn(values
[0], 0)) == NULL
||
2256 if ((attrs
= ldap_explode_rdn(rdn
[0], 0)) == NULL
) {
2257 ldap_value_free(rdn
);
2260 /* Assume the rdn is normalized */
2261 for (i
= 0; attrs
[i
] != NULL
; i
++) {
2262 /* parse attribute name and value, get attribute name first */
2263 if ((token
= strtok_r(attrs
[i
], "=", &lasts
)) == NULL
) {
2266 if (strcasecmp(token
, attrptr
->attrname
) == 0) {
2268 rdn_attr_value
= lasts
;
2272 if (rdn_attr_value
) {
2278 * After parsing RDN and find the matching attribute in RDN,
2279 * match rdn value with values in "cn".
2281 for (i
= 0; i
< attrptr
->value_count
; i
++) {
2282 if (attrptr
->attrvalue
[i
] &&
2283 (*cmp
)(rdn_attr_value
,
2284 attrptr
->attrvalue
[i
]) == 0) {
2285 /* RDN "cn" value matches the "cn" value */
2286 value
= attrptr
->attrvalue
[i
];
2292 ldap_value_free(rdn
);
2293 ldap_value_free(attrs
);
2299 * This function requests a server to be removed from
2300 * the cache manager maintained server list. This is
2301 * done via the door functionality.
2302 * Returns 0 if OK, else a negative value.
2306 __s_api_removeServer(const char *server
)
2310 char s_b
[DOORBUFFERSIZE
];
2313 ns_server_info_t r
, *ret
= &r
;
2320 ns_ldap_error_t
*error
= NULL
;
2325 ireq
= NS_CACHE_NORESP
;
2327 if (__s_api_isStandalone()) {
2329 * Remove 'server' from the standalone server list.
2330 * __s_api_findRootDSE() is the standalone version
2331 * of getldap_get_serverInfo() used in ldap_cachemgr.
2332 * Request NS_CACHE_NORESP indicates 'server' should
2335 if (__s_api_findRootDSE(ireq
,
2339 &error
) != NS_LDAP_SUCCESS
) {
2341 "libsldap (\"standalone\" mode): "
2342 " Unable to remove %s - %s",
2344 error
!= NULL
&& error
->message
!= NULL
?
2345 error
->message
: " no error info");
2346 if (error
!= NULL
) {
2347 (void) __ns_ldap_freeError(&error
);
2350 return (NS_CACHE_NOSERVER
);
2356 (void) memset(ret
, 0, sizeof (ns_server_info_t
));
2357 (void) memset(space
.s_b
, 0, DOORBUFFERSIZE
);
2359 adata
= (sizeof (ldap_call_t
) + strlen(ireq
) +
2360 strlen(NS_CACHE_ADDR_IP
) + 1);
2361 adata
+= strlen(DOORLINESEP
) + 1;
2362 adata
+= strlen(server
) + 1;
2364 ndata
= sizeof (space
);
2365 space
.s_d
.ldap_call
.ldap_callnumber
= GETLDAPSERVER
;
2366 len
= sizeof (space
) - sizeof (space
.s_d
.ldap_call
.ldap_callnumber
);
2367 if (strlcpy(space
.s_d
.ldap_call
.ldap_u
.domainname
, ireq
, len
) >= len
)
2369 if (strlcat(space
.s_d
.ldap_call
.ldap_u
.domainname
,
2370 NS_CACHE_ADDR_IP
, len
) >= len
)
2372 if (strlcat(space
.s_d
.ldap_call
.ldap_u
.domainname
, DOORLINESEP
, len
) >=
2375 if (strlcat(space
.s_d
.ldap_call
.ldap_u
.domainname
, server
, len
) >= len
)
2379 /* try to remove the server via the door interface */
2380 rc
= __ns_ldap_trydoorcall(&sptr
, &ndata
, &adata
);
2382 /* clean up the door call */
2383 if (sptr
!= &space
.s_d
) {
2384 (void) munmap((char *)sptr
, ndata
);
2391 __s_api_free_server_info(ns_server_info_t
*sinfo
) {
2392 if (sinfo
->server
) {
2393 free(sinfo
->server
);
2394 sinfo
->server
= NULL
;
2396 if (sinfo
->serverFQDN
) {
2397 free(sinfo
->serverFQDN
);
2398 sinfo
->serverFQDN
= NULL
;
2400 __s_api_free2dArray(sinfo
->saslMechanisms
);
2401 sinfo
->saslMechanisms
= NULL
;
2402 __s_api_free2dArray(sinfo
->controls
);
2403 sinfo
->controls
= NULL
;
2407 * Create an ns_ldap_error structure, set status to 'rc',
2408 * and copy in the error message 'msg'.
2411 __s_api_make_error(int rc
, char *msg
) {
2412 ns_ldap_error_t
*ep
;
2414 ep
= (ns_ldap_error_t
*)calloc(1, sizeof (*ep
));
2420 ep
->message
= strdup(msg
); /* OK if ep->message is NULL */
2426 * Make a copy of the input ns_ldap_error.
2429 __s_api_copy_error(ns_ldap_error_t
*errorp
) {
2430 ns_ldap_error_t
*ep
;
2436 ep
= (ns_ldap_error_t
*)malloc(sizeof (*ep
));
2439 if (ep
->message
!= NULL
) {
2440 msg
= strdup(ep
->message
);