]> git.sur5r.net Git - openldap/blob - libraries/libldap/open.c
ITS#4875 from HEAD, zero length reads
[openldap] / libraries / libldap / open.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2007 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_tm_api = NULL;
126         ld->ld_options.ldo_tm_net = NULL;
127         ld->ld_options.ldo_defludp = NULL;
128
129 #ifdef HAVE_CYRUS_SASL
130         ld->ld_options.ldo_def_sasl_mech = gopts->ldo_def_sasl_mech
131                 ? LDAP_STRDUP( gopts->ldo_def_sasl_mech ) : NULL;
132         ld->ld_options.ldo_def_sasl_realm = gopts->ldo_def_sasl_realm
133                 ? LDAP_STRDUP( gopts->ldo_def_sasl_realm ) : NULL;
134         ld->ld_options.ldo_def_sasl_authcid = gopts->ldo_def_sasl_authcid
135                 ? LDAP_STRDUP( gopts->ldo_def_sasl_authcid ) : NULL;
136         ld->ld_options.ldo_def_sasl_authzid = gopts->ldo_def_sasl_authzid
137                 ? LDAP_STRDUP( gopts->ldo_def_sasl_authzid ) : NULL;
138 #endif
139
140         if ( gopts->ldo_tm_api &&
141                 ldap_int_timeval_dup( &ld->ld_options.ldo_tm_api, gopts->ldo_tm_api ))
142                 goto nomem;
143
144         if ( gopts->ldo_tm_net &&
145                 ldap_int_timeval_dup( &ld->ld_options.ldo_tm_net, gopts->ldo_tm_net ))
146                 goto nomem;
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         LDAP_FREE( ld->ld_options.ldo_tm_net );
173         LDAP_FREE( ld->ld_options.ldo_tm_api );
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_int_open_connection(
247         LDAP *ld,
248         LDAPConn *conn,
249         LDAPURLDesc *srv,
250         int async )
251 {
252         int rc = -1;
253         char *host;
254         int port, proto;
255
256         Debug( LDAP_DEBUG_TRACE, "ldap_int_open_connection\n", 0, 0, 0 );
257
258         switch ( proto = ldap_pvt_url_scheme2proto( srv->lud_scheme ) ) {
259                 case LDAP_PROTO_TCP:
260                         port = srv->lud_port;
261
262                         if ( srv->lud_host == NULL || *srv->lud_host == 0 ) {
263                                 host = NULL;
264                         } else {
265                                 host = srv->lud_host;
266                         }
267
268                         if( !port ) {
269                                 if( strcmp(srv->lud_scheme, "ldaps") == 0 ) {
270                                         port = LDAPS_PORT;
271                                 } else {
272                                         port = LDAP_PORT;
273                                 }
274                         }
275
276                         rc = ldap_connect_to_host( ld, conn->lconn_sb,
277                                 proto, host, port, async );
278
279                         if ( rc == -1 ) return rc;
280
281 #ifdef LDAP_DEBUG
282                         ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
283                                 LBER_SBIOD_LEVEL_PROVIDER, (void *)"tcp_" );
284 #endif
285                         ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_tcp,
286                                 LBER_SBIOD_LEVEL_PROVIDER, NULL );
287
288                         break;
289
290 #ifdef LDAP_CONNECTIONLESS
291                 case LDAP_PROTO_UDP:
292                         port = srv->lud_port;
293
294                         if ( srv->lud_host == NULL || *srv->lud_host == 0 ) {
295                                 host = NULL;
296                         } else {
297                                 host = srv->lud_host;
298                         }
299
300                         if( !port ) port = LDAP_PORT;
301
302                         LDAP_IS_UDP(ld) = 1;
303                         rc = ldap_connect_to_host( ld, conn->lconn_sb,
304                                 proto, host, port, async );
305
306                         if ( rc == -1 ) return rc;
307 #ifdef LDAP_DEBUG
308                         ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
309                                 LBER_SBIOD_LEVEL_PROVIDER, (void *)"udp_" );
310 #endif
311                         ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_udp,
312                                 LBER_SBIOD_LEVEL_PROVIDER, NULL );
313
314                         ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_readahead,
315                                 LBER_SBIOD_LEVEL_PROVIDER, NULL );
316
317                         break;
318 #endif
319                 case LDAP_PROTO_IPC:
320 #ifdef LDAP_PF_LOCAL
321                         /* only IPC mechanism supported is PF_LOCAL (PF_UNIX) */
322                         rc = ldap_connect_to_path( ld, conn->lconn_sb,
323                                 srv->lud_host, async );
324                         if ( rc == -1 ) return rc;
325 #ifdef LDAP_DEBUG
326                         ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
327                                 LBER_SBIOD_LEVEL_PROVIDER, (void *)"ipc_" );
328 #endif
329                         ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_fd,
330                                 LBER_SBIOD_LEVEL_PROVIDER, NULL );
331
332                         break;
333 #endif /* LDAP_PF_LOCAL */
334                 default:
335                         return -1;
336                         break;
337         }
338
339 #ifdef LDAP_DEBUG
340         ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
341                 INT_MAX, (void *)"ldap_" );
342 #endif
343
344 #ifdef LDAP_CONNECTIONLESS
345         if( proto == LDAP_PROTO_UDP ) return 0;
346 #endif
347
348 #ifdef HAVE_TLS
349         if (ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD ||
350                 strcmp( srv->lud_scheme, "ldaps" ) == 0 )
351         {
352                 ++conn->lconn_refcnt;   /* avoid premature free */
353
354                 rc = ldap_int_tls_start( ld, conn, srv );
355
356                 --conn->lconn_refcnt;
357
358                 if (rc != LDAP_SUCCESS) {
359                         return -1;
360                 }
361         }
362 #endif
363
364 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
365         if ( conn->lconn_krbinstance == NULL ) {
366                 char *c;
367                 conn->lconn_krbinstance = ldap_host_connected_to(
368                         conn->lconn_sb, host );
369
370                 if( conn->lconn_krbinstance != NULL && 
371                     ( c = strchr( conn->lconn_krbinstance, '.' )) != NULL ) {
372                         *c = '\0';
373                 }
374         }
375 #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */
376
377         return( 0 );
378 }
379
380
381 int ldap_open_internal_connection( LDAP **ldp, ber_socket_t *fdp )
382 {
383         int rc;
384         LDAPConn *c;
385         LDAPRequest *lr;
386
387         rc = ldap_create( ldp );
388         if( rc != LDAP_SUCCESS ) {
389                 *ldp = NULL;
390                 return( rc );
391         }
392
393         /* Make it appear that a search request, msgid 0, was sent */
394         lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ));
395         if( lr == NULL ) {
396                 ldap_unbind( *ldp );
397                 *ldp = NULL;
398                 return( LDAP_NO_MEMORY );
399         }
400         memset(lr, 0, sizeof( LDAPRequest ));
401         lr->lr_msgid = 0;
402         lr->lr_status = LDAP_REQST_INPROGRESS;
403         lr->lr_res_errno = LDAP_SUCCESS;
404         /* no mutex lock needed, we just created this ld here */
405         (*ldp)->ld_requests = lr;
406
407         /* Attach the passed socket as the *LDAP's connection */
408         c = ldap_new_connection( *ldp, NULL, 1, 0, NULL);
409         if( c == NULL ) {
410                 ldap_unbind( *ldp );
411                 *ldp = NULL;
412                 return( LDAP_NO_MEMORY );
413         }
414         ber_sockbuf_ctrl( c->lconn_sb, LBER_SB_OPT_SET_FD, fdp );
415 #ifdef LDAP_DEBUG
416         ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_debug,
417                 LBER_SBIOD_LEVEL_PROVIDER, (void *)"int_" );
418 #endif
419         ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_tcp,
420           LBER_SBIOD_LEVEL_PROVIDER, NULL );
421         (*ldp)->ld_defconn = c;
422
423         /* Add the connection to the *LDAP's select pool */
424         ldap_mark_select_read( *ldp, c->lconn_sb );
425         ldap_mark_select_write( *ldp, c->lconn_sb );
426
427         /* Make this connection an LDAP V3 protocol connection */
428         rc = LDAP_VERSION3;
429         ldap_set_option( *ldp, LDAP_OPT_PROTOCOL_VERSION, &rc );
430
431         return( LDAP_SUCCESS );
432 }