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
},
86 static char ** parseDN(const char *val
, const char *service
);
87 static char ** sortServerNet(char **srvlist
);
88 static char ** sortServerPref(char **srvlist
, char **preflist
,
89 boolean_t flag
, int version
, int *error
);
92 * FUNCTION: s_api_printResult
93 * Given a ns_ldap_result structure print it.
96 __s_api_printResult(ns_ldap_result_t
*result
)
99 ns_ldap_entry_t
*curEntry
;
103 (void) fprintf(stderr
, "__s_api_printResult START\n");
105 (void) printf("--------------------------------------\n");
106 if (result
== NULL
) {
107 (void) printf("No result\n");
110 (void) printf("entries_count %d\n", result
->entries_count
);
111 curEntry
= result
->entry
;
112 for (i
= 0; i
< result
->entries_count
; i
++) {
114 (void) printf("entry %d has attr_count = %d \n", i
,
115 curEntry
->attr_count
);
116 for (j
= 0; j
< curEntry
->attr_count
; j
++) {
117 (void) printf("entry %d has attr_pair[%d] = %s \n",
118 i
, j
, curEntry
->attr_pair
[j
]->attrname
);
119 for (k
= 0; k
< 20 &&
120 curEntry
->attr_pair
[j
]->attrvalue
[k
]; k
++)
121 (void) printf("entry %d has attr_pair[%d]->"
122 "attrvalue[%d] = %s \n", i
, j
, k
,
123 curEntry
->attr_pair
[j
]->attrvalue
[k
]);
125 (void) printf("\n--------------------------------------\n");
126 curEntry
= curEntry
->next
;
132 * FUNCTION: __s_api_getSearchScope
134 * Retrieve the search scope for ldap search from the config module.
136 * RETURN VALUES: NS_LDAP_SUCCESS, NS_LDAP_CONFIG
138 * OUTPUT: searchScope, errorp
141 __s_api_getSearchScope(
143 ns_ldap_error_t
**errorp
)
146 char errmsg
[MAXERROR
];
147 void **paramVal
= NULL
;
152 (void) fprintf(stderr
, "__s_api_getSearchScope START\n");
154 if (*searchScope
== 0) {
155 if ((rc
= __ns_ldap_getParam(NS_LDAP_SEARCH_SCOPE_P
,
156 ¶mVal
, errorp
)) != NS_LDAP_SUCCESS
) {
159 if (paramVal
&& *paramVal
)
160 scope
= * (int *)(*paramVal
);
162 scope
= NS_LDAP_SCOPE_ONELEVEL
;
163 (void) __ns_ldap_freeParam(¶mVal
);
165 scope
= *searchScope
;
170 case NS_LDAP_SCOPE_ONELEVEL
:
171 *searchScope
= LDAP_SCOPE_ONELEVEL
;
173 case NS_LDAP_SCOPE_BASE
:
174 *searchScope
= LDAP_SCOPE_BASE
;
176 case NS_LDAP_SCOPE_SUBTREE
:
177 *searchScope
= LDAP_SCOPE_SUBTREE
;
180 (void) snprintf(errmsg
, sizeof (errmsg
),
181 gettext("Invalid search scope!"));
182 MKERROR(LOG_ERR
, *errorp
, NS_CONFIG_FILE
,
183 strdup(errmsg
), NS_LDAP_CONFIG
);
184 return (NS_LDAP_CONFIG
);
187 return (NS_LDAP_SUCCESS
);
191 * FUNCTION: __ns_ldap_dupAuth
193 * Duplicates an authentication structure.
195 * RETURN VALUES: copy of authp or NULL on error
199 __ns_ldap_dupAuth(const ns_cred_t
*authp
)
204 (void) fprintf(stderr
, "__ns_ldap_dupAuth START\n");
209 ap
= (ns_cred_t
*)calloc(1, sizeof (ns_cred_t
));
213 if (authp
->hostcertpath
) {
214 ap
->hostcertpath
= strdup(authp
->hostcertpath
);
215 if (ap
->hostcertpath
== NULL
) {
220 if (authp
->cred
.unix_cred
.userID
) {
221 ap
->cred
.unix_cred
.userID
=
222 strdup(authp
->cred
.unix_cred
.userID
);
223 if (ap
->cred
.unix_cred
.userID
== NULL
) {
224 (void) __ns_ldap_freeCred(&ap
);
228 if (authp
->cred
.unix_cred
.passwd
) {
229 ap
->cred
.unix_cred
.passwd
=
230 strdup(authp
->cred
.unix_cred
.passwd
);
231 if (ap
->cred
.unix_cred
.passwd
== NULL
) {
232 (void) __ns_ldap_freeCred(&ap
);
236 if (authp
->cred
.cert_cred
.nickname
) {
237 ap
->cred
.cert_cred
.nickname
=
238 strdup(authp
->cred
.cert_cred
.nickname
);
239 if (ap
->cred
.cert_cred
.nickname
== NULL
) {
240 (void) __ns_ldap_freeCred(&ap
);
244 ap
->auth
.type
= authp
->auth
.type
;
245 ap
->auth
.tlstype
= authp
->auth
.tlstype
;
246 ap
->auth
.saslmech
= authp
->auth
.saslmech
;
247 ap
->auth
.saslopt
= authp
->auth
.saslopt
;
252 * FUNCTION: __ns_ldap_freeUnixCred
254 * Frees all the memory associated with a UnixCred_t structure.
256 * RETURN VALUES: NS_LDAP_INVALID_PARAM, NS_LDAP_SUCCESS
260 __ns_ldap_freeUnixCred(UnixCred_t
** credp
)
265 (void) fprintf(stderr
, "__ns_ldap_freeUnixCred START\n");
267 if (credp
== NULL
|| *credp
== NULL
)
268 return (NS_LDAP_INVALID_PARAM
);
272 (void) memset(ap
->userID
, 0, strlen(ap
->userID
));
277 (void) memset(ap
->passwd
, 0, strlen(ap
->passwd
));
283 return (NS_LDAP_SUCCESS
);
287 * FUNCTION: __ns_ldap_freeCred
289 * Frees all the memory associated with a ns_cred_t structure.
291 * RETURN VALUES: NS_LDAP_INVALID_PARAM, NS_LDAP_SUCCESS
295 __ns_ldap_freeCred(ns_cred_t
** credp
)
300 (void) fprintf(stderr
, "__ns_ldap_freeCred START\n");
302 if (credp
== NULL
|| *credp
== NULL
)
303 return (NS_LDAP_INVALID_PARAM
);
306 if (ap
->hostcertpath
) {
307 (void) memset(ap
->hostcertpath
, 0,
308 strlen(ap
->hostcertpath
));
309 free(ap
->hostcertpath
);
312 if (ap
->cred
.unix_cred
.userID
) {
313 (void) memset(ap
->cred
.unix_cred
.userID
, 0,
314 strlen(ap
->cred
.unix_cred
.userID
));
315 free(ap
->cred
.unix_cred
.userID
);
318 if (ap
->cred
.unix_cred
.passwd
) {
319 (void) memset(ap
->cred
.unix_cred
.passwd
, 0,
320 strlen(ap
->cred
.unix_cred
.passwd
));
321 free(ap
->cred
.unix_cred
.passwd
);
324 if (ap
->cred
.cert_cred
.nickname
) {
325 (void) memset(ap
->cred
.cert_cred
.nickname
, 0,
326 strlen(ap
->cred
.cert_cred
.nickname
));
327 free(ap
->cred
.cert_cred
.nickname
);
332 return (NS_LDAP_SUCCESS
);
336 * FUNCTION: __s_api_is_auth_matched
338 * Compare an authentication structure.
340 * RETURN VALUES: B_TRUE if matched, B_FALSE otherwise.
341 * INPUT: auth1, auth2
344 __s_api_is_auth_matched(const ns_cred_t
*auth1
,
345 const ns_cred_t
*auth2
)
347 if ((auth1
->auth
.type
!= auth2
->auth
.type
) ||
348 (auth1
->auth
.tlstype
!= auth2
->auth
.tlstype
) ||
349 (auth1
->auth
.saslmech
!= auth2
->auth
.saslmech
) ||
350 (auth1
->auth
.saslopt
!= auth2
->auth
.saslopt
))
353 if ((((auth1
->auth
.type
== NS_LDAP_AUTH_SASL
) &&
354 ((auth1
->auth
.saslmech
== NS_LDAP_SASL_CRAM_MD5
) ||
355 (auth1
->auth
.saslmech
== NS_LDAP_SASL_DIGEST_MD5
))) ||
356 (auth1
->auth
.type
== NS_LDAP_AUTH_SIMPLE
)) &&
357 ((auth1
->cred
.unix_cred
.userID
== NULL
) ||
358 (auth1
->cred
.unix_cred
.passwd
== NULL
) ||
359 ((strcasecmp(auth1
->cred
.unix_cred
.userID
,
360 auth2
->cred
.unix_cred
.userID
) != 0)) ||
361 ((strcmp(auth1
->cred
.unix_cred
.passwd
,
362 auth2
->cred
.unix_cred
.passwd
) != 0))))
369 * FUNCTION: __s_api_getDNs
371 * Retrieves the default base dn for the given
374 * RETURN VALUES: NS_LDAP_SUCCESS, NS_LDAP_MEMORY, NS_LDAP_CONFIG
378 typedef int (*pf
)(const char *, char **, ns_ldap_error_t
**);
383 ns_ldap_error_t
** error
)
386 void **paramVal
= NULL
;
390 pf prepend_auto2dn
= __s_api_prepend_automountmapname_to_dn
;
393 (void) fprintf(stderr
, "__s_api_getDNs START\n");
395 if ((rc
= __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P
,
396 ¶mVal
, error
)) != NS_LDAP_SUCCESS
) {
400 char errmsg
[MAXERROR
];
402 (void) snprintf(errmsg
, sizeof (errmsg
),
403 gettext("BaseDN not defined"));
404 MKERROR(LOG_ERR
, *error
, NS_CONFIG_FILE
, strdup(errmsg
),
406 return (NS_LDAP_CONFIG
);
409 dns
= (char **)calloc(2, sizeof (char *));
411 (void) __ns_ldap_freeParam(¶mVal
);
412 return (NS_LDAP_MEMORY
);
415 if (service
== NULL
) {
416 dns
[0] = strdup((char *)*paramVal
);
417 if (dns
[0] == NULL
) {
418 (void) __ns_ldap_freeParam(¶mVal
);
420 return (NS_LDAP_MEMORY
);
423 for (i
= 0; ns_def_map
[i
].service
!= NULL
; i
++) {
424 if (strcasecmp(service
,
425 ns_def_map
[i
].service
) == 0) {
427 len
= strlen((char *)*paramVal
) +
428 strlen(ns_def_map
[i
].rdn
) + 1;
430 calloc(len
, sizeof (char));
431 if (dns
[0] == NULL
) {
432 (void) __ns_ldap_freeParam(
435 return (NS_LDAP_MEMORY
);
437 (void) strcpy(dns
[0],
439 (void) strcat(dns
[0],
444 if (ns_def_map
[i
].service
== NULL
) {
445 char *p
= (char *)*paramVal
;
449 if (strchr(service
, '=') == NULL
) {
450 /* automount entries */
451 if (strncasecmp(service
, "auto_", 5) == 0) {
455 (void) __ns_ldap_freeParam(
457 return (NS_LDAP_MEMORY
);
459 /* shorten name to avoid cstyle error */
460 rc
= prepend_auto2dn(
461 service
, &buffer
, error
);
462 if (rc
!= NS_LDAP_SUCCESS
) {
465 (void) __ns_ldap_freeParam(
470 /* strlen("nisMapName")+"="+","+'\0' = 13 */
471 buflen
= strlen(service
) + strlen(p
) +
473 buffer
= (char *)malloc(buflen
);
474 if (buffer
== NULL
) {
476 (void) __ns_ldap_freeParam(
478 return (NS_LDAP_MEMORY
);
480 (void) snprintf(buffer
, buflen
,
481 "nisMapName=%s,%s", service
, p
);
484 buflen
= strlen(service
) + strlen(p
) + 2;
485 buffer
= (char *)malloc(buflen
);
486 if (buffer
== NULL
) {
488 (void) __ns_ldap_freeParam(¶mVal
);
489 return (NS_LDAP_MEMORY
);
491 (void) snprintf(buffer
, buflen
,
492 "%s,%s", service
, p
);
498 (void) __ns_ldap_freeParam(¶mVal
);
500 return (NS_LDAP_SUCCESS
);
503 * FUNCTION: __s_api_get_search_DNs_v1
505 * Retrieves the list of search DNS from the V1 profile for the given
508 * RETURN VALUES: NS_LDAP_SUCCESS, NS_LDAP_MEMORY, NS_LDAP_CONFIG
513 __s_api_get_search_DNs_v1(
516 ns_ldap_error_t
** error
)
519 void **paramVal
= NULL
;
520 void **temptr
= NULL
;
524 if ((rc
= __ns_ldap_getParam(NS_LDAP_SEARCH_DN_P
,
525 ¶mVal
, error
)) != NS_LDAP_SUCCESS
) {
529 if (service
&& paramVal
) {
530 for (temptr
= paramVal
; *temptr
!= NULL
; temptr
++) {
531 dns
= parseDN((const char *)(*temptr
),
532 (const char *)service
);
538 (void) __ns_ldap_freeParam(¶mVal
);
540 return (NS_LDAP_SUCCESS
);
546 * Parse a special formated list(val) into an array of char *.
548 * RETURN VALUE: A char * pointer to the new list of dns.
549 * INPUT: val, service
559 char **retVal
= NULL
;
566 char *SSD_service
= NULL
;
569 (void) fprintf(stderr
, "parseDN START\n");
571 if (val
== NULL
|| *val
== '\0')
573 if (service
== NULL
|| *service
== '\0')
577 slen
= strlen(service
);
578 if (strncasecmp(val
, service
, slen
) != 0) {
580 * This routine is only called
581 * to process V1 profile and
582 * for V1 profile, map service
583 * to the corresponding SSD_service
584 * which is associated with a
585 * real container in the LDAP directory
586 * tree, e.g., map "shadow" to
587 * "password". See function
588 * __s_api_get_SSD_from_SSDtoUse_service
589 * for similar service to SSD_service
590 * mapping handling for V2 profile.
592 for (i
= 0; ns_def_map
[i
].service
!= NULL
; i
++) {
593 if (ns_def_map
[i
].SSDtoUse_service
&&
595 ns_def_map
[i
].service
) == 0) {
597 ns_def_map
[i
].SSDtoUse_service
;
602 if (SSD_service
== NULL
)
605 slen
= strlen(SSD_service
);
606 if (strncasecmp(val
, SSD_service
, slen
) != 0)
611 while (*temptr
== SPACETOK
|| *temptr
== TABTOK
)
613 if (*temptr
!= COLONTOK
)
617 temptr2
= strchr(temptr
, OPARATOK
);
621 temptr2
= strchr(temptr2
, CPARATOK
);
628 retVal
= (char **)calloc(valNo
+1, sizeof (char *));
635 for (i
= 0; (i
< valNo
) && (temptr
< valend
); i
++) {
636 temptr
= strchr(temptr
, OPARATOK
);
637 if (temptr
== NULL
) {
638 __s_api_free2dArray(retVal
);
642 temptr2
= strchr(temptr
, CPARATOK
);
643 if (temptr2
== NULL
) {
644 __s_api_free2dArray(retVal
);
647 valSize
= temptr2
- temptr
;
649 retVal
[i
] = (char *)calloc(valSize
+ 1, sizeof (char));
650 if (retVal
[i
] == NULL
) {
651 __s_api_free2dArray(retVal
);
654 (void) strncpy(retVal
[i
], temptr
, valSize
);
655 retVal
[i
][valSize
] = '\0';
656 temptr
= temptr2
+ 1;
664 * __s_api_get_local_interfaces
666 * Returns a pointer to an array of addresses and netmasks of all interfaces
667 * configured on the system.
669 * NOTE: This function is very IPv4 centric.
671 static struct ifinfo
*
672 __s_api_get_local_interfaces()
675 struct ifreq ifreq
, *ifr
;
676 struct ifinfo
*localinfo
;
677 struct in_addr netmask
;
678 struct sockaddr_in
*sin
;
684 if ((fd
= open(UDP
, O_RDONLY
)) < 0)
687 if (ioctl(fd
, SIOCGIFNUM
, (char *)&numifs
) < 0) {
691 buf
= malloc(numifs
* sizeof (struct ifreq
));
696 ifc
.ifc_len
= numifs
* (int)sizeof (struct ifreq
);
698 if (ioctl(fd
, SIOCGIFCONF
, (char *)&ifc
) < 0) {
704 ifr
= (struct ifreq
*)buf
;
705 numifs
= ifc
.ifc_len
/(int)sizeof (struct ifreq
);
706 localinfo
= (struct ifinfo
*)malloc((numifs
+ 1) *
707 sizeof (struct ifinfo
));
708 if (localinfo
== NULL
) {
715 for (i
= 0, n
= numifs
; n
> 0; n
--, ifr
++) {
719 if (ioctl(fd
, SIOCGIFFLAGS
, (char *)&ifreq
) < 0)
722 ifrflags
= ifreq
.ifr_flags
;
723 if (((ifrflags
& IFF_UP
) == 0) ||
724 (ifr
->ifr_addr
.sa_family
!= AF_INET
))
727 if (ioctl(fd
, SIOCGIFNETMASK
, (char *)&ifreq
) < 0)
729 netmask
= ((struct sockaddr_in
*)&ifreq
.ifr_addr
)->sin_addr
;
731 if (ioctl(fd
, SIOCGIFADDR
, (char *)&ifreq
) < 0)
734 sin
= (struct sockaddr_in
*)&ifreq
.ifr_addr
;
736 localinfo
[i
].addr
= sin
->sin_addr
;
737 localinfo
[i
].netmask
= netmask
;
740 localinfo
[i
].addr
.s_addr
= 0;
750 * __s_api_samenet(char *, struct ifinfo *)
752 * Returns 1 if address is on the same subnet of the array of addresses
755 * NOTE: This function is only valid for IPv4 addresses.
758 __s_api_IPv4sameNet(char *addr
, struct ifinfo
*ifs
)
767 if ((addr_raw
= strdup(addr
)) != NULL
) {
770 /* Remove port number. */
771 if ((s
= strchr(addr_raw
, ':')) != NULL
)
774 iaddr
= inet_addr(addr_raw
);
776 /* Loop through interface list to find match. */
777 for (i
= 0; ifs
[i
].addr
.s_addr
!= 0; i
++) {
778 if ((iaddr
& ifs
[i
].netmask
.s_addr
) ==
779 (ifs
[i
].addr
.s_addr
&
780 ifs
[i
].netmask
.s_addr
))
791 * FUNCTION: __s_api_getServers
793 * Retrieve a list of ldap servers from the config module.
795 * RETURN VALUE: NS_LDAP_SUCCESS, NS_LDAP_CONFIG, NS_LDAP_MEMORY
797 * OUTPUT: servers, error
802 ns_ldap_error_t
** error
)
804 void **paramVal
= NULL
;
805 char errmsg
[MAXERROR
];
806 char **sortServers
= NULL
;
807 char **netservers
= NULL
;
808 int rc
= 0, err
= NS_LDAP_CONFIG
, version
= 1;
809 const char *str
, *str1
;
812 (void) fprintf(stderr
, "__s_api_getServers START\n");
815 /* get profile version number */
816 if ((rc
= __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P
,
817 ¶mVal
, error
)) != NS_LDAP_SUCCESS
)
820 if (paramVal
== NULL
|| *paramVal
== NULL
) {
821 (void) snprintf(errmsg
, sizeof (errmsg
),
822 gettext("No file version"));
823 MKERROR(LOG_INFO
, *error
, NS_CONFIG_FILE
, strdup(errmsg
),
825 return (NS_LDAP_CONFIG
);
828 if (strcasecmp((char *)*paramVal
, NS_LDAP_VERSION_1
) == 0)
830 else if (strcasecmp((char *)*paramVal
, NS_LDAP_VERSION_2
) == 0)
833 (void) __ns_ldap_freeParam(¶mVal
);
836 if ((rc
= __ns_ldap_getParam(NS_LDAP_SERVERS_P
,
837 ¶mVal
, error
)) != NS_LDAP_SUCCESS
)
841 * For version 2, default server list could be
844 if ((paramVal
== NULL
|| (char *)*paramVal
== NULL
) &&
846 str
= NULL_OR_STR(__s_api_get_configname(NS_LDAP_SERVERS_P
));
847 (void) snprintf(errmsg
, sizeof (errmsg
),
848 gettext("Unable to retrieve the '%s' list"), str
);
849 MKERROR(LOG_WARNING
, *error
, NS_CONFIG_FILE
, strdup(errmsg
),
851 return (NS_LDAP_CONFIG
);
855 * Get server address(es) and go through them.
857 *servers
= (char **)paramVal
;
860 /* Sort servers based on network. */
862 netservers
= sortServerNet(*servers
);
865 *servers
= netservers
;
867 return (NS_LDAP_MEMORY
);
871 /* Get preferred server list and sort servers based on that. */
872 if ((rc
= __ns_ldap_getParam(NS_LDAP_SERVER_PREF_P
,
873 ¶mVal
, error
)) != NS_LDAP_SUCCESS
) {
875 __s_api_free2dArray(*servers
);
880 if (paramVal
!= NULL
) {
884 if ((rc
= __ns_ldap_getParam(NS_LDAP_PREF_ONLY_P
,
885 &val
, error
)) != NS_LDAP_SUCCESS
) {
887 __s_api_free2dArray(*servers
);
889 (void) __ns_ldap_freeParam(¶mVal
);
893 prefServers
= (char **)paramVal
;
896 if (val
!= NULL
&& (*val
) != NULL
&&
898 sortServers
= sortServerPref(*servers
,
899 prefServers
, B_FALSE
, version
,
902 sortServers
= sortServerPref(*servers
,
903 prefServers
, B_TRUE
, version
,
910 *servers
= sortServers
;
913 __s_api_free2dArray(*servers
);
915 __s_api_free2dArray(prefServers
);
919 (void) __ns_ldap_freeParam(&val
);
921 (void) __ns_ldap_freeParam(¶mVal
);
923 if (*servers
== NULL
) {
924 if (err
== NS_LDAP_CONFIG
) {
925 str
= NULL_OR_STR(__s_api_get_configname(
927 str1
= NULL_OR_STR(__s_api_get_configname(
928 NS_LDAP_SERVER_PREF_P
));
929 (void) snprintf(errmsg
, sizeof (errmsg
),
930 gettext("Unable to generate a new server list "
931 "based on '%s' and/or '%s'"), str
, str1
);
932 MKERROR(LOG_WARNING
, *error
, NS_CONFIG_FILE
,
933 strdup(errmsg
), err
);
936 return (NS_LDAP_MEMORY
);
939 return (NS_LDAP_SUCCESS
);
944 * FUNCTION: sortServerNet
945 * Sort the serverlist based on the distance from client as long
946 * as the list only contains IPv4 addresses. Otherwise do nothing.
949 sortServerNet(char **srvlist
)
954 struct ifinfo
*ifs
= __s_api_get_local_interfaces();
956 char **psrvs
, **retsrvs
;
959 if (srvlist
== NULL
|| srvlist
[0] == NULL
)
962 /* Count the number of servers to sort. */
963 for (count
= 0; srvlist
[count
] != NULL
; count
++) {
964 if (!__s_api_isipv4(srvlist
[count
]))
969 /* Make room for the returned list of servers. */
970 retsrvs
= (char **)calloc(count
, sizeof (char *));
971 if (retsrvs
== NULL
) {
977 retsrvs
[count
- 1] = NULL
;
979 /* Make a temporary list of servers. */
980 psrvs
= (char **)calloc(count
, sizeof (char *));
989 /* Filter servers on the same subnet */
992 if (ipv4only
&& __s_api_IPv4sameNet(*tsrvs
, ifs
)) {
994 retsrvs
[all
++] = *(tsrvs
);
999 /* Filter remaining servers. */
1002 char **ttsrvs
= psrvs
;
1005 if (strcmp(*tsrvs
, *ttsrvs
) == 0)
1010 if (*ttsrvs
== NULL
)
1011 retsrvs
[all
++] = *(tsrvs
);
1024 * FUNCTION: sortServerPref
1025 * Sort the serverlist based on the preferred server list.
1027 * The sorting algorithm works as follows:
1029 * If version 1, if flag is TRUE, find all the servers in both preflist
1030 * and srvlist, then append other servers in srvlist to this list
1031 * and return the list.
1032 * If flag is FALSE, just return srvlist.
1033 * srvlist can not be empty.
1035 * If version 2, append all the servers in srvlist
1036 * but not in preflist to preflist, and return the merged list.
1037 * If srvlist is empty, just return preflist.
1038 * If preflist is empty, just return srvlist.
1041 sortServerPref(char **srvlist
, char **preflist
,
1042 boolean_t flag
, int version
, int *error
)
1044 int i
, scount
= 0, pcount
= 0;
1045 int all
= 0, dup
= 0;
1050 /* Count the number of servers to sort. */
1051 if (srvlist
&& srvlist
[0])
1052 for (i
= 0; srvlist
[i
] != NULL
; i
++)
1056 if (scount
== 0 && version
== 1) {
1057 *error
= NS_LDAP_CONFIG
;
1061 /* Count the number of preferred servers */
1062 if (preflist
&& preflist
[0])
1063 for (i
= 0; preflist
[i
] != NULL
; i
++)
1067 if (scount
== 0 && pcount
== 0) {
1068 *error
= NS_LDAP_CONFIG
;
1072 /* Make room for the returned list of servers */
1073 retsrvs
= (char **)calloc(scount
+ pcount
+ 1, sizeof (char *));
1074 if (retsrvs
== NULL
) {
1075 *error
= NS_LDAP_MEMORY
;
1080 * if the preferred server list is empty,
1081 * just return a copy of the server list
1086 retsrvs
[all
++] = *(tsrvs
++);
1092 * if the server list is empty,
1093 * just return a copy of the preferred server list
1098 retsrvs
[all
++] = *(tsrvs
++);
1103 /* Make room for the servers whose memory needs to be freed */
1104 dupsrvs
= (char **)calloc(scount
+ pcount
+ 1, sizeof (char *));
1105 if (dupsrvs
== NULL
) {
1107 *error
= NS_LDAP_MEMORY
;
1113 * throw out preferred servers not on server list.
1114 * If version 2, make a copy of the preferred server list.
1119 char **ttsrvs
= srvlist
;
1122 if (strcmp(*tsrvs
, *(ttsrvs
)) == 0)
1126 if (*ttsrvs
!= NULL
)
1127 retsrvs
[all
++] = *tsrvs
;
1129 dupsrvs
[dup
++] = *tsrvs
;
1135 retsrvs
[all
++] = *(tsrvs
++);
1139 * if PREF_ONLY is false, we append the non-preferred servers
1140 * to bottom of list.
1141 * For version 2, always append.
1143 if (flag
== B_TRUE
|| version
!= 1) {
1147 char **ttsrvs
= preflist
;
1150 if (strcmp(*tsrvs
, *ttsrvs
) == 0) {
1155 if (*ttsrvs
== NULL
)
1156 retsrvs
[all
++] = *tsrvs
;
1158 dupsrvs
[dup
++] = *tsrvs
;
1163 /* free memory for duplicate servers */
1165 for (tsrvs
= dupsrvs
; *tsrvs
; tsrvs
++)
1174 * FUNCTION: __s_api_removeBadServers
1175 * Contacts the ldap cache manager for marking the
1176 * problem servers as down, so that the server is
1177 * not contacted until the TTL expires.
1180 __s_api_removeBadServers(char ** Servers
)
1185 if (Servers
== NULL
)
1188 for (host
= Servers
; *host
!= NULL
; host
++) {
1189 if (__s_api_removeServer(*host
) < 0) {
1191 * Couldn't remove server from
1192 * server list. Log a warning.
1194 syslog(LOG_WARNING
, "libsldap: could "
1195 "not remove %s from servers list", *host
);
1201 * FUNCTION: __s_api_free2dArray
1204 __s_api_free2dArray(char ** inarray
)
1209 if (inarray
== NULL
)
1212 for (temptr
= inarray
; *temptr
!= NULL
; temptr
++) {
1219 * FUNCTION: __s_api_cp2dArray
1222 __s_api_cp2dArray(char **inarray
)
1225 char **ttarray
, *ret
;
1228 if (inarray
== NULL
)
1231 for (count
= 0; inarray
[count
] != NULL
; count
++)
1234 newarray
= (char **)calloc(count
+ 1, sizeof (char *));
1235 if (newarray
== NULL
)
1239 for (; *inarray
; inarray
++) {
1240 *(ttarray
++) = ret
= strdup(*inarray
);
1242 __s_api_free2dArray(newarray
);
1250 * FUNCTION: __s_api_isCtrlSupported
1251 * Determines if the passed control is supported by the LDAP sever.
1252 * RETURNS: NS_LDAP_SUCCESS if yes, NS_LDAP_OP_FAIL if not.
1255 __s_api_isCtrlSupported(Connection
*con
, char *ctrlString
)
1260 len
= strlen(ctrlString
);
1261 for (ctrl
= con
->controls
; ctrl
&& *ctrl
; ctrl
++) {
1262 if (strncasecmp(*ctrl
, ctrlString
, len
) == 0)
1263 return (NS_LDAP_SUCCESS
);
1265 return (NS_LDAP_OP_FAILED
);
1269 * FUNCTION: __s_api_toFollowReferrals
1270 * Determines if need to follow referral for an SLDAP API.
1271 * RETURN VALUES: NS_LDAP_SUCCESS, NS_LDAP_INVALID_PARAM, or
1272 * other rc from __ns_ldap_getParam()
1274 * OUTPUT: toFollow, errorp
1277 __s_api_toFollowReferrals(const int flags
,
1279 ns_ldap_error_t
**errorp
)
1281 void **paramVal
= NULL
;
1286 (void) fprintf(stderr
, "__s_api_toFollowReferrals START\n");
1289 /* Either NS_LDAP_NOREF or NS_LDAP_FOLLOWREF not both */
1290 if ((flags
& (NS_LDAP_NOREF
| NS_LDAP_FOLLOWREF
)) ==
1291 (NS_LDAP_NOREF
| NS_LDAP_FOLLOWREF
)) {
1292 return (NS_LDAP_INVALID_PARAM
);
1296 * if the NS_LDAP_NOREF or NS_LDAP_FOLLOWREF is set
1297 * this will take precendence over the values specified
1298 * in the configuration file
1300 if (flags
& (NS_LDAP_NOREF
| NS_LDAP_FOLLOWREF
)) {
1303 rc
= __ns_ldap_getParam(NS_LDAP_SEARCH_REF_P
,
1305 if (rc
!= NS_LDAP_SUCCESS
)
1307 if (paramVal
== NULL
|| *paramVal
== NULL
) {
1308 (void) __ns_ldap_freeParam(¶mVal
);
1310 (void) __ns_ldap_freeError(errorp
);
1312 return (NS_LDAP_SUCCESS
);
1314 iflags
= (* (int *)(*paramVal
));
1315 (void) __ns_ldap_freeParam(¶mVal
);
1318 if (iflags
& NS_LDAP_NOREF
)
1323 return (NS_LDAP_SUCCESS
);
1327 * FUNCTION: __s_api_addRefInfo
1328 * Insert a referral info into a referral info list.
1329 * RETURN VALUES: NS_LDAP_SUCCESS, NS_LDAP_MEMORY, NS_LDAP_OP_FAILED
1330 * INPUT: LDAP URL, pointer to the referral info list,
1331 * search baseDN, search scope, search filter,
1332 * previous connection
1335 __s_api_addRefInfo(ns_referral_info_t
**head
, char *url
,
1336 char *baseDN
, int *scope
,
1337 char *filter
, LDAP
*ld
)
1339 char errmsg
[MAXERROR
], *tmp
;
1340 ns_referral_info_t
*ref
, *tmpref
;
1341 LDAPURLDesc
*ludp
= NULL
;
1343 char *ld_defhost
= NULL
;
1346 (void) fprintf(stderr
, "__s_api_addRefInfo START\n");
1351 return (NS_LDAP_OP_FAILED
);
1354 * log error and return NS_LDAP_SUCCESS
1355 * if one of the following:
1357 * 2. LDAP URL which can not be parsed
1359 if (!ldap_is_ldap_url(url
) ||
1360 ldap_url_parse_nodn(url
, &ludp
) != 0) {
1361 (void) snprintf(errmsg
, MAXERROR
, "%s: %s",
1362 gettext("Invalid or non-LDAP URL when"
1363 " processing referrals URL"),
1365 syslog(LOG_ERR
, "libsldap: %s", errmsg
);
1367 ldap_free_urldesc(ludp
);
1368 return (NS_LDAP_SUCCESS
);
1371 ref
= (ns_referral_info_t
*)calloc(1,
1372 sizeof (ns_referral_info_t
));
1374 ldap_free_urldesc(ludp
);
1375 return (NS_LDAP_MEMORY
);
1379 * we do have a valid URL and we were able to parse it
1380 * however, we still need to find out what hostport to
1381 * use if none were provided in the LDAP URL
1382 * (e.g., ldap:///...)
1384 if ((ludp
->lud_port
== 0) && (ludp
->lud_host
== NULL
)) {
1386 (void) snprintf(errmsg
, MAXERROR
, "%s: %s",
1387 gettext("no LDAP handle when"
1388 " processing referrals URL"),
1390 syslog(LOG_WARNING
, "libsldap: %s", errmsg
);
1391 ldap_free_urldesc(ludp
);
1393 return (NS_LDAP_SUCCESS
);
1395 (void) ldap_get_option(ld
, LDAP_OPT_HOST_NAME
,
1397 if (ld_defhost
== NULL
) {
1398 (void) snprintf(errmsg
, MAXERROR
, "%s: %s",
1399 gettext("not able to retrieve default "
1400 "host when processing "
1403 syslog(LOG_WARNING
, "libsldap: %s", errmsg
);
1404 ldap_free_urldesc(ludp
);
1406 return (NS_LDAP_SUCCESS
);
1408 ref
->refHost
= strdup(ld_defhost
);
1409 if (ref
->refHost
== NULL
) {
1410 ldap_free_urldesc(ludp
);
1412 return (NS_LDAP_MEMORY
);
1419 * 1 for the last '\0'.
1420 * 1 for host and prot separator ":"
1421 * and "[" & "]" for possible ipV6 addressing
1423 hostlen
= strlen(ludp
->lud_host
) +
1424 sizeof (MAXPORTNUMBER_STR
) + 4;
1425 ref
->refHost
= (char *)malloc(hostlen
);
1426 if (ref
->refHost
== NULL
) {
1427 ldap_free_urldesc(ludp
);
1429 return (NS_LDAP_MEMORY
);
1432 if (ludp
->lud_port
!= 0) {
1434 * serverAddr = host:port
1436 * if host is an IPV6 address
1439 tmp
= strstr(url
, ludp
->lud_host
);
1440 if (tmp
&& (tmp
> url
) && *(tmp
- 1) == '[') {
1441 (void) snprintf(ref
->refHost
, hostlen
,
1446 (void) snprintf(ref
->refHost
, hostlen
,
1452 /* serverAddr = host */
1453 (void) snprintf(ref
->refHost
, hostlen
, "%s",
1459 ref
->refDN
= strdup(ludp
->lud_dn
);
1460 if (ref
->refDN
== NULL
) {
1461 ldap_free_urldesc(ludp
);
1464 return (NS_LDAP_MEMORY
);
1468 ref
->refDN
= strdup(baseDN
);
1469 if (ref
->refDN
== NULL
) {
1470 ldap_free_urldesc(ludp
);
1473 return (NS_LDAP_MEMORY
);
1479 ref
->refFilter
= strdup(filter
);
1480 else if (ludp
->lud_filter
)
1481 ref
->refFilter
= strdup(ludp
->lud_filter
);
1483 ref
->refFilter
= strdup("");
1485 if (ref
->refFilter
== NULL
) {
1486 ldap_free_urldesc(ludp
);
1490 return (NS_LDAP_MEMORY
);
1494 * If the scope is specified in the URL use it.
1495 * Note if the scope is missing in the URL, ldap_url_parse_nodn()
1496 * returns the scope BASE. We need to check that the scope of BASE
1497 * is actually present in the URL.
1498 * If the scope is missing in the URL then use the passed-in
1500 * If there is no passed-in scope, then use the scope SUBTREE.
1502 if (ludp
->lud_dn
&& ludp
->lud_scope
!= LDAP_SCOPE_BASE
)
1503 ref
->refScope
= ludp
->lud_scope
;
1504 else if (ludp
->lud_dn
&& strstr(url
, "?base"))
1505 ref
->refScope
= LDAP_SCOPE_BASE
;
1507 ref
->refScope
= *scope
;
1509 ref
->refScope
= LDAP_SCOPE_SUBTREE
;
1513 ldap_free_urldesc(ludp
);
1515 /* insert the referral info */
1517 for (tmpref
= *head
; tmpref
->next
; tmpref
= tmpref
->next
)
1523 return (NS_LDAP_SUCCESS
);
1527 * FUNCTION: __s_api_deleteRefInfo
1528 * Delete a referral info list.
1529 * INPUT: pointer to the referral info list
1532 __s_api_deleteRefInfo(ns_referral_info_t
*head
)
1534 ns_referral_info_t
*ref
, *tmp
;
1537 (void) fprintf(stderr
, "__s_api_deleteRefInfo START\n");
1540 for (ref
= head
; ref
; ) {
1543 free(ref
->refFilter
);
1552 * FUNCTION: __s_api_get_SSD_from_SSDtoUse_service
1554 * Retrieves the Service Search Descriptors which should be used for
1555 * the given service. For example, return all the "passwd" SSDs for
1556 * service "shadow" if no SSD is defined for service "shadow" and
1557 * no filter component is defined in all the "passwd" SSDs. This idea
1558 * of sharing the SSDs defined for some other service is to reduce the
1559 * configuration complexity. For a service, which does not have its own
1560 * entries in the LDAP directory, SSD for it is useless, and should not
1561 * be set. But since this service must share the container with at least
1562 * one other service which does have it own entries, the SSD for
1563 * this other service will be shared by this service.
1564 * This other service is called the SSD-to-use service.
1565 * The static data structure, ns_def_map[], in this file
1566 * defines the SSD-to-use service for all the services supported.
1568 * RETURN VALUES: NS_LDAP_SUCCESS, NS_LDAP_MEMORY, NS_LDAP_INVALID_PARAM
1570 * OUTPUT: *SSDlist, *errorp if error
1573 __s_api_get_SSD_from_SSDtoUse_service(const char *service
,
1574 ns_ldap_search_desc_t
***SSDlist
,
1575 ns_ldap_error_t
**errorp
)
1579 int filter_found
= FALSE
;
1580 char *SSD_service
= NULL
;
1581 char errmsg
[MAXERROR
];
1582 ns_ldap_search_desc_t
**sdlist
;
1583 int auto_service
= FALSE
;
1586 (void) fprintf(stderr
,
1587 "__s_api_get_SSD_from_SSDtoUse_service START\n");
1590 if (SSDlist
== NULL
|| errorp
== NULL
)
1591 return (NS_LDAP_INVALID_PARAM
);
1596 if (service
== NULL
)
1597 return (NS_LDAP_SUCCESS
);
1599 if (strncasecmp(service
, "auto_", 5) == 0)
1600 auto_service
= TRUE
;
1603 * First try to return the configured SSDs for the input server
1605 rc
= __ns_ldap_getSearchDescriptors(service
, SSDlist
, errorp
);
1606 if (rc
!= NS_LDAP_SUCCESS
)
1609 if (*SSDlist
!= NULL
)
1610 return (NS_LDAP_SUCCESS
);
1614 * If service == auto_* and SSD is not found,
1615 * then try automount to see if there is an SSD
1620 rc
= __ns_ldap_getSearchDescriptors(
1621 "automount", SSDlist
, errorp
);
1622 if (rc
!= NS_LDAP_SUCCESS
)
1625 if (*SSDlist
!= NULL
) {
1627 * If SSDlist is found,
1628 * prepend automountMapName to the basedn
1632 rc
= __s_api_prepend_automountmapname(
1637 if (rc
!= NS_LDAP_SUCCESS
) {
1638 (void) __ns_ldap_freeSearchDescriptors(
1649 * Find the SSDtoUse service.
1650 * If none found, flag "found" remains FALSE.
1652 for (i
= 0; ns_def_map
[i
].service
!= NULL
; i
++) {
1653 if (ns_def_map
[i
].SSDtoUse_service
&&
1655 ns_def_map
[i
].service
) == 0) {
1657 SSD_service
= ns_def_map
[i
].SSDtoUse_service
;
1663 return (NS_LDAP_SUCCESS
);
1666 * return the SSDs for SSD_service only if no optional filter
1667 * component is defined in the SSDs
1669 rc
= __ns_ldap_getSearchDescriptors(SSD_service
,
1671 if (rc
!= NS_LDAP_SUCCESS
) {
1674 if (*SSDlist
== NULL
)
1675 return (NS_LDAP_SUCCESS
);
1677 /* check to see if filter defined in SSD */
1678 for (sdlist
= *SSDlist
; *sdlist
; sdlist
++) {
1679 if ((*sdlist
)->filter
&&
1680 strlen((*sdlist
)->filter
) > 0) {
1681 filter_found
= TRUE
;
1686 (void) __ns_ldap_freeSearchDescriptors(SSDlist
);
1688 (void) snprintf(errmsg
, sizeof (errmsg
),
1689 gettext("Service search descriptor for "
1690 "service '%s' contains filter, "
1691 "which can not be used for "
1693 SSD_service
, service
);
1694 MKERROR(LOG_WARNING
, *errorp
, NS_CONFIG_FILE
,
1695 strdup(errmsg
), NS_LDAP_CONFIG
);
1696 return (NS_LDAP_CONFIG
);
1700 return (NS_LDAP_SUCCESS
);
1705 * verify addr is an IPv4 address with the optional [:portno]
1706 * RFC2373 & RFC2732 & RFC2396
1709 __s_api_isipv4(char *addr
)
1711 int i
, seg
, digit
, port
;
1716 digit
= seg
= port
= 0;
1718 for (i
= 0; i
< strlen(addr
); i
++) {
1719 if (isdigit(addr
[i
])) {
1723 if (addr
[i
] == '.') {
1724 if (digit
> 3 || digit
== 0)
1730 if (addr
[i
] == ':') {
1741 if ((seg
== 3 && port
== 0 && digit
> 0 && digit
< 4) ||
1742 (seg
== 4 && port
== 1 && digit
> 0))
1750 * verify addr is an IPv6 address with the optional [IPv6]:portno
1751 * RFC2373 & RFC2732 & RFC2396
1754 __s_api_isipv6(char *addr
)
1756 int i
, col
, digit
, port
, dc
, tc
;
1757 char *laddr
, *c1
, *s
;
1764 digit
= col
= port
= 0;
1765 if (addr
[0] == '[') {
1766 laddr
= strdup(addr
);
1769 c1
= strchr(laddr
, ']');
1770 /* only 1 ']' should be in an addr */
1771 if (!c1
|| (strchr(c1
+1, ']')))
1776 for (i
= 2; i
< strlen(c1
); i
++) {
1777 if (!isdigit(c1
[i
]))
1794 digit
= dc
= tc
= 0;
1795 for (i
= 0; i
< strlen(s
); i
++) {
1796 if (isxdigit(s
[i
])) {
1805 if ((col
> 1) || (i
&& !col
&& !digit
))
1812 if (__s_api_isipv4(&s
[dc
]) && tc
)
1830 * verify addr is a valid hostname with the optional [:portno]
1831 * RFC2373 & RFC2732 & RFC2396
1834 __s_api_ishost(char *addr
)
1836 int i
, seg
, alpha
, digit
, port
;
1841 alpha
= digit
= seg
= port
= 0;
1843 /* must start with alpha character */
1844 if (!isalpha(addr
[0]))
1847 for (i
= 0; i
< strlen(addr
); i
++) {
1848 if (isalpha(addr
[i
]) || (i
&& addr
[i
] == '-')) {
1852 if (isdigit(addr
[i
])) {
1856 if (addr
[i
] == '.') {
1857 if (!alpha
&& !digit
)
1863 if (addr
[i
] == ':') {
1864 if (!alpha
&& !digit
)
1874 if ((port
== 0 && (seg
|| alpha
|| digit
)) ||
1875 (port
== 1 && alpha
== 0 && digit
))
1883 * Prepend automountMapName=auto_xxx to the basedn
1887 int __s_api_prepend_automountmapname(
1888 const char *service
,
1889 ns_ldap_search_desc_t
***SSDlist
,
1890 ns_ldap_error_t
**errorp
)
1893 ns_ldap_search_desc_t
** ssdlist
= NULL
;
1895 if (service
== NULL
|| SSDlist
== NULL
|| *SSDlist
== NULL
)
1896 return (NS_LDAP_INVALID_PARAM
);
1900 for (i
= 0; ssdlist
[i
] != NULL
; i
++) {
1901 rc
= __s_api_prepend_automountmapname_to_dn(
1902 service
, &ssdlist
[i
]->basedn
, errorp
);
1904 if (rc
!= NS_LDAP_SUCCESS
)
1908 return (NS_LDAP_SUCCESS
);
1913 * Prepend automountMapName=auto_xxx to the DN
1914 * Construct a string of
1915 * "automountMapName=auto_xxx,dn"
1917 * If automountMapName is mapped to some other attribute,
1918 * then use the mapping in the setup.
1920 * If a version 1 profile is in use, use nisMapName for
1921 * backward compatibility (i.e. "nisMapName=auto_xxx,dn").
1925 __s_api_prepend_automountmapname_to_dn(
1926 const char *service
,
1928 ns_ldap_error_t
**errorp
)
1930 int rc
, len_s
= 0, len_d
= 0, len
= 0;
1931 char *buffer
= NULL
;
1932 char *default_automountmapname
= "automountMapName";
1933 char *automountmapname
= NULL
;
1934 char **mappedattrs
= NULL
;
1935 char errstr
[MAXERROR
];
1936 void **paramVal
= NULL
;
1938 if (service
== NULL
|| dn
== NULL
|| *dn
== NULL
)
1939 return (NS_LDAP_INVALID_PARAM
);
1941 rc
= __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P
, ¶mVal
, errorp
);
1942 if (rc
!= NS_LDAP_SUCCESS
|| !paramVal
|| !*paramVal
) {
1944 (void) __ns_ldap_freeParam(¶mVal
);
1947 if (strcasecmp(*paramVal
, NS_LDAP_VERSION_1
) == 0) {
1948 automountmapname
= strdup("nisMapName");
1949 (void) __ns_ldap_freeParam(¶mVal
);
1950 if (automountmapname
== NULL
) {
1951 return (NS_LDAP_MEMORY
);
1954 (void) __ns_ldap_freeParam(¶mVal
);
1956 /* Find mapped attribute name of auto_xxx first */
1957 mappedattrs
= __ns_ldap_getMappedAttributes(
1958 service
, default_automountmapname
);
1960 * if mapped attribute name of auto_xxx is not found,
1961 * find the mapped attribute name of automount
1964 if (mappedattrs
== NULL
)
1965 mappedattrs
= __ns_ldap_getMappedAttributes(
1966 "automount", default_automountmapname
);
1969 * if mapped attr is not found, use the default automountmapname
1972 if (mappedattrs
== NULL
) {
1973 automountmapname
= strdup(default_automountmapname
);
1974 if (automountmapname
== NULL
)
1975 return (NS_LDAP_MEMORY
);
1977 if (mappedattrs
[0] != NULL
) {
1979 * Copy it from the mapped attr list
1980 * Assume it's 1 to 1 mapping
1981 * 1 to n does not make sense
1983 automountmapname
= strdup(mappedattrs
[0]);
1984 __s_api_free2dArray(mappedattrs
);
1985 if (automountmapname
== NULL
) {
1986 return (NS_LDAP_MEMORY
);
1991 * automountmapname is mapped to an empty string
1994 __s_api_free2dArray(mappedattrs
);
1996 (void) sprintf(errstr
,
1998 "Attribute automountMapName is "
1999 "mapped to an empty string.\n"));
2001 MKERROR(LOG_WARNING
, *errorp
, NS_CONFIG_SYNTAX
,
2002 strdup(errstr
), NS_LDAP_MEMORY
);
2004 return (NS_LDAP_CONFIG
);
2009 len_s
= strlen(service
);
2010 len_d
= strlen(*dn
);
2011 /* automountMapName + "=" + service + "," + dn + '\0' */
2012 len
= strlen(automountmapname
) + 1 + len_s
+ 1 + len_d
+ 1;
2013 buffer
= (char *)malloc(len
);
2014 if (buffer
== NULL
) {
2015 free(automountmapname
);
2016 return (NS_LDAP_MEMORY
);
2019 (void) snprintf(buffer
, len
, "%s=%s,%s",
2020 automountmapname
, service
, *dn
);
2022 buffer
[len
-1] = '\0';
2024 free(automountmapname
);
2026 /* free the original dn */
2031 return (NS_LDAP_SUCCESS
);
2035 * Map the LDAP error code and error message from LDAP server
2036 * to a password status used for password aging/management.
2038 ns_ldap_passwd_status_t
2039 __s_api_set_passwd_status(int errnum
, char *errmsg
)
2041 syslog(LOG_DEBUG
, "libsldap: got LDAP errnum %d & message: %s ", errnum
,
2042 (errmsg
!= NULL
) ? errmsg
: "error msg not available");
2045 LDAP_INVALID_CREDENTIALS
) {
2052 return (NS_PASSWD_EXPIRED
);
2056 LDAP_UNWILLING_TO_PERFORM
) {
2063 return (NS_PASSWD_EXPIRED
);
2067 * Account inactivated
2070 NS_PWDERR_ACCT_INACTIVATED
))
2071 return (NS_PASSWD_EXPIRED
);
2075 * case 3 (Modify passwd):
2076 * the user is not allow to change
2077 * password; only admin can change it
2080 NS_PWDERR_CHANGE_NOT_ALLOW
))
2081 return (NS_PASSWD_CHANGE_NOT_ALLOWED
);
2085 LDAP_CONSTRAINT_VIOLATION
) {
2088 * the user account is locked due to
2089 * too many login failures.
2092 NS_PWDERR_MAXTRIES
))
2093 return (NS_PASSWD_RETRY_EXCEEDED
);
2095 * case 5 (Modify passwd):
2096 * syntax error: the new password
2097 * has length less than defined
2099 * Not true anymore with strong password
2100 * policies on LDAP server: errmsg that
2101 * contain NS_PWDERR_INVALID_SYNTAX may
2102 * have different meanings.
2103 * To keep compatibility with older password
2104 * policy, check if errmsg is strictly equal
2105 * to NS_PWDERR_INVALID_SYNTAX and if yes only,
2106 * return NS_PASSWD_TOO_SHORT.
2109 NS_PWDERR_INVALID_SYNTAX
) == 0)
2110 return (NS_PASSWD_TOO_SHORT
);
2112 NS_PWDERR_INVALID_SYNTAX
))
2113 return (NS_PASSWD_INVALID_SYNTAX
);
2115 * case 6 (Modify passwd):
2116 * trivial password: same value as
2117 * that of attribute cn, sn, or uid ...
2120 NS_PWDERR_TRIVIAL_PASSWD
))
2121 return (NS_PASSWD_INVALID_SYNTAX
);
2123 * case 7 (Modify passwd):
2124 * re-use one of the old passwords
2128 NS_PWDERR_IN_HISTORY
))
2129 return (NS_PASSWD_IN_HISTORY
);
2131 * case 8 (Modify passwd):
2132 * password not allowed to be
2133 * changed yet; within minimum
2137 NS_PWDERR_WITHIN_MIN_AGE
))
2138 return (NS_PASSWD_WITHIN_MIN_AGE
);
2143 return (NS_PASSWD_GOOD
);
2147 * Determine if the input OID list contains
2148 * one of the password control OIDs, which are:
2149 * LDAP_CONTROL_PWEXPIRED: 2.16.840.1.113730.3.4.4
2150 * LDAP_CONTROL_PWEXPIRING: 2.16.840.1.113730.3.4.5.
2151 * If yes, return 1, if no, 0.
2154 __s_api_contain_passwd_control_oid(char **oids
)
2161 for (oid
= oids
; *oid
; oid
++) {
2162 if (strcmp(*oid
, LDAP_CONTROL_PWEXPIRED
) == 0 ||
2163 strcmp(*oid
, LDAP_CONTROL_PWEXPIRING
) == 0) {
2172 * Determine if the input OID list contains LDAP V3 password less
2173 * account management control OID, which is:
2174 * NS_LDAP_ACCOUNT_USABLE_CONTROL:1.3.6.1.4.1.42.2.27.9.5.8
2175 * If yes, return 1, if no, 0.
2178 __s_api_contain_account_usable_control_oid(char **oids
)
2185 for (oid
= oids
; *oid
; oid
++) {
2186 if (strcmp(*oid
, NS_LDAP_ACCOUNT_USABLE_CONTROL
) == 0) {
2195 * For some databases in name switch, the name and aliases are saved
2196 * as "cn". When the "cn" valuse are retrieved, there is no distinction
2197 * which is the name and which is(are) aliase(s).
2198 * This function is to parse RDN and find the value of the "cn" and
2199 * then find the matching value in "cn" attribute.
2200 * Also see RFC 2307 section 5.6.
2203 * entry: An LDAP entry
2204 * attrptr: A attribute which value appears in RDN
2205 * This should be "cn" for the name switch for now.
2206 * case_ignore: 0 Case sensitive comparison on the attribute value
2207 * 1 Case insensitive comparison
2210 * The value of an attrbute which is used as canonical name
2211 * This is read only and the caller should not try to free it.
2212 * If it's a NULL, it could be either an RDN parsing error
2213 * or RDN value does not match any existing "cn" values.
2215 * dn: cn=xx+ipserviceprotocol=udp,......
2220 * Although the name switch/ldap's rdn is in "cn=xx" or "cn=xx+..."
2221 * format, this function makes no such assumption. If the DN
2222 * is saved as "dn: yy=...+sn=my_canocical_name, ..", then it can still work.
2223 * The comments use "cn" as an example only.
2226 typedef int (*cmpfunc
)(const char *, const char *);
2229 __s_api_get_canonical_name(ns_ldap_entry_t
*entry
, ns_ldap_attr_t
*attrptr
,
2232 char *token
, *lasts
, *value
= NULL
;
2233 char **rdn
= NULL
, **attrs
= NULL
, **values
= NULL
;
2234 char *rdn_attr_value
= NULL
;
2237 if (entry
== NULL
|| attrptr
== NULL
)
2240 /* "values" is read-only */
2241 if ((values
= __ns_ldap_getAttr(entry
, "dn")) == NULL
||
2245 if ((rdn
= ldap_explode_dn(values
[0], 0)) == NULL
||
2249 if ((attrs
= ldap_explode_rdn(rdn
[0], 0)) == NULL
) {
2250 ldap_value_free(rdn
);
2253 /* Assume the rdn is normalized */
2254 for (i
= 0; attrs
[i
] != NULL
; i
++) {
2255 /* parse attribute name and value, get attribute name first */
2256 if ((token
= strtok_r(attrs
[i
], "=", &lasts
)) == NULL
) {
2259 if (strcasecmp(token
, attrptr
->attrname
) == 0) {
2261 rdn_attr_value
= lasts
;
2265 if (rdn_attr_value
) {
2271 * After parsing RDN and find the matching attribute in RDN,
2272 * match rdn value with values in "cn".
2274 for (i
= 0; i
< attrptr
->value_count
; i
++) {
2275 if (attrptr
->attrvalue
[i
] &&
2276 (*cmp
)(rdn_attr_value
,
2277 attrptr
->attrvalue
[i
]) == 0) {
2278 /* RDN "cn" value matches the "cn" value */
2279 value
= attrptr
->attrvalue
[i
];
2285 ldap_value_free(rdn
);
2286 ldap_value_free(attrs
);
2292 * This function requests a server to be removed from
2293 * the cache manager maintained server list. This is
2294 * done via the door functionality.
2295 * Returns 0 if OK, else a negative value.
2299 __s_api_removeServer(const char *server
)
2303 char s_b
[DOORBUFFERSIZE
];
2306 ns_server_info_t r
, *ret
= &r
;
2313 ns_ldap_error_t
*error
= NULL
;
2318 ireq
= NS_CACHE_NORESP
;
2320 if (__s_api_isStandalone()) {
2322 * Remove 'server' from the standalone server list.
2323 * __s_api_findRootDSE() is the standalone version
2324 * of getldap_get_serverInfo() used in ldap_cachemgr.
2325 * Request NS_CACHE_NORESP indicates 'server' should
2328 if (__s_api_findRootDSE(ireq
,
2332 &error
) != NS_LDAP_SUCCESS
) {
2334 "libsldap (\"standalone\" mode): "
2335 " Unable to remove %s - %s",
2337 error
!= NULL
&& error
->message
!= NULL
?
2338 error
->message
: " no error info");
2339 if (error
!= NULL
) {
2340 (void) __ns_ldap_freeError(&error
);
2343 return (NS_CACHE_NOSERVER
);
2349 (void) memset(ret
, 0, sizeof (ns_server_info_t
));
2350 (void) memset(space
.s_b
, 0, DOORBUFFERSIZE
);
2352 adata
= (sizeof (ldap_call_t
) + strlen(ireq
) +
2353 strlen(NS_CACHE_ADDR_IP
) + 1);
2354 adata
+= strlen(DOORLINESEP
) + 1;
2355 adata
+= strlen(server
) + 1;
2357 ndata
= sizeof (space
);
2358 space
.s_d
.ldap_call
.ldap_callnumber
= GETLDAPSERVER
;
2359 len
= sizeof (space
) - sizeof (space
.s_d
.ldap_call
.ldap_callnumber
);
2360 if (strlcpy(space
.s_d
.ldap_call
.ldap_u
.domainname
, ireq
, len
) >= len
)
2362 if (strlcat(space
.s_d
.ldap_call
.ldap_u
.domainname
,
2363 NS_CACHE_ADDR_IP
, len
) >= len
)
2365 if (strlcat(space
.s_d
.ldap_call
.ldap_u
.domainname
, DOORLINESEP
, len
) >=
2368 if (strlcat(space
.s_d
.ldap_call
.ldap_u
.domainname
, server
, len
) >= len
)
2372 /* try to remove the server via the door interface */
2373 rc
= __ns_ldap_trydoorcall(&sptr
, &ndata
, &adata
);
2375 /* clean up the door call */
2376 if (sptr
!= &space
.s_d
) {
2377 (void) munmap((char *)sptr
, ndata
);
2384 __s_api_free_server_info(ns_server_info_t
*sinfo
) {
2385 if (sinfo
->server
) {
2386 free(sinfo
->server
);
2387 sinfo
->server
= NULL
;
2389 if (sinfo
->serverFQDN
) {
2390 free(sinfo
->serverFQDN
);
2391 sinfo
->serverFQDN
= NULL
;
2393 __s_api_free2dArray(sinfo
->saslMechanisms
);
2394 sinfo
->saslMechanisms
= NULL
;
2395 __s_api_free2dArray(sinfo
->controls
);
2396 sinfo
->controls
= NULL
;
2400 * Create an ns_ldap_error structure, set status to 'rc',
2401 * and copy in the error message 'msg'.
2404 __s_api_make_error(int rc
, char *msg
) {
2405 ns_ldap_error_t
*ep
;
2407 ep
= (ns_ldap_error_t
*)calloc(1, sizeof (*ep
));
2413 ep
->message
= strdup(msg
); /* OK if ep->message is NULL */
2419 * Make a copy of the input ns_ldap_error.
2422 __s_api_copy_error(ns_ldap_error_t
*errorp
) {
2423 ns_ldap_error_t
*ep
;
2429 ep
= (ns_ldap_error_t
*)malloc(sizeof (*ep
));
2432 if (ep
->message
!= NULL
) {
2433 msg
= strdup(ep
->message
);