]> git.sur5r.net Git - openldap/blob - libraries/libldap/open.c
8588e884580d84d371cdd33bdecda19a878fe134
[openldap] / libraries / libldap / open.c
1 /* $OpenLDAP$ */
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         ld->ld_options.ldo_conn_cbs = NULL;
127
128 #ifdef HAVE_CYRUS_SASL
129         ld->ld_options.ldo_def_sasl_mech = gopts->ldo_def_sasl_mech
130                 ? LDAP_STRDUP( gopts->ldo_def_sasl_mech ) : NULL;
131         ld->ld_options.ldo_def_sasl_realm = gopts->ldo_def_sasl_realm
132                 ? LDAP_STRDUP( gopts->ldo_def_sasl_realm ) : NULL;
133         ld->ld_options.ldo_def_sasl_authcid = gopts->ldo_def_sasl_authcid
134                 ? LDAP_STRDUP( gopts->ldo_def_sasl_authcid ) : NULL;
135         ld->ld_options.ldo_def_sasl_authzid = gopts->ldo_def_sasl_authzid
136                 ? LDAP_STRDUP( gopts->ldo_def_sasl_authzid ) : NULL;
137 #endif
138
139 #ifdef HAVE_TLS
140         /* We explicitly inherit the SSL_CTX, don't need the names/paths. Leave
141          * them empty to allow new SSL_CTX's to be created from scratch.
142          */
143         memset( &ld->ld_options.ldo_tls_info, 0,
144                 sizeof( ld->ld_options.ldo_tls_info ));
145         ld->ld_options.ldo_tls_ctx = NULL;
146 #endif
147
148         if ( gopts->ldo_defludp ) {
149                 ld->ld_options.ldo_defludp = ldap_url_duplist(gopts->ldo_defludp);
150
151                 if ( ld->ld_options.ldo_defludp == NULL ) goto nomem;
152         }
153
154         if (( ld->ld_selectinfo = ldap_new_select_info()) == NULL ) goto nomem;
155
156         ld->ld_lberoptions = LBER_USE_DER;
157
158         ld->ld_sb = ber_sockbuf_alloc( );
159         if ( ld->ld_sb == NULL ) goto nomem;
160
161 #ifdef LDAP_R_COMPILE
162         ldap_pvt_thread_mutex_init( &ld->ld_req_mutex );
163         ldap_pvt_thread_mutex_init( &ld->ld_res_mutex );
164         ldap_pvt_thread_mutex_init( &ld->ld_conn_mutex );
165 #endif
166         *ldp = ld;
167         return LDAP_SUCCESS;
168
169 nomem:
170         ldap_free_select_info( ld->ld_selectinfo );
171         ldap_free_urllist( ld->ld_options.ldo_defludp );
172 #ifdef HAVE_CYRUS_SASL
173         LDAP_FREE( ld->ld_options.ldo_def_sasl_authzid );
174         LDAP_FREE( ld->ld_options.ldo_def_sasl_authcid );
175         LDAP_FREE( ld->ld_options.ldo_def_sasl_realm );
176         LDAP_FREE( ld->ld_options.ldo_def_sasl_mech );
177 #endif
178         LDAP_FREE( (char *)ld );
179         return LDAP_NO_MEMORY;
180 }
181
182 /*
183  * ldap_init - initialize the LDAP library.  A magic cookie to be used for
184  * future communication is returned on success, NULL on failure.
185  * "host" may be a space-separated list of hosts or IP addresses
186  *
187  * Example:
188  *      LDAP    *ld;
189  *      ld = ldap_init( host, port );
190  */
191 LDAP *
192 ldap_init( LDAP_CONST char *defhost, int defport )
193 {
194         LDAP *ld;
195         int rc;
196
197         rc = ldap_create(&ld);
198         if ( rc != LDAP_SUCCESS )
199                 return NULL;
200
201         if (defport != 0)
202                 ld->ld_options.ldo_defport = defport;
203
204         if (defhost != NULL) {
205                 rc = ldap_set_option(ld, LDAP_OPT_HOST_NAME, defhost);
206                 if ( rc != LDAP_SUCCESS ) {
207                         ldap_ld_free(ld, 1, NULL, NULL);
208                         return NULL;
209                 }
210         }
211
212         return( ld );
213 }
214
215
216 int
217 ldap_initialize( LDAP **ldp, LDAP_CONST char *url )
218 {
219         int rc;
220         LDAP *ld;
221
222         *ldp = NULL;
223         rc = ldap_create(&ld);
224         if ( rc != LDAP_SUCCESS )
225                 return rc;
226
227         if (url != NULL) {
228                 rc = ldap_set_option(ld, LDAP_OPT_URI, url);
229                 if ( rc != LDAP_SUCCESS ) {
230                         ldap_ld_free(ld, 1, NULL, NULL);
231                         return rc;
232                 }
233 #ifdef LDAP_CONNECTIONLESS
234                 if (ldap_is_ldapc_url(url))
235                         LDAP_IS_UDP(ld) = 1;
236 #endif
237         }
238
239         *ldp = ld;
240         return LDAP_SUCCESS;
241 }
242
243 int
244 ldap_init_fd(
245         ber_socket_t fd,
246         int proto,
247         LDAP_CONST char *url,
248         LDAP **ldp
249 )
250 {
251         int rc;
252         LDAP *ld;
253         LDAPConn *conn;
254
255         *ldp = NULL;
256         rc = ldap_create( &ld );
257         if( rc != LDAP_SUCCESS )
258                 return( rc );
259
260         if (url != NULL) {
261                 rc = ldap_set_option(ld, LDAP_OPT_URI, url);
262                 if ( rc != LDAP_SUCCESS ) {
263                         ldap_ld_free(ld, 1, NULL, NULL);
264                         return rc;
265                 }
266         }
267
268         /* Attach the passed socket as the LDAP's connection */
269         conn = ldap_new_connection( ld, NULL, 1, 0, NULL);
270         if( conn == NULL ) {
271                 ldap_unbind_ext( ld, NULL, NULL );
272                 return( LDAP_NO_MEMORY );
273         }
274         ber_sockbuf_ctrl( conn->lconn_sb, LBER_SB_OPT_SET_FD, &fd );
275         ld->ld_defconn = conn;
276         ++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */
277
278         switch( proto ) {
279         case LDAP_PROTO_TCP:
280 #ifdef LDAP_DEBUG
281                 ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
282                         LBER_SBIOD_LEVEL_PROVIDER, (void *)"tcp_" );
283 #endif
284                 ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_tcp,
285                         LBER_SBIOD_LEVEL_PROVIDER, NULL );
286                 break;
287
288 #ifdef LDAP_CONNECTIONLESS
289         case LDAP_PROTO_UDP:
290 #ifdef LDAP_DEBUG
291                 ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
292                         LBER_SBIOD_LEVEL_PROVIDER, (void *)"udp_" );
293 #endif
294                 ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_udp,
295                         LBER_SBIOD_LEVEL_PROVIDER, NULL );
296                 ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_readahead,
297                         LBER_SBIOD_LEVEL_PROVIDER, NULL );
298                 break;
299 #endif /* LDAP_CONNECTIONLESS */
300
301         case LDAP_PROTO_IPC:
302 #ifdef LDAP_DEBUG
303                 ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
304                         LBER_SBIOD_LEVEL_PROVIDER, (void *)"ipc_" );
305 #endif
306                 ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_fd,
307                         LBER_SBIOD_LEVEL_PROVIDER, NULL );
308                 break;
309
310         case LDAP_PROTO_EXT:
311                 /* caller must supply sockbuf handlers */
312                 break;
313
314         default:
315                 ldap_unbind_ext( ld, NULL, NULL );
316                 return LDAP_PARAM_ERROR;
317         }
318
319 #ifdef LDAP_DEBUG
320         ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
321                 INT_MAX, (void *)"ldap_" );
322 #endif
323
324         /* Add the connection to the *LDAP's select pool */
325         ldap_mark_select_read( ld, conn->lconn_sb );
326         ldap_mark_select_write( ld, conn->lconn_sb );
327         
328         *ldp = ld;
329         return LDAP_SUCCESS;
330 }
331
332 int
333 ldap_int_open_connection(
334         LDAP *ld,
335         LDAPConn *conn,
336         LDAPURLDesc *srv,
337         int async )
338 {
339         int rc = -1;
340         int 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                         rc = ldap_connect_to_host( ld, conn->lconn_sb,
347                                 proto, srv, async );
348
349                         if ( rc == -1 ) return rc;
350 #ifdef LDAP_DEBUG
351                         ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
352                                 LBER_SBIOD_LEVEL_PROVIDER, (void *)"tcp_" );
353 #endif
354                         ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_tcp,
355                                 LBER_SBIOD_LEVEL_PROVIDER, NULL );
356
357                         break;
358
359 #ifdef LDAP_CONNECTIONLESS
360                 case LDAP_PROTO_UDP:
361                         LDAP_IS_UDP(ld) = 1;
362                         rc = ldap_connect_to_host( ld, conn->lconn_sb,
363                                 proto, srv, async );
364
365                         if ( rc == -1 ) return rc;
366 #ifdef LDAP_DEBUG
367                         ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
368                                 LBER_SBIOD_LEVEL_PROVIDER, (void *)"udp_" );
369 #endif
370                         ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_udp,
371                                 LBER_SBIOD_LEVEL_PROVIDER, NULL );
372
373                         ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_readahead,
374                                 LBER_SBIOD_LEVEL_PROVIDER, NULL );
375
376                         break;
377 #endif
378                 case LDAP_PROTO_IPC:
379 #ifdef LDAP_PF_LOCAL
380                         /* only IPC mechanism supported is PF_LOCAL (PF_UNIX) */
381                         rc = ldap_connect_to_path( ld, conn->lconn_sb,
382                                 srv, async );
383                         if ( rc == -1 ) return rc;
384 #ifdef LDAP_DEBUG
385                         ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
386                                 LBER_SBIOD_LEVEL_PROVIDER, (void *)"ipc_" );
387 #endif
388                         ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_fd,
389                                 LBER_SBIOD_LEVEL_PROVIDER, NULL );
390
391                         break;
392 #endif /* LDAP_PF_LOCAL */
393                 default:
394                         return -1;
395                         break;
396         }
397
398         conn->lconn_created = time( NULL );
399
400 #ifdef LDAP_DEBUG
401         ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
402                 INT_MAX, (void *)"ldap_" );
403 #endif
404
405 #ifdef LDAP_CONNECTIONLESS
406         if( proto == LDAP_PROTO_UDP ) return 0;
407 #endif
408
409 #ifdef HAVE_TLS
410         if (ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD ||
411                 strcmp( srv->lud_scheme, "ldaps" ) == 0 )
412         {
413                 ++conn->lconn_refcnt;   /* avoid premature free */
414
415                 rc = ldap_int_tls_start( ld, conn, srv );
416
417                 --conn->lconn_refcnt;
418
419                 if (rc != LDAP_SUCCESS) {
420                         return -1;
421                 }
422         }
423 #endif
424
425         return( 0 );
426 }
427
428
429 int
430 ldap_open_internal_connection( LDAP **ldp, ber_socket_t *fdp )
431 {
432         int rc;
433         LDAPConn *c;
434         LDAPRequest *lr;
435
436         rc = ldap_create( ldp );
437         if( rc != LDAP_SUCCESS ) {
438                 *ldp = NULL;
439                 return( rc );
440         }
441
442         /* Make it appear that a search request, msgid 0, was sent */
443         lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ));
444         if( lr == NULL ) {
445                 ldap_unbind_ext( *ldp, NULL, NULL );
446                 *ldp = NULL;
447                 return( LDAP_NO_MEMORY );
448         }
449         memset(lr, 0, sizeof( LDAPRequest ));
450         lr->lr_msgid = 0;
451         lr->lr_status = LDAP_REQST_INPROGRESS;
452         lr->lr_res_errno = LDAP_SUCCESS;
453         /* no mutex lock needed, we just created this ld here */
454         (*ldp)->ld_requests = lr;
455
456         /* Attach the passed socket as the *LDAP's connection */
457         c = ldap_new_connection( *ldp, NULL, 1, 0, NULL);
458         if( c == NULL ) {
459                 ldap_unbind_ext( *ldp, NULL, NULL );
460                 *ldp = NULL;
461                 return( LDAP_NO_MEMORY );
462         }
463         ber_sockbuf_ctrl( c->lconn_sb, LBER_SB_OPT_SET_FD, fdp );
464 #ifdef LDAP_DEBUG
465         ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_debug,
466                 LBER_SBIOD_LEVEL_PROVIDER, (void *)"int_" );
467 #endif
468         ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_tcp,
469           LBER_SBIOD_LEVEL_PROVIDER, NULL );
470         (*ldp)->ld_defconn = c;
471
472         /* Add the connection to the *LDAP's select pool */
473         ldap_mark_select_read( *ldp, c->lconn_sb );
474         ldap_mark_select_write( *ldp, c->lconn_sb );
475
476         /* Make this connection an LDAP V3 protocol connection */
477         rc = LDAP_VERSION3;
478         ldap_set_option( *ldp, LDAP_OPT_PROTOCOL_VERSION, &rc );
479
480         return( LDAP_SUCCESS );
481 }