open.c 11.7 KB
Newer Older
1
/* $OpenLDAP$ */
2
3
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 *
Kurt Zeilenga's avatar
Kurt Zeilenga committed
4
 * Copyright 1998-2008 The OpenLDAP Foundation.
5
 * All rights reserved.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
6
 *
7
8
9
10
11
12
13
14
15
16
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in the file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
 */
/* Portions Copyright (c) 1995 Regents of the University of Michigan.
 * All rights reserved.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
17
18
 */

Kurt Zeilenga's avatar
Kurt Zeilenga committed
19
20
#include "portable.h"

Kurt Zeilenga's avatar
Kurt Zeilenga committed
21
#include <stdio.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
22
#ifdef HAVE_LIMITS_H
Kurt Zeilenga's avatar
Kurt Zeilenga committed
23
#include <limits.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
24
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
25
26

#include <ac/stdlib.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
27

28
#include <ac/param.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
29
30
31
#include <ac/socket.h>
#include <ac/string.h>
#include <ac/time.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
32

33
#include <ac/unistd.h>
34

Kurt Zeilenga's avatar
Kurt Zeilenga committed
35
#include "ldap-int.h"
Julius Enarusai's avatar
   
Julius Enarusai committed
36
#include "ldap_log.h"
Kurt Zeilenga's avatar
Kurt Zeilenga committed
37

Howard Chu's avatar
Howard Chu committed
38
/* Caller should hold the req_mutex if simultaneous accesses are possible */
39
40
int ldap_open_defconn( LDAP *ld )
{
Howard Chu's avatar
Howard Chu committed
41
42
	ld->ld_defconn = ldap_new_connection( ld,
		&ld->ld_options.ldo_defludp, 1, 1, NULL );
Howard Chu's avatar
Howard Chu committed
43

Howard Chu's avatar
Howard Chu committed
44
45
46
	if( ld->ld_defconn == NULL ) {
		ld->ld_errno = LDAP_SERVER_DOWN;
		return -1;
Howard Chu's avatar
Howard Chu committed
47
	}
Howard Chu's avatar
Howard Chu committed
48
49
50

	++ld->ld_defconn->lconn_refcnt;	/* so it never gets closed/freed */
	return 0;
51
}
52

Kurt Zeilenga's avatar
Kurt Zeilenga committed
53
54
55
56
57
58
59
60
61
62
63
/*
 * ldap_open - initialize and connect to an ldap server.  A magic cookie to
 * be used for future communication is returned on success, NULL on failure.
 * "host" may be a space-separated list of hosts or IP addresses
 *
 * Example:
 *	LDAP	*ld;
 *	ld = ldap_open( hostname, port );
 */

