xref: /netbsd-src/external/bsd/openldap/dist/libraries/libldap/open.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /*	$NetBSD: open.c,v 1.1.1.2 2010/03/08 02:14:20 lukem Exp $	*/
2 
3 /* OpenLDAP: pkg/ldap/libraries/libldap/open.c,v 1.110.2.12 2009/11/18 22:19:02 quanah Exp */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 1998-2009 The OpenLDAP Foundation.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
18  * All rights reserved.
19  */
20 
21 #include "portable.h"
22 
23 #include <stdio.h>
24 #ifdef HAVE_LIMITS_H
25 #include <limits.h>
26 #endif
27 
28 #include <ac/stdlib.h>
29 
30 #include <ac/param.h>
31 #include <ac/socket.h>
32 #include <ac/string.h>
33 #include <ac/time.h>
34 
35 #include <ac/unistd.h>
36 
37 #include "ldap-int.h"
38 #include "ldap_log.h"
39 
40 /* Caller should hold the req_mutex if simultaneous accesses are possible */
41 int ldap_open_defconn( LDAP *ld )
42 {
43 	ld->ld_defconn = ldap_new_connection( ld,
44 		&ld->ld_options.ldo_defludp, 1, 1, NULL );
45 
46 	if( ld->ld_defconn == NULL ) {
47 		ld->ld_errno = LDAP_SERVER_DOWN;
48 		return -1;
49 	}
50 
51 	++ld->ld_defconn->lconn_refcnt;	/* so it never gets closed/freed */
52 	return 0;
53 }
54 
55 /*
56  * ldap_open - initialize and connect to an ldap server.  A magic cookie to
57  * be used for future communication is returned on success, NULL on failure.
58  * "host" may be a space-separated list of hosts or IP addresses
59  *
60  * Example:
61  *	LDAP	*ld;
62  *	ld = ldap_open( hostname, port );
63  */
64 
65 LDAP *
66 ldap_open( LDAP_CONST char *host, int port )
67 {
68 	int rc;
69 	LDAP		*ld;
70 
71 	Debug( LDAP_DEBUG_TRACE, "ldap_open(%s, %d)\n",
72 		host, port, 0 );
73 
74 	ld = ldap_init( host, port );
75 	if ( ld == NULL ) {
76 		return( NULL );
77 	}
78 
79 	rc = ldap_open_defconn( ld );
80 
81 	if( rc < 0 ) {
82 		ldap_ld_free( ld, 0, NULL, NULL );
83 		ld = NULL;
84 	}
85 
86 	Debug( LDAP_DEBUG_TRACE, "ldap_open: %s\n",
87 		ld != NULL ? "succeeded" : "failed", 0, 0 );
88 
89 	return ld;
90 }
91 
92 
93 
94 int
95 ldap_create( LDAP **ldp )
96 {
97 	LDAP			*ld;
98 	struct ldapoptions	*gopts;
99 
100 	*ldp = NULL;
101 	/* Get pointer to global option structure */
102 	if ( (gopts = LDAP_INT_GLOBAL_OPT()) == NULL) {
103 		return LDAP_NO_MEMORY;
104 	}
105 
106 	/* Initialize the global options, if not already done. */
107 	if( gopts->ldo_valid != LDAP_INITIALIZED ) {
108 		ldap_int_initialize(gopts, NULL);
109 		if ( gopts->ldo_valid != LDAP_INITIALIZED )
110 			return LDAP_LOCAL_ERROR;
111 	}
112 
113 	Debug( LDAP_DEBUG_TRACE, "ldap_create\n", 0, 0, 0 );
114 
115 	if ( (ld = (LDAP *) LDAP_CALLOC( 1, sizeof(LDAP) )) == NULL ) {
116 		return( LDAP_NO_MEMORY );
117 	}
118 
119 	/* copy the global options */
120 	AC_MEMCPY(&ld->ld_options, gopts, sizeof(ld->ld_options));
121 
122 	ld->ld_valid = LDAP_VALID_SESSION;
123 
124 	/* but not pointers to malloc'ed items */
125 	ld->ld_options.ldo_sctrls = NULL;
126 	ld->ld_options.ldo_cctrls = NULL;
127 	ld->ld_options.ldo_defludp = NULL;
128 	ld->ld_options.ldo_conn_cbs = NULL;
129 
130 #ifdef HAVE_CYRUS_SASL
131 	ld->ld_options.ldo_def_sasl_mech = gopts->ldo_def_sasl_mech
132 		? LDAP_STRDUP( gopts->ldo_def_sasl_mech ) : NULL;
133 	ld->ld_options.ldo_def_sasl_realm = gopts->ldo_def_sasl_realm
134 		? LDAP_STRDUP( gopts->ldo_def_sasl_realm ) : NULL;
135 	ld->ld_options.ldo_def_sasl_authcid = gopts->ldo_def_sasl_authcid
136 		? LDAP_STRDUP( gopts->ldo_def_sasl_authcid ) : NULL;
137 	ld->ld_options.ldo_def_sasl_authzid = gopts->ldo_def_sasl_authzid
138 		? LDAP_STRDUP( gopts->ldo_def_sasl_authzid ) : NULL;
139 #endif
140 
141 #ifdef HAVE_TLS
142 	/* We explicitly inherit the SSL_CTX, don't need the names/paths. Leave
143 	 * them empty to allow new SSL_CTX's to be created from scratch.
144 	 */
145 	memset( &ld->ld_options.ldo_tls_info, 0,
146 		sizeof( ld->ld_options.ldo_tls_info ));
147 	ld->ld_options.ldo_tls_ctx = NULL;
148 #endif
149 
150 	if ( gopts->ldo_defludp ) {
151 		ld->ld_options.ldo_defludp = ldap_url_duplist(gopts->ldo_defludp);
152 
153 		if ( ld->ld_options.ldo_defludp == NULL ) goto nomem;
154 	}
155 
156 	if (( ld->ld_selectinfo = ldap_new_select_info()) == NULL ) goto nomem;
157 
158 	ld->ld_lberoptions = LBER_USE_DER;
159 
160 	ld->ld_sb = ber_sockbuf_alloc( );
161 	if ( ld->ld_sb == NULL ) goto nomem;
162 
163 #ifdef LDAP_R_COMPILE
164 	ldap_pvt_thread_mutex_init( &ld->ld_req_mutex );
165 	ldap_pvt_thread_mutex_init( &ld->ld_res_mutex );
166 	ldap_pvt_thread_mutex_init( &ld->ld_conn_mutex );
167 #endif
168 	*ldp = ld;
169 	return LDAP_SUCCESS;
170 
171 nomem:
172 	ldap_free_select_info( ld->ld_selectinfo );
173 	ldap_free_urllist( ld->ld_options.ldo_defludp );
174 #ifdef HAVE_CYRUS_SASL
175 	LDAP_FREE( ld->ld_options.ldo_def_sasl_authzid );
176 	LDAP_FREE( ld->ld_options.ldo_def_sasl_authcid );
177 	LDAP_FREE( ld->ld_options.ldo_def_sasl_realm );
178 	LDAP_FREE( ld->ld_options.ldo_def_sasl_mech );
179 #endif
180 	LDAP_FREE( (char *)ld );
181 	return LDAP_NO_MEMORY;
182 }
183 
184 /*
185  * ldap_init - initialize the LDAP library.  A magic cookie to be used for
186  * future communication is returned on success, NULL on failure.
187  * "host" may be a space-separated list of hosts or IP addresses
188  *
189  * Example:
190  *	LDAP	*ld;
191  *	ld = ldap_init( host, port );
192  */
193 LDAP *
194 ldap_init( LDAP_CONST char *defhost, int defport )
195 {
196 	LDAP *ld;
197 	int rc;
198 
199 	rc = ldap_create(&ld);
200 	if ( rc != LDAP_SUCCESS )
201 		return NULL;
202 
203 	if (defport != 0)
204 		ld->ld_options.ldo_defport = defport;
205 
206 	if (defhost != NULL) {
207 		rc = ldap_set_option(ld, LDAP_OPT_HOST_NAME, defhost);
208 		if ( rc != LDAP_SUCCESS ) {
209 			ldap_ld_free(ld, 1, NULL, NULL);
210 			return NULL;
211 		}
212 	}
213 
214 	return( ld );
215 }
216 
217 
218 int
219 ldap_initialize( LDAP **ldp, LDAP_CONST char *url )
220 {
221 	int rc;
222 	LDAP *ld;
223 
224 	*ldp = NULL;
225 	rc = ldap_create(&ld);
226 	if ( rc != LDAP_SUCCESS )
227 		return rc;
228 
229 	if (url != NULL) {
230 		rc = ldap_set_option(ld, LDAP_OPT_URI, url);
231 		if ( rc != LDAP_SUCCESS ) {
232 			ldap_ld_free(ld, 1, NULL, NULL);
233 			return rc;
234 		}
235 #ifdef LDAP_CONNECTIONLESS
236 		if (ldap_is_ldapc_url(url))
237 			LDAP_IS_UDP(ld) = 1;
238 #endif
239 	}
240 
241 	*ldp = ld;
242 	return LDAP_SUCCESS;
243 }
244 
245 int
246 ldap_init_fd(
247 	ber_socket_t fd,
248 	int proto,
249 	LDAP_CONST char *url,
250 	LDAP **ldp
251 )
252 {
253 	int rc;
254 	LDAP *ld;
255 	LDAPConn *conn;
256 
257 	*ldp = NULL;
258 	rc = ldap_create( &ld );
259 	if( rc != LDAP_SUCCESS )
260 		return( rc );
261 
262 	if (url != NULL) {
263 		rc = ldap_set_option(ld, LDAP_OPT_URI, url);
264 		if ( rc != LDAP_SUCCESS ) {
265 			ldap_ld_free(ld, 1, NULL, NULL);
266 			return rc;
267 		}
268 	}
269 
270 	/* Attach the passed socket as the LDAP's connection */
271 	conn = ldap_new_connection( ld, NULL, 1, 0, NULL);
272 	if( conn == NULL ) {
273 		ldap_unbind_ext( ld, NULL, NULL );
274 		return( LDAP_NO_MEMORY );
275 	}
276 	if( url )
277 		conn->lconn_server = ldap_url_dup( ld->ld_options.ldo_defludp );
278 	ber_sockbuf_ctrl( conn->lconn_sb, LBER_SB_OPT_SET_FD, &fd );
279 	ld->ld_defconn = conn;
280 	++ld->ld_defconn->lconn_refcnt;	/* so it never gets closed/freed */
281 
282 	switch( proto ) {
283 	case LDAP_PROTO_TCP:
284 #ifdef LDAP_DEBUG
285 		ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
286 			LBER_SBIOD_LEVEL_PROVIDER, (void *)"tcp_" );
287 #endif
288 		ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_tcp,
289 			LBER_SBIOD_LEVEL_PROVIDER, NULL );
290 		break;
291 
292 #ifdef LDAP_CONNECTIONLESS
293 	case LDAP_PROTO_UDP:
294 #ifdef LDAP_DEBUG
295 		ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
296 			LBER_SBIOD_LEVEL_PROVIDER, (void *)"udp_" );
297 #endif
298 		ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_udp,
299 			LBER_SBIOD_LEVEL_PROVIDER, NULL );
300 		ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_readahead,
301 			LBER_SBIOD_LEVEL_PROVIDER, NULL );
302 		break;
303 #endif /* LDAP_CONNECTIONLESS */
304 
305 	case LDAP_PROTO_IPC:
306 #ifdef LDAP_DEBUG
307 		ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
308 			LBER_SBIOD_LEVEL_PROVIDER, (void *)"ipc_" );
309 #endif
310 		ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_fd,
311 			LBER_SBIOD_LEVEL_PROVIDER, NULL );
312 		break;
313 
314 	case LDAP_PROTO_EXT:
315 		/* caller must supply sockbuf handlers */
316 		break;
317 
318 	default:
319 		ldap_unbind_ext( ld, NULL, NULL );
320 		return LDAP_PARAM_ERROR;
321 	}
322 
323 #ifdef LDAP_DEBUG
324 	ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
325 		INT_MAX, (void *)"ldap_" );
326 #endif
327 
328 	/* Add the connection to the *LDAP's select pool */
329 	ldap_mark_select_read( ld, conn->lconn_sb );
330 	ldap_mark_select_write( ld, conn->lconn_sb );
331 
332 	*ldp = ld;
333 	return LDAP_SUCCESS;
334 }
335 
336 int
337 ldap_int_open_connection(
338 	LDAP *ld,
339 	LDAPConn *conn,
340 	LDAPURLDesc *srv,
341 	int async )
342 {
343 	int rc = -1;
344 	int proto;
345 
346 	Debug( LDAP_DEBUG_TRACE, "ldap_int_open_connection\n", 0, 0, 0 );
347 
348 	switch ( proto = ldap_pvt_url_scheme2proto( srv->lud_scheme ) ) {
349 		case LDAP_PROTO_TCP:
350 			rc = ldap_connect_to_host( ld, conn->lconn_sb,
351 				proto, srv, async );
352 
353 			if ( rc == -1 ) return rc;
354 #ifdef LDAP_DEBUG
355 			ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
356 				LBER_SBIOD_LEVEL_PROVIDER, (void *)"tcp_" );
357 #endif
358 			ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_tcp,
359 				LBER_SBIOD_LEVEL_PROVIDER, NULL );
360 
361 			break;
362 
363 #ifdef LDAP_CONNECTIONLESS
364 		case LDAP_PROTO_UDP:
365 			LDAP_IS_UDP(ld) = 1;
366 			rc = ldap_connect_to_host( ld, conn->lconn_sb,
367 				proto, srv, async );
368 
369 			if ( rc == -1 ) return rc;
370 #ifdef LDAP_DEBUG
371 			ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
372 				LBER_SBIOD_LEVEL_PROVIDER, (void *)"udp_" );
373 #endif
374 			ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_udp,
375 				LBER_SBIOD_LEVEL_PROVIDER, NULL );
376 
377 			ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_readahead,
378 				LBER_SBIOD_LEVEL_PROVIDER, NULL );
379 
380 			break;
381 #endif
382 		case LDAP_PROTO_IPC:
383 #ifdef LDAP_PF_LOCAL
384 			/* only IPC mechanism supported is PF_LOCAL (PF_UNIX) */
385 			rc = ldap_connect_to_path( ld, conn->lconn_sb,
386 				srv, async );
387 			if ( rc == -1 ) return rc;
388 #ifdef LDAP_DEBUG
389 			ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
390 				LBER_SBIOD_LEVEL_PROVIDER, (void *)"ipc_" );
391 #endif
392 			ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_fd,
393 				LBER_SBIOD_LEVEL_PROVIDER, NULL );
394 
395 			break;
396 #endif /* LDAP_PF_LOCAL */
397 		default:
398 			return -1;
399 			break;
400 	}
401 
402 	conn->lconn_created = time( NULL );
403 
404 #ifdef LDAP_DEBUG
405 	ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
406 		INT_MAX, (void *)"ldap_" );
407 #endif
408 
409 #ifdef LDAP_CONNECTIONLESS
410 	if( proto == LDAP_PROTO_UDP ) return 0;
411 #endif
412 
413 #ifdef HAVE_TLS
414 	if (ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD ||
415 		strcmp( srv->lud_scheme, "ldaps" ) == 0 )
416 	{
417 		++conn->lconn_refcnt;	/* avoid premature free */
418 
419 		rc = ldap_int_tls_start( ld, conn, srv );
420 
421 		--conn->lconn_refcnt;
422 
423 		if (rc != LDAP_SUCCESS) {
424 			return -1;
425 		}
426 	}
427 #endif
428 
429 	return( 0 );
430 }
431 
432 
433 int
434 ldap_open_internal_connection( LDAP **ldp, ber_socket_t *fdp )
435 {
436 	int rc;
437 	LDAPConn *c;
438 	LDAPRequest *lr;
439 
440 	rc = ldap_create( ldp );
441 	if( rc != LDAP_SUCCESS ) {
442 		*ldp = NULL;
443 		return( rc );
444 	}
445 
446 	/* Make it appear that a search request, msgid 0, was sent */
447 	lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ));
448 	if( lr == NULL ) {
449 		ldap_unbind_ext( *ldp, NULL, NULL );
450 		*ldp = NULL;
451 		return( LDAP_NO_MEMORY );
452 	}
453 	memset(lr, 0, sizeof( LDAPRequest ));
454 	lr->lr_msgid = 0;
455 	lr->lr_status = LDAP_REQST_INPROGRESS;
456 	lr->lr_res_errno = LDAP_SUCCESS;
457 	/* no mutex lock needed, we just created this ld here */
458 	(*ldp)->ld_requests = lr;
459 
460 	/* Attach the passed socket as the *LDAP's connection */
461 	c = ldap_new_connection( *ldp, NULL, 1, 0, NULL);
462 	if( c == NULL ) {
463 		ldap_unbind_ext( *ldp, NULL, NULL );
464 		*ldp = NULL;
465 		return( LDAP_NO_MEMORY );
466 	}
467 	ber_sockbuf_ctrl( c->lconn_sb, LBER_SB_OPT_SET_FD, fdp );
468 #ifdef LDAP_DEBUG
469 	ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_debug,
470 		LBER_SBIOD_LEVEL_PROVIDER, (void *)"int_" );
471 #endif
472 	ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_tcp,
473 	  LBER_SBIOD_LEVEL_PROVIDER, NULL );
474 	(*ldp)->ld_defconn = c;
475 
476 	/* Add the connection to the *LDAP's select pool */
477 	ldap_mark_select_read( *ldp, c->lconn_sb );
478 	ldap_mark_select_write( *ldp, c->lconn_sb );
479 
480 	/* Make this connection an LDAP V3 protocol connection */
481 	rc = LDAP_VERSION3;
482 	ldap_set_option( *ldp, LDAP_OPT_PROTOCOL_VERSION, &rc );
483 
484 	return( LDAP_SUCCESS );
485 }
486