2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
8 * The contents of this file are subject to the Netscape Public
9 * License Version 1.1 (the "License"); you may not use this file
10 * except in compliance with the License. You may obtain a copy of
11 * the License at http://www.mozilla.org/NPL/
13 * Software distributed under the License is distributed on an "AS
14 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
15 * implied. See the License for the specific language governing
16 * rights and limitations under the License.
18 * The Original Code is Mozilla Communicator client code, released
21 * The Initial Developer of the Original Code is Netscape
22 * Communications Corporation. Portions created by Netscape are
23 * Copyright (C) 1998-1999 Netscape Communications Corporation. All
30 * DNS callback functions for libldap that use the NSPR (Netscape
31 * Portable Runtime) thread API.
36 #include "solaris-int.h"
41 #include <nss_dbdefs.h>
42 #include <netinet/in.h>
43 static char *host_service
= NULL
;
44 static DEFINE_NSS_DB_ROOT(db_root_hosts
);
47 #include "ldappr-int.h"
49 static LDAPHostEnt
*prldap_gethostbyname( const char *name
,
50 LDAPHostEnt
*result
, char *buffer
, int buflen
, int *statusp
,
52 static LDAPHostEnt
*prldap_gethostbyaddr( const char *addr
, int length
,
53 int type
, LDAPHostEnt
*result
, char *buffer
, int buflen
,
54 int *statusp
, void *extradata
);
55 static int prldap_getpeername( LDAP
*ld
, struct sockaddr
*addr
,
56 char *buffer
, int buflen
);
57 static LDAPHostEnt
*prldap_convert_hostent( LDAPHostEnt
*ldhp
,
62 prldap_gethostbyname1(const char *name
, LDAPHostEnt
*result
,
63 char *buffer
, int buflen
, int *statusp
, void *extradata
);
65 str2hostent(const char *instr
, int lenstr
, void *ent
, char *buffer
,
67 #endif /* _SOLARIS_SDK */
71 * Install NSPR DNS functions into ld (if ld is NULL, they are installed
72 * as the default functions for new LDAP * handles).
74 * Returns 0 if all goes well and -1 if not.
77 prldap_install_dns_functions( LDAP
*ld
)
79 struct ldap_dns_fns dnsfns
;
81 memset( &dnsfns
, '\0', sizeof(struct ldap_dns_fns
) );
82 dnsfns
.lddnsfn_bufsize
= PR_NETDB_BUF_SIZE
;
83 dnsfns
.lddnsfn_gethostbyname
= prldap_gethostbyname
;
84 dnsfns
.lddnsfn_gethostbyaddr
= prldap_gethostbyaddr
;
85 dnsfns
.lddnsfn_getpeername
= prldap_getpeername
;
86 if ( ldap_set_option( ld
, LDAP_OPT_DNS_FN_PTRS
, (void *)&dnsfns
) != 0 ) {
95 prldap_gethostbyname( const char *name
, LDAPHostEnt
*result
,
96 char *buffer
, int buflen
, int *statusp
, void *extradata
)
100 if( !statusp
|| ( *statusp
= (int)PR_GetIPNodeByName( name
,
101 PRLDAP_DEFAULT_ADDRESS_FAMILY
, PR_AI_DEFAULT
,
102 buffer
, buflen
, &prhent
)) == PR_FAILURE
) {
106 return( prldap_convert_hostent( result
, &prhent
));
111 prldap_gethostbyaddr( const char *addr
, int length
, int type
,
112 LDAPHostEnt
*result
, char *buffer
, int buflen
, int *statusp
,
118 if ( PR_SetNetAddr(PR_IpAddrNull
, PRLDAP_DEFAULT_ADDRESS_FAMILY
,
119 0, &iaddr
) == PR_FAILURE
120 || PR_StringToNetAddr( addr
, &iaddr
) == PR_FAILURE
) {
124 if( !statusp
|| (*statusp
= PR_GetHostByAddr(&iaddr
, buffer
,
125 buflen
, &prhent
)) == PR_FAILURE
) {
128 return( prldap_convert_hostent( result
, &prhent
));
132 prldap_getpeername( LDAP
*ld
, struct sockaddr
*addr
, char *buffer
, int buflen
)
134 PRLDAPIOSocketArg
*sa
;
140 ret
= prldap_socket_arg_from_ld( ld
, &sa
);
141 if (ret
!= LDAP_SUCCESS
) {
144 ret
= PR_GetPeerName(sa
->prsock_prfd
, &iaddr
);
145 if( ret
== PR_FAILURE
) {
148 *addr
= *((struct sockaddr
*)&iaddr
.raw
);
149 ret
= PR_NetAddrToString(&iaddr
, buffer
, buflen
);
150 if( ret
== PR_FAILURE
) {
160 * Function: prldap_convert_hostent()
161 * Description: copy the fields of a PRHostEnt struct to an LDAPHostEnt
162 * Returns: the LDAPHostEnt pointer passed in.
165 prldap_convert_hostent( LDAPHostEnt
*ldhp
, PRHostEnt
*prhp
)
167 ldhp
->ldaphe_name
= prhp
->h_name
;
168 ldhp
->ldaphe_aliases
= prhp
->h_aliases
;
169 ldhp
->ldaphe_addrtype
= prhp
->h_addrtype
;
170 ldhp
->ldaphe_length
= prhp
->h_length
;
171 ldhp
->ldaphe_addr_list
= prhp
->h_addr_list
;
177 * prldap_x_install_dns_skipdb attempts to prevent recursion in resolving
178 * the hostname to an IP address when a host name is given to LDAP user.
180 * For example, libsldap cannot use LDAP to resolve the host name to an
181 * address because of recursion. The caller is instructing libldap to skip
182 * the specified name service when resolving addresses for the specified
186 * This only supports ipv4 addresses currently.
188 * Since host_service applies to all connections, calling
189 * prldap_x_install_dns_skipdb with name services other than
190 * ldap or what uses ldap (for example nis+ might use ldap) to
191 * skip will lead to unpredictable results.
194 * 0 if success and data base found
199 prldap_x_install_dns_skipdb(LDAP
*ld
, const char *skip
)
201 enum __nsw_parse_err pserr
;
202 struct __nsw_switchconfig
*conf
;
203 struct __nsw_lookup
*lkp
;
204 struct ldap_dns_fns dns_fns
;
205 char *name_list
= NULL
;
209 boolean_t got_skip
= B_FALSE
;
212 * db_root_hosts.lock mutex is used to ensure that the name list
213 * is not in use by the name service switch while we are updating
217 (void) mutex_lock(&db_root_hosts
.lock
);
218 conf
= __nsw_getconfig("hosts", &pserr
);
220 (void) mutex_unlock(&db_root_hosts
.lock
);
224 /* check for skip and count other backends */
225 for (lkp
= conf
->lookups
; lkp
!= NULL
; lkp
= lkp
->next
) {
226 name
= lkp
->service_name
;
227 if (strcmp(name
, skip
) == 0) {
231 if (name_list
== NULL
)
232 name_list
= strdup(name
);
234 len
= strlen(name_list
);
235 tmp
= realloc(name_list
, len
+ strlen(name
) + 2);
241 name_list
[len
++] = ' ';
242 (void) strcpy(name_list
+len
, name
);
245 if (name_list
== NULL
) { /* alloc error */
246 (void) mutex_unlock(&db_root_hosts
.lock
);
247 __nsw_freeconfig(conf
);
251 __nsw_freeconfig(conf
);
254 * Since skip name service not used for hosts, we do not need
255 * to install our private address resolution function
257 (void) mutex_unlock(&db_root_hosts
.lock
);
262 host_service
= name_list
;
263 (void) mutex_unlock(&db_root_hosts
.lock
);
265 if (ldap_get_option(ld
, LDAP_OPT_DNS_FN_PTRS
, &dns_fns
) != 0)
267 dns_fns
.lddnsfn_bufsize
= PR_NETDB_BUF_SIZE
;
268 dns_fns
.lddnsfn_gethostbyname
= prldap_gethostbyname1
;
269 if (ldap_set_option(ld
, LDAP_OPT_DNS_FN_PTRS
, &dns_fns
) != 0)
275 * prldap_initf_hosts is passed to and called by nss_search() as a
283 prldap_initf_hosts(nss_db_params_t
*p
)
285 static char *no_service
= "";
287 p
->name
= NSS_DBNAM_HOSTS
;
288 p
->flags
|= NSS_USE_DEFAULT_CONFIG
;
289 p
->default_config
= host_service
== NULL
? no_service
: host_service
;
293 * called by prldap_gethostbyname1()
296 * prldap_switch_gethostbyname_r is called by prldap_gethostbyname1 as a
297 * substitute for gethostbyname_r(). A method which prevents recursion. see
298 * prldap_gethostbyname1() and prldap_x_install_dns_skipdb().
301 * PR_SUCCESS if success
302 * PR_FAILURE if failure
306 prldap_switch_gethostbyname_r(const char *name
,
307 struct hostent
*result
, char *buffer
, int buflen
,
312 struct hostent
*resp
;
315 * Log the information indicating that we are trying to
316 * resolve the LDAP server name.
318 syslog(LOG_INFO
, "libldap: Resolving server name \"%s\"", name
);
320 NSS_XbyY_INIT(&arg
, result
, buffer
, buflen
, str2hostent
);
325 res
= nss_search(&db_root_hosts
, prldap_initf_hosts
,
326 NSS_DBOP_HOSTS_BYNAME
, &arg
);
328 *h_errnop
= arg
.h_errno
;
329 resp
= (struct hostent
*)NSS_XbyY_FINI(&arg
);
331 return (resp
!= NULL
? PR_SUCCESS
: PR_FAILURE
);
335 * prldap_gethostbyname1 is used to be a substitute gethostbyname_r for
336 * libldap when it is unsafe to use the normal nameservice functions.
339 * pointer to LDAPHostEnt: if success contains the address
340 * NULL pointer: if failure
344 prldap_gethostbyname1(const char *name
, LDAPHostEnt
*result
,
345 char *buffer
, int buflen
, int *statusp
, void *extradata
)
350 memset(&prhent
, '\0', sizeof (prhent
));
351 if (!statusp
|| ( *statusp
= prldap_switch_gethostbyname_r(name
,
352 &prhent
, buffer
, buflen
, &h_errno
)) == PR_FAILURE
) {
354 * If we got here, it means that we are not able to
355 * resolve the LDAP server name and so warn the system
356 * adminstrator accordingly.
358 syslog(LOG_WARNING
, "libldap: server name \"%s\" could not "
359 "be resolved", name
);
363 return (prldap_convert_hostent(result
, &prhent
));
366 #endif /* _SOLARIS_SDK */