LDAP *
Kurt Zeilenga's avatar
Kurt Zeilenga committed
64
ldap_open( LDAP_CONST char *host, int port )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
65
{
66
	int rc;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
67
68
	LDAP		*ld;

69
70
	Debug( LDAP_DEBUG_TRACE, "ldap_open(%s, %d)\n",
		host, port, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
71

72
73
	ld = ldap_init( host, port );
	if ( ld == NULL ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
74
75
76
		return( NULL );
	}

77
	rc = ldap_open_defconn( ld );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
78

79
	if( rc < 0 ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
80
		ldap_ld_free( ld, 0, NULL, NULL );
81
		ld = NULL;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
82
83
	}

84
	Debug( LDAP_DEBUG_TRACE, "ldap_open: %s\n",
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
85
		ld != NULL ? "succeeded" : "failed", 0, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
86

87
	return ld;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
88
89
90
}


91
92
93

int
ldap_create( LDAP **ldp )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
94
95
{
	LDAP			*ld;
96
	struct ldapoptions	*gopts;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
97

98
	*ldp = NULL;
99
100
101
102
103
104
105
106
	/* Get pointer to global option structure */
	if ( (gopts = LDAP_INT_GLOBAL_OPT()) == NULL) {
		return LDAP_NO_MEMORY;
	}

	/* Initialize the global options, if not already done. */
	if( gopts->ldo_valid != LDAP_INITIALIZED ) {
		ldap_int_initialize(gopts, NULL);
107
108
		if ( gopts->ldo_valid != LDAP_INITIALIZED )
			return LDAP_LOCAL_ERROR;
109
110
	}

111
	Debug( LDAP_DEBUG_TRACE, "ldap_create\n", 0, 0, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
112

113
	if ( (ld = (LDAP *) LDAP_CALLOC( 1, sizeof(LDAP) )) == NULL ) {
114
		return( LDAP_NO_MEMORY );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
115
	}
116
   
117
	/* copy the global options */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
118
	AC_MEMCPY(&ld->ld_options, gopts, sizeof(ld->ld_options));
119

120
121
	ld->ld_valid = LDAP_VALID_SESSION;

Kurt Zeilenga's avatar
Kurt Zeilenga committed
122
123
124
	/* but not pointers to malloc'ed items */
	ld->ld_options.ldo_sctrls = NULL;
	ld->ld_options.ldo_cctrls = NULL;
125
	ld->ld_options.ldo_defludp = NULL;
126

127
128
129
130
131
132
133
134
135
136
137
#ifdef HAVE_CYRUS_SASL
	ld->ld_options.ldo_def_sasl_mech = gopts->ldo_def_sasl_mech
		? LDAP_STRDUP( gopts->ldo_def_sasl_mech ) : NULL;
	ld->ld_options.ldo_def_sasl_realm = gopts->ldo_def_sasl_realm
		? LDAP_STRDUP( gopts->ldo_def_sasl_realm ) : NULL;
	ld->ld_options.ldo_def_sasl_authcid = gopts->ldo_def_sasl_authcid
		? LDAP_STRDUP( gopts->ldo_def_sasl_authcid ) : NULL;
	ld->ld_options.ldo_def_sasl_authzid = gopts->ldo_def_sasl_authzid
		? LDAP_STRDUP( gopts->ldo_def_sasl_authzid ) : NULL;
#endif

Howard Chu's avatar
Howard Chu committed
138
#ifdef HAVE_TLS
139
140
	/* We explicitly inherit the SSL_CTX, don't need the names/paths. Leave
	 * them empty to allow new SSL_CTX's to be created from scratch.
Howard Chu's avatar
Howard Chu committed
141
142
143
	 */
	memset( &ld->ld_options.ldo_tls_info, 0,
		sizeof( ld->ld_options.ldo_tls_info ));
144
	ld->ld_options.ldo_tls_ctx = NULL;
Howard Chu's avatar
Howard Chu committed
145
146
#endif

147
148
149
150
	if ( gopts->ldo_defludp ) {
		ld->ld_options.ldo_defludp = ldap_url_duplist(gopts->ldo_defludp);

		if ( ld->ld_options.ldo_defludp == NULL ) goto nomem;
151
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
152

153
154
	if (( ld->ld_selectinfo = ldap_new_select_info()) == NULL ) goto nomem;

Kurt Zeilenga's avatar
Kurt Zeilenga committed
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
161
162
#ifdef LDAP_R_COMPILE
	ldap_pvt_thread_mutex_init( &ld->ld_req_mutex );
	ldap_pvt_thread_mutex_init( &ld->ld_res_mutex );
163
	ldap_pvt_thread_mutex_init( &ld->ld_conn_mutex );
164
#endif
165
166
	*ldp = ld;
	return LDAP_SUCCESS;
167
168
169
170
171
172
173
174
175
176
177
178

nomem:
	ldap_free_select_info( ld->ld_selectinfo );
	ldap_free_urllist( ld->ld_options.ldo_defludp );
#ifdef HAVE_CYRUS_SASL
	LDAP_FREE( ld->ld_options.ldo_def_sasl_authzid );
	LDAP_FREE( ld->ld_options.ldo_def_sasl_authcid );
	LDAP_FREE( ld->ld_options.ldo_def_sasl_realm );
	LDAP_FREE( ld->ld_options.ldo_def_sasl_mech );
#endif
	LDAP_FREE( (char *)ld );
	return LDAP_NO_MEMORY;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
179
180
}

181
182
183
184
185
186
187
/*
 * ldap_init - initialize the LDAP library.  A magic cookie to be used for
 * future communication is returned on success, NULL on failure.
 * "host" may be a space-separated list of hosts or IP addresses
 *
 * Example:
 *	LDAP	*ld;
188
 *	ld = ldap_init( host, port );
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
 */
LDAP *
ldap_init( LDAP_CONST char *defhost, int defport )
{
	LDAP *ld;
	int rc;

	rc = ldap_create(&ld);
	if ( rc != LDAP_SUCCESS )
		return NULL;

	if (defport != 0)
		ld->ld_options.ldo_defport = defport;

	if (defhost != NULL) {
		rc = ldap_set_option(ld, LDAP_OPT_HOST_NAME, defhost);
		if ( rc != LDAP_SUCCESS ) {
			ldap_ld_free(ld, 1, NULL, NULL);
			return NULL;
		}
	}

	return( ld );
}


215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
int
ldap_initialize( LDAP **ldp, LDAP_CONST char *url )
{
	int rc;
	LDAP *ld;

	*ldp = NULL;
	rc = ldap_create(&ld);
	if ( rc != LDAP_SUCCESS )
		return rc;

	if (url != NULL) {
		rc = ldap_set_option(ld, LDAP_OPT_URI, url);
		if ( rc != LDAP_SUCCESS ) {
			ldap_ld_free(ld, 1, NULL, NULL);
			return rc;
		}
232
#ifdef LDAP_CONNECTIONLESS
233
		if (ldap_is_ldapc_url(url))
Howard Chu's avatar
Howard Chu committed
234
			LDAP_IS_UDP(ld) = 1;
235
#endif
236
237
238
239
240
	}

	*ldp = ld;
	return LDAP_SUCCESS;
}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
241

242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
int
ldap_init_fd(
	ber_socket_t fd,
	int proto,
	LDAP_CONST char *url,
	LDAP **ldp
)
{
	int rc;
	LDAP *ld;
	LDAPConn *conn;

	*ldp = NULL;
	rc = ldap_create( &ld );
	if( rc != LDAP_SUCCESS )
		return( rc );

	if (url != NULL) {
		rc = ldap_set_option(ld, LDAP_OPT_URI, url);
		if ( rc != LDAP_SUCCESS ) {
			ldap_ld_free(ld, 1, NULL, NULL);
			return rc;
		}
	}

	/* Attach the passed socket as the LDAP's connection */
	conn = ldap_new_connection( ld, NULL, 1, 0, NULL);
	if( conn == NULL ) {
		ldap_unbind_ext( ld, NULL, NULL );
		return( LDAP_NO_MEMORY );
	}
	ber_sockbuf_ctrl( conn->lconn_sb, LBER_SB_OPT_SET_FD, &fd );
	ld->ld_defconn = conn;
	++ld->ld_defconn->lconn_refcnt;	/* so it never gets closed/freed */

	switch( proto ) {
	case LDAP_PROTO_TCP:
#ifdef LDAP_DEBUG
		ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
			LBER_SBIOD_LEVEL_PROVIDER, (void *)"tcp_" );
#endif
		ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_tcp,
			LBER_SBIOD_LEVEL_PROVIDER, NULL );
		break;

#ifdef LDAP_CONNECTIONLESS
	case LDAP_PROTO_UDP:
#ifdef LDAP_DEBUG
		ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
			LBER_SBIOD_LEVEL_PROVIDER, (void *)"udp_" );
#endif
		ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_udp,
			LBER_SBIOD_LEVEL_PROVIDER, NULL );
		ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_readahead,
			LBER_SBIOD_LEVEL_PROVIDER, NULL );
		break;
#endif /* LDAP_CONNECTIONLESS */

	case LDAP_PROTO_IPC:
#ifdef LDAP_DEBUG
		ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
			LBER_SBIOD_LEVEL_PROVIDER, (void *)"ipc_" );
