~ttx/openldap/lucid-gssapi-495418

« back to all changes in this revision

Viewing changes to libraries/libldap/open.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathias Gug
  • Date: 2008-07-10 14:45:49 UTC
  • Revision ID: james.westby@ubuntu.com-20080710144549-wck73med0e72gfyo
Tags: upstream-2.4.10
ImportĀ upstreamĀ versionĀ 2.4.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}