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