#endif
		ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_fd,
			LBER_SBIOD_LEVEL_PROVIDER, NULL );
		break;

	case LDAP_PROTO_EXT:
		/* caller must supply sockbuf handlers */
		break;

	default:
		ldap_unbind_ext( ld, NULL, NULL );
		return LDAP_PARAM_ERROR;
	}

#ifdef LDAP_DEBUG
	ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
		INT_MAX, (void *)"ldap_" );
#endif

	/* Add the connection to the *LDAP's select pool */
	ldap_mark_select_read( ld, conn->lconn_sb );
	ldap_mark_select_write( ld, conn->lconn_sb );
	
	*ldp = ld;
	return LDAP_SUCCESS;
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
331
int
332
333
334
335
336
ldap_int_open_connection(
	LDAP *ld,
	LDAPConn *conn,
	LDAPURLDesc *srv,
	int async )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
337
{
338
	int rc = -1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
339
	char *host;
340
	int port, proto;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
341

342
	Debug( LDAP_DEBUG_TRACE, "ldap_int_open_connection\n", 0, 0, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
343

344
	switch ( proto = ldap_pvt_url_scheme2proto( srv->lud_scheme ) ) {
345
		case LDAP_PROTO_TCP:
Kurt Zeilenga's avatar
Kurt Zeilenga committed
346
			port = srv->lud_port;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
347

Kurt Zeilenga's avatar
Kurt Zeilenga committed
348
349
350
351
352
			if ( srv->lud_host == NULL || *srv->lud_host == 0 ) {
				host = NULL;
			} else {
				host = srv->lud_host;
			}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
353

Kurt Zeilenga's avatar
Kurt Zeilenga committed
354
355
356
357
358
359
360
361
			if( !port ) {
				if( strcmp(srv->lud_scheme, "ldaps") == 0 ) {
					port = LDAPS_PORT;
				} else {
					port = LDAP_PORT;
				}
			}

362
			rc = ldap_connect_to_host( ld, conn->lconn_sb,
363
				proto, host, port, async );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
364

365
			if ( rc == -1 ) return rc;
366
367
368
369
370

#ifdef LDAP_DEBUG
			ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
				LBER_SBIOD_LEVEL_PROVIDER, (void *)"tcp_" );
#endif
371
			ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_tcp,
372
				LBER_SBIOD_LEVEL_PROVIDER, NULL );
373

374
			break;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
375

376
#ifdef LDAP_CONNECTIONLESS
377
		case LDAP_PROTO_UDP:
Kurt Zeilenga's avatar
Kurt Zeilenga committed
378
			port = srv->lud_port;
379
380
381
382
383
384

			if ( srv->lud_host == NULL || *srv->lud_host == 0 ) {
				host = NULL;
			} else {
				host = srv->lud_host;
			}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
385
386
387

			if( !port ) port = LDAP_PORT;

Howard Chu's avatar
Howard Chu committed
388
			LDAP_IS_UDP(ld) = 1;
389
			rc = ldap_connect_to_host( ld, conn->lconn_sb,
390
				proto, host, port, async );
391
392
393
394
395
396
397
398

			if ( rc == -1 ) return rc;
#ifdef LDAP_DEBUG
			ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
				LBER_SBIOD_LEVEL_PROVIDER, (void *)"udp_" );
