2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
6 #pragma ident "%Z%%M% %I% %E% SMI"
10 * The contents of this file are subject to the Netscape Public
11 * License Version 1.1 (the "License"); you may not use this file
12 * except in compliance with the License. You may obtain a copy of
13 * the License at http://www.mozilla.org/NPL/
15 * Software distributed under the License is distributed on an "AS
16 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
17 * implied. See the License for the specific language governing
18 * rights and limitations under the License.
20 * The Original Code is Mozilla Communicator client code, released
23 * The Initial Developer of the Original Code is Netscape
24 * Communications Corporation. Portions created by Netscape are
25 * Copyright (C) 1998-1999 Netscape Communications Corporation. All
32 * DNS callback functions for libldap that use the NSPR (Netscape
33 * Portable Runtime) thread API.
38 #include "solaris-int.h"
43 #include <nss_dbdefs.h>
44 #include <netinet/in.h>
45 static char *host_service
= NULL
;
46 static DEFINE_NSS_DB_ROOT(db_root_hosts
);
49 #include "ldappr-int.h"
51 static LDAPHostEnt
*prldap_gethostbyname( const char *name
,
52 LDAPHostEnt
*result
, char *buffer
, int buflen
, int *statusp
,
54 static LDAPHostEnt
*prldap_gethostbyaddr( const char *addr
, int length
,
55 int type
, LDAPHostEnt
*result
, char *buffer
, int buflen
,
56 int *statusp
, void *extradata
);
57 static int prldap_getpeername( LDAP
*ld
, struct sockaddr
*addr
,
58 char *buffer
, int buflen
);
59 static LDAPHostEnt
*prldap_convert_hostent( LDAPHostEnt
*ldhp
,
64 prldap_gethostbyname1(const char *name
, LDAPHostEnt
*result
,
65 char *buffer
, int buflen
, int *statusp
, void *extradata
);
67 str2hostent(const char *instr
, int lenstr
, void *ent
, char *buffer
,
69 #endif /* _SOLARIS_SDK */
73 * Install NSPR DNS functions into ld (if ld is NULL, they are installed
74 * as the default functions for new LDAP * handles).
76 * Returns 0 if all goes well and -1 if not.
79 prldap_install_dns_functions( LDAP
*ld
)
81 struct ldap_dns_fns dnsfns
;
83 memset( &dnsfns
, '\0', sizeof(struct ldap_dns_fns
) );
84 dnsfns
.lddnsfn_bufsize
= PR_NETDB_BUF_SIZE
;
85 dnsfns
.lddnsfn_gethostbyname
= prldap_gethostbyname
;
86 dnsfns
.lddnsfn_gethostbyaddr
= prldap_gethostbyaddr
;
87 dnsfns
.lddnsfn_getpeername
= prldap_getpeername
;
88 if ( ldap_set_option( ld
, LDAP_OPT_DNS_FN_PTRS
, (void *)&dnsfns
) != 0 ) {
97 prldap_gethostbyname( const char *name
, LDAPHostEnt
*result
,
98 char *buffer
, int buflen
, int *statusp
, void *extradata
)
102 if( !statusp
|| ( *statusp
= (int)PR_GetIPNodeByName( name
,
103 PRLDAP_DEFAULT_ADDRESS_FAMILY
, PR_AI_DEFAULT
,
104 buffer
, buflen
, &prhent
)) == PR_FAILURE
) {
108 return( prldap_convert_hostent( result
, &prhent
));
113 prldap_gethostbyaddr( const char *addr
, int length
, int type
,
114 LDAPHostEnt
*result
, char *buffer
, int buflen
, int *statusp
,
120 if ( PR_SetNetAddr(PR_IpAddrNull
, PRLDAP_DEFAULT_ADDRESS_FAMILY
,
121 0, &iaddr
) == PR_FAILURE
122 || PR_StringToNetAddr( addr
, &iaddr
) == PR_FAILURE
) {
126 if( !statusp
|| (*statusp
= PR_GetHostByAddr(&iaddr
, buffer
,
127 buflen
, &prhent
)) == PR_FAILURE
) {
130 return( prldap_convert_hostent( result
, &prhent
));
134 prldap_getpeername( LDAP
*ld
, struct sockaddr
*addr
, char *buffer
, int buflen
)
136 PRLDAPIOSocketArg
*sa
;
142 ret
= prldap_socket_arg_from_ld( ld
, &sa
);
143 if (ret
!= LDAP_SUCCESS
) {
146 ret
= PR_GetPeerName(sa
->prsock_prfd
, &iaddr
);
147 if( ret
== PR_FAILURE
) {
150 *addr
= *((struct sockaddr
*)&iaddr
.raw
);
151 ret
= PR_NetAddrToString(&iaddr
, buffer
, buflen
);
152 if( ret
== PR_FAILURE
) {
162 * Function: prldap_convert_hostent()
163 * Description: copy the fields of a PRHostEnt struct to an LDAPHostEnt
164 * Returns: the LDAPHostEnt pointer passed in.
167 prldap_convert_hostent( LDAPHostEnt
*ldhp
, PRHostEnt
*prhp
)
169 ldhp
->ldaphe_name
= prhp
->h_name
;
170 ldhp
->ldaphe_aliases
= prhp
->h_aliases
;
171 ldhp
->ldaphe_addrtype
= prhp
->h_addrtype
;
172 ldhp
->ldaphe_length
= prhp
->h_length
;
173 ldhp
->ldaphe_addr_list
= prhp
->h_addr_list
;
179 * prldap_x_install_dns_skipdb attempts to prevent recursion in resolving
180 * the hostname to an IP address when a host name is given to LDAP user.
182 * For example, libsldap cannot use LDAP to resolve the host name to an
183 * address because of recursion. The caller is instructing libldap to skip
184 * the specified name service when resolving addresses for the specified
188 * This only supports ipv4 addresses currently.
190 * Since host_service applies to all connections, calling
191 * prldap_x_install_dns_skipdb with name services other than
192 * ldap or what uses ldap (for example nis+ might use ldap) to
193 * skip will lead to unpredictable results.
196 * 0 if success and data base found
201 prldap_x_install_dns_skipdb(LDAP
*ld
, const char *skip
)
203 enum __nsw_parse_err pserr
;
204 struct __nsw_switchconfig
*conf
;
205 struct __nsw_lookup
*lkp
;
206 struct ldap_dns_fns dns_fns
;
207 char *name_list
= NULL
;
211 boolean_t got_skip
= B_FALSE
;
214 * db_root_hosts.lock mutex is used to ensure that the name list
215 * is not in use by the name service switch while we are updating
219 (void) mutex_lock(&db_root_hosts
.lock
);
220 conf
= __nsw_getconfig("hosts", &pserr
);
222 (void) mutex_unlock(&db_root_hosts
.lock
);
226 /* check for skip and count other backends */
227 for (lkp
= conf
->lookups
; lkp
!= NULL
; lkp
= lkp
->next
) {
228 name
= lkp
->service_name
;
229 if (strcmp(name
, skip
) == 0) {
233 if (name_list
== NULL
)
234 name_list
= strdup(name
);
236 len
= strlen(name_list
);
237 tmp
= realloc(name_list
, len
+ strlen(name
) + 2);
243 name_list
[len
++] = ' ';
244 (void) strcpy(name_list
+len
, name
);
247 if (name_list
== NULL
) { /* alloc error */
248 (void) mutex_unlock(&db_root_hosts
.lock
);
249 __nsw_freeconfig(conf
);
253 __nsw_freeconfig(conf
);
256 * Since skip name service not used for hosts, we do not need
257 * to install our private address resolution function
259 (void) mutex_unlock(&db_root_hosts
.lock
);
260 if (name_list
!= NULL
)
264 if (host_service
!= NULL
)
266 host_service
= name_list
;
267 (void) mutex_unlock(&db_root_hosts
.lock
);
269 if (ldap_get_option(ld
, LDAP_OPT_DNS_FN_PTRS
, &dns_fns
) != 0)
271 dns_fns
.lddnsfn_bufsize
= PR_NETDB_BUF_SIZE
;
272 dns_fns
.lddnsfn_gethostbyname
= prldap_gethostbyname1
;
273 if (ldap_set_option(ld
, LDAP_OPT_DNS_FN_PTRS
, &dns_fns
) != 0)
279 * prldap_initf_hosts is passed to and called by nss_search() as a
287 prldap_initf_hosts(nss_db_params_t
*p
)
289 static char *no_service
= "";
291 p
->name
= NSS_DBNAM_HOSTS
;
292 p
->flags
|= NSS_USE_DEFAULT_CONFIG
;
293 p
->default_config
= host_service
== NULL
? no_service
: host_service
;
297 * called by prldap_gethostbyname1()
300 * prldap_switch_gethostbyname_r is called by prldap_gethostbyname1 as a
301 * substitute for gethostbyname_r(). A method which prevents recursion. see
302 * prldap_gethostbyname1() and prldap_x_install_dns_skipdb().
305 * PR_SUCCESS if success
306 * PR_FAILURE if failure
310 prldap_switch_gethostbyname_r(const char *name
,
311 struct hostent
*result
, char *buffer
, int buflen
,
316 struct hostent
*resp
;
319 * Log the information indicating that we are trying to
320 * resolve the LDAP server name.
322 syslog(LOG_INFO
, "libldap: Resolving server name \"%s\"", name
);
324 NSS_XbyY_INIT(&arg
, result
, buffer
, buflen
, str2hostent
);
329 res
= nss_search(&db_root_hosts
, prldap_initf_hosts
,
330 NSS_DBOP_HOSTS_BYNAME
, &arg
);
332 *h_errnop
= arg
.h_errno
;
333 resp
= (struct hostent
*)NSS_XbyY_FINI(&arg
);
335 return (resp
!= NULL
? PR_SUCCESS
: PR_FAILURE
);
339 * prldap_gethostbyname1 is used to be a substitute gethostbyname_r for
340 * libldap when it is unsafe to use the normal nameservice functions.
343 * pointer to LDAPHostEnt: if success contains the address
344 * NULL pointer: if failure
348 prldap_gethostbyname1(const char *name
, LDAPHostEnt
*result
,
349 char *buffer
, int buflen
, int *statusp
, void *extradata
)
354 memset(&prhent
, '\0', sizeof (prhent
));
355 if (!statusp
|| ( *statusp
= prldap_switch_gethostbyname_r(name
,
356 &prhent
, buffer
, buflen
, &h_errno
)) == PR_FAILURE
) {
358 * If we got here, it means that we are not able to
359 * resolve the LDAP server name and so warn the system
360 * adminstrator accordingly.
362 syslog(LOG_WARNING
, "libldap: server name \"%s\" could not "
363 "be resolved", name
);
367 return (prldap_convert_hostent(result
, &prhent
));
370 #endif /* _SOLARIS_SDK */