#endif
			ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_udp,
				LBER_SBIOD_LEVEL_PROVIDER, NULL );
399
400
401
402

			ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_readahead,
				LBER_SBIOD_LEVEL_PROVIDER, NULL );

403
404
			break;
#endif
405
		case LDAP_PROTO_IPC:
Kurt Zeilenga's avatar
Kurt Zeilenga committed
406
407
#ifdef LDAP_PF_LOCAL
			/* only IPC mechanism supported is PF_LOCAL (PF_UNIX) */
408
			rc = ldap_connect_to_path( ld, conn->lconn_sb,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
409
				srv->lud_host, async );
410
			if ( rc == -1 ) return rc;
411
412
413
414
#ifdef LDAP_DEBUG
			ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
				LBER_SBIOD_LEVEL_PROVIDER, (void *)"ipc_" );
#endif
415
			ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_fd,
416
				LBER_SBIOD_LEVEL_PROVIDER, NULL );
417

418
			break;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
419
#endif /* LDAP_PF_LOCAL */
420
		default:
421
			return -1;
422
423
424
			break;
	}

425
426
	conn->lconn_created = time( NULL );

427
#ifdef LDAP_DEBUG
428
	ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
429
		INT_MAX, (void *)"ldap_" );
430
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
431

432
#ifdef LDAP_CONNECTIONLESS
Kurt Zeilenga's avatar
Kurt Zeilenga committed
433
	if( proto == LDAP_PROTO_UDP ) return 0;
434
435
#endif

436
#ifdef HAVE_TLS
Howard Chu's avatar
Howard Chu committed
437
	if (ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD ||
438
439
		strcmp( srv->lud_scheme, "ldaps" ) == 0 )
	{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
440
441
		++conn->lconn_refcnt;	/* avoid premature free */

442
		rc = ldap_int_tls_start( ld, conn, srv );
443

Kurt Zeilenga's avatar
Kurt Zeilenga committed
444
445
		--conn->lconn_refcnt;

446
447
448
		if (rc != LDAP_SUCCESS) {
			return -1;
		}
449
450
	}
#endif
451

Kurt Zeilenga's avatar
Kurt Zeilenga committed
452
453
	return( 0 );
}
454
455


456
457
int
ldap_open_internal_connection( LDAP **ldp, ber_socket_t *fdp )
458
459
460
461
462
463
464
465
466
467
468
469
470
471
{
	int rc;
	LDAPConn *c;
	LDAPRequest *lr;

	rc = ldap_create( ldp );
	if( rc != LDAP_SUCCESS ) {
		*ldp = NULL;
		return( rc );
	}

	/* Make it appear that a search request, msgid 0, was sent */
	lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ));
	if( lr == NULL ) {
472
		ldap_unbind_ext( *ldp, NULL, NULL );
473
474
475
476
477
478
479
		*ldp = NULL;
		return( LDAP_NO_MEMORY );
	}
	memset(lr, 0, sizeof( LDAPRequest ));
	lr->lr_msgid = 0;
	lr->lr_status = LDAP_REQST_INPROGRESS;
	lr->lr_res_errno = LDAP_SUCCESS;
480
	/* no mutex lock needed, we just created this ld here */
481
482
483
484
485
	(*ldp)->ld_requests = lr;

	/* Attach the passed socket as the *LDAP's connection */
	c = ldap_new_connection( *ldp, NULL, 1, 0, NULL);
	if( c == NULL ) {
486
		ldap_unbind_ext( *ldp, NULL, NULL );
487
488
489
490
		*ldp = NULL;
		return( LDAP_NO_MEMORY );
	}
	ber_sockbuf_ctrl( c->lconn_sb, LBER_SB_OPT_SET_FD, fdp );
491
492
493
494
#ifdef LDAP_DEBUG
	ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_debug,
		LBER_SBIOD_LEVEL_PROVIDER, (void *)"int_" );
#endif
495
496
497
498
499
500
501
502
503
504
505
506
507
508
	ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_tcp,
	  LBER_SBIOD_LEVEL_PROVIDER, NULL );
	(*ldp)->ld_defconn = c;

	/* Add the connection to the *LDAP's select pool */
	ldap_mark_select_read( *ldp, c->lconn_sb );
	ldap_mark_select_write( *ldp, c->lconn_sb );

	/* Make this connection an LDAP V3 protocol connection */
	rc = LDAP_VERSION3;
	ldap_set_option( *ldp, LDAP_OPT_PROTOCOL_VERSION, &rc );

	return( LDAP_SUCCESS );
}