]> git.sur5r.net Git - openldap/blob - libraries/libldap/open.c
9df35ac8885c5066500130ee374c0aa11f9dfc07
[openldap] / libraries / libldap / open.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 /*  Portions
7  *  Copyright (c) 1995 Regents of the University of Michigan.
8  *  All rights reserved.
9  *
10  *  open.c
11  */
12
13 #include "portable.h"
14
15 #include <stdio.h>
16 #include <limits.h>
17
18 #include <ac/stdlib.h>
19
20 #include <ac/param.h>
21 #include <ac/socket.h>
22 #include <ac/string.h>
23 #include <ac/time.h>
24
25 #include "ldap-int.h"
26
27 int ldap_open_defconn( LDAP *ld )
28 {
29         ld->ld_defconn = ldap_new_connection( ld,
30                 ld->ld_options.ldo_defludp, 1, 1, NULL );
31
32         if( ld->ld_defconn == NULL ) {
33                 ld->ld_errno = LDAP_SERVER_DOWN;
34                 return -1;
35         }
36
37         ++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */
38         return 0;
39 }
40
41 /*
42  * ldap_open - initialize and connect to an ldap server.  A magic cookie to
43  * be used for future communication is returned on success, NULL on failure.
44  * "host" may be a space-separated list of hosts or IP addresses
45  *
46  * Example:
47  *      LDAP    *ld;
48  *      ld = ldap_open( hostname, port );
49  */
50
51 LDAP *
52 ldap_open( LDAP_CONST char *host, int port )
53 {
54         int rc;
55         LDAP            *ld;
56
57         Debug( LDAP_DEBUG_TRACE, "ldap_open\n", 0, 0, 0 );
58
59         if (( ld = ldap_init( host, port )) == NULL ) {
60                 return( NULL );
61         }
62
63         rc = ldap_open_defconn( ld );
64
65         if( rc < 0 ) {
66                 ldap_ld_free( ld, 0, NULL, NULL );
67                 return( NULL );
68         }
69
70         Debug( LDAP_DEBUG_TRACE, "ldap_open successful, ld_host is %s\n",
71                 ( ld->ld_host == NULL ) ? "(null)" : ld->ld_host, 0, 0 );
72
73         return( ld );
74 }
75
76
77
78 int
79 ldap_create( LDAP **ldp )
80 {
81         LDAP                    *ld;
82         struct ldapoptions      *gopts;
83
84         *ldp = NULL;
85         /* Get pointer to global option structure */
86         if ( (gopts = LDAP_INT_GLOBAL_OPT()) == NULL) {
87                 return LDAP_NO_MEMORY;
88         }
89
90         /* Initialize the global options, if not already done. */
91         if( gopts->ldo_valid != LDAP_INITIALIZED ) {
92                 ldap_int_initialize(gopts, NULL);
93         }
94
95         Debug( LDAP_DEBUG_TRACE, "ldap_create\n", 0, 0, 0 );
96
97 #ifdef HAVE_WINSOCK2
98 {       WORD wVersionRequested;
99         WSADATA wsaData;
100  
101         wVersionRequested = MAKEWORD( 2, 0 );
102         if ( WSAStartup( wVersionRequested, &wsaData ) != 0 ) {
103                 /* Tell the user that we couldn't find a usable */
104                 /* WinSock DLL.                                  */
105                 return LDAP_LOCAL_ERROR;
106         }
107  
108         /* Confirm that the WinSock DLL supports 2.0.*/
109         /* Note that if the DLL supports versions greater    */
110         /* than 2.0 in addition to 2.0, it will still return */
111         /* 2.0 in wVersion since that is the version we      */
112         /* requested.                                        */
113  
114         if ( LOBYTE( wsaData.wVersion ) != 2 ||
115                 HIBYTE( wsaData.wVersion ) != 0 )
116         {
117             /* Tell the user that we couldn't find a usable */
118             /* WinSock DLL.                                  */
119             WSACleanup( );
120             return LDAP_LOCAL_ERROR; 
121         }
122 }       /* The WinSock DLL is acceptable. Proceed. */
123
124 #elif HAVE_WINSOCK
125 {       WSADATA wsaData;
126         if ( WSAStartup( 0x0101, &wsaData ) != 0 ) {
127             return LDAP_LOCAL_ERROR;
128         }
129 }
130 #endif
131
132         if ( (ld = (LDAP *) LDAP_CALLOC( 1, sizeof(LDAP) )) == NULL ) {
133             WSACleanup( );
134                 return( LDAP_NO_MEMORY );
135         }
136    
137         /* copy the global options */
138         AC_MEMCPY(&ld->ld_options, gopts, sizeof(ld->ld_options));
139
140         ld->ld_valid = LDAP_VALID_SESSION;
141
142         /* but not pointers to malloc'ed items */
143         ld->ld_options.ldo_sctrls = NULL;
144         ld->ld_options.ldo_cctrls = NULL;
145
146 #ifdef HAVE_CYRUS_SASL
147         ld->ld_options.ldo_def_sasl_mech = gopts->ldo_def_sasl_mech
148                 ? LDAP_STRDUP( gopts->ldo_def_sasl_mech ) : NULL;
149         ld->ld_options.ldo_def_sasl_realm = gopts->ldo_def_sasl_realm
150                 ? LDAP_STRDUP( gopts->ldo_def_sasl_realm ) : NULL;
151         ld->ld_options.ldo_def_sasl_authcid = gopts->ldo_def_sasl_authcid
152                 ? LDAP_STRDUP( gopts->ldo_def_sasl_authcid ) : NULL;
153         ld->ld_options.ldo_def_sasl_authzid = gopts->ldo_def_sasl_authzid
154                 ? LDAP_STRDUP( gopts->ldo_def_sasl_authzid ) : NULL;
155 #endif
156
157         ld->ld_options.ldo_defludp = ldap_url_duplist(gopts->ldo_defludp);
158
159         if ( ld->ld_options.ldo_defludp == NULL ) {
160                 LDAP_FREE( (char*)ld );
161             WSACleanup( );
162                 return LDAP_NO_MEMORY;
163         }
164
165         if (( ld->ld_selectinfo = ldap_new_select_info()) == NULL ) {
166                 ldap_free_urllist( ld->ld_options.ldo_defludp );
167                 LDAP_FREE( (char*) ld );
168             WSACleanup( );
169                 return LDAP_NO_MEMORY;
170         }
171
172         ld->ld_lberoptions = LBER_USE_DER;
173
174         ld->ld_sb = ber_sockbuf_alloc( );
175         if ( ld->ld_sb == NULL ) {
176                 ldap_free_urllist( ld->ld_options.ldo_defludp );
177                 LDAP_FREE( (char*) ld );
178                 WSACleanup( );
179                 return LDAP_NO_MEMORY;
180         }
181
182         *ldp = ld;
183         return LDAP_SUCCESS;
184 }
185
186 /*
187  * ldap_init - initialize the LDAP library.  A magic cookie to be used for
188  * future communication is returned on success, NULL on failure.
189  * "host" may be a space-separated list of hosts or IP addresses
190  *
191  * Example:
192  *      LDAP    *ld;
193  *      ld = ldap_init( host, port );
194  */
195 LDAP *
196 ldap_init( LDAP_CONST char *defhost, int defport )
197 {
198         LDAP *ld;
199         int rc;
200
201         rc = ldap_create(&ld);
202         if ( rc != LDAP_SUCCESS )
203                 return NULL;
204
205         if (defport != 0)
206                 ld->ld_options.ldo_defport = defport;
207
208         if (defhost != NULL) {
209                 rc = ldap_set_option(ld, LDAP_OPT_HOST_NAME, defhost);
210                 if ( rc != LDAP_SUCCESS ) {
211                         ldap_ld_free(ld, 1, NULL, NULL);
212                         return NULL;
213                 }
214         }
215
216         return( ld );
217 }
218
219
220 int
221 ldap_initialize( LDAP **ldp, LDAP_CONST char *url )
222 {
223         int rc;
224         LDAP *ld;
225
226         *ldp = NULL;
227         rc = ldap_create(&ld);
228         if ( rc != LDAP_SUCCESS )
229                 return rc;
230
231         if (url != NULL) {
232                 rc = ldap_set_option(ld, LDAP_OPT_URI, url);
233                 if ( rc != LDAP_SUCCESS ) {
234                         ldap_ld_free(ld, 1, NULL, NULL);
235                         return rc;
236                 }
237         }
238
239         *ldp = ld;
240         return LDAP_SUCCESS;
241 }
242
243 int
244 ldap_int_open_connection(
245         LDAP *ld,
246         LDAPConn *conn,
247         LDAPURLDesc *srv,
248         int async )
249 {
250         int rc = -1;
251 #ifdef HAVE_CYRUS_SASL
252         char *sasl_host = NULL;
253         int sasl_ssf = 0;
254 #endif
255         char *host;
256         int port;
257         long addr;
258
259         Debug( LDAP_DEBUG_TRACE, "ldap_int_open_connection\n", 0, 0, 0 );
260
261         switch ( ldap_pvt_url_scheme2proto( srv->lud_scheme ) ) {
262                 case LDAP_PROTO_TCP:
263                         port = htons( (short) srv->lud_port );
264
265                         addr = 0;
266                         if ( srv->lud_host == NULL || *srv->lud_host == 0 ) {
267                                 host = NULL;
268                                 addr = htonl( INADDR_LOOPBACK );
269                         } else {
270                                 host = srv->lud_host;
271                         }
272
273                         rc = ldap_connect_to_host( ld, conn->lconn_sb, 0,
274                                 host, addr, port, async );
275
276                         if ( rc == -1 ) return rc;
277
278 #ifdef LDAP_DEBUG
279                         ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
280                                 LBER_SBIOD_LEVEL_PROVIDER, (void *)"tcp_" );
281 #endif
282                         ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_tcp,
283                                 LBER_SBIOD_LEVEL_PROVIDER, NULL );
284
285 #ifdef HAVE_CYRUS_SASL
286                         sasl_host = ldap_host_connected_to( conn->lconn_sb );
287 #endif
288                         break;
289                 case LDAP_PROTO_IPC:
290 #ifdef LDAP_PF_LOCAL
291                         /* only IPC mechanism supported is PF_LOCAL (PF_UNIX) */
292                         rc = ldap_connect_to_path( ld, conn->lconn_sb,
293                                 srv->lud_host, async );
294                         if ( rc == -1 ) return rc;
295
296 #ifdef LDAP_DEBUG
297                         ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
298                                 LBER_SBIOD_LEVEL_PROVIDER, (void *)"ipc_" );
299 #endif
300                         ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_fd,
301                                 LBER_SBIOD_LEVEL_PROVIDER, NULL );
302
303 #ifdef HAVE_CYRUS_SASL
304                         sasl_host = ldap_host_connected_to( conn->lconn_sb );
305                         sasl_ssf = LDAP_PVT_SASL_LOCAL_SSF;
306 #endif
307                         break;
308 #endif /* LDAP_PF_LOCAL */
309                 default:
310                         return -1;
311                         break;
312         }
313
314 #ifdef HAVE_CYRUS_SASL
315         if( sasl_host != NULL ) {
316                 ldap_int_sasl_open( ld, conn, sasl_host, sasl_ssf );
317         }
318 #endif
319
320         ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_readahead,
321                 LBER_SBIOD_LEVEL_PROVIDER, NULL );
322
323 #ifdef LDAP_DEBUG
324         ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
325                 INT_MAX, (void *)"ldap_" );
326 #endif
327
328 #ifdef HAVE_TLS
329         if (ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD ||
330                 strcmp( srv->lud_scheme, "ldaps" ) == 0 )
331         {
332                 rc = ldap_pvt_tls_start( ld, conn->lconn_sb,
333                         ld->ld_options.ldo_tls_ctx );
334
335                 if (rc != LDAP_SUCCESS) {
336                         return -1;
337                 }
338         }
339 #endif
340
341 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
342         if ( conn->lconn_krbinstance == NULL ) {
343                 char *c;
344                 conn->lconn_krbinstance = ldap_host_connected_to( conn->lconn_sb );
345
346                 if( conn->lconn_krbinstance != NULL && 
347                     ( c = strchr( conn->lconn_krbinstance, '.' )) != NULL ) {
348                         *c = '\0';
349                 }
350         }
351 #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */
352
353         return( 0 );
354 }
355
356
357 int ldap_open_internal_connection( LDAP **ldp, ber_socket_t *fdp )
358 {
359         int rc;
360         LDAPConn *c;
361         LDAPRequest *lr;
362
363         rc = ldap_create( ldp );
364         if( rc != LDAP_SUCCESS ) {
365                 *ldp = NULL;
366                 return( rc );
367         }
368
369         /* Make it appear that a search request, msgid 0, was sent */
370         lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ));
371         if( lr == NULL ) {
372                 ldap_unbind( *ldp );
373                 *ldp = NULL;
374                 return( LDAP_NO_MEMORY );
375         }
376         memset(lr, 0, sizeof( LDAPRequest ));
377         lr->lr_msgid = 0;
378         lr->lr_status = LDAP_REQST_INPROGRESS;
379         lr->lr_res_errno = LDAP_SUCCESS;
380         (*ldp)->ld_requests = lr;
381
382         /* Attach the passed socket as the *LDAP's connection */
383         c = ldap_new_connection( *ldp, NULL, 1, 0, NULL);
384         if( c == NULL ) {
385                 ldap_unbind( *ldp );
386                 *ldp = NULL;
387                 return( LDAP_NO_MEMORY );
388         }
389         ber_sockbuf_ctrl( c->lconn_sb, LBER_SB_OPT_SET_FD, fdp );
390 #ifdef LDAP_DEBUG
391         ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_debug,
392                 LBER_SBIOD_LEVEL_PROVIDER, (void *)"int_" );
393 #endif
394         ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_tcp,
395           LBER_SBIOD_LEVEL_PROVIDER, NULL );
396         (*ldp)->ld_defconn = c;
397
398         /* Add the connection to the *LDAP's select pool */
399         ldap_mark_select_read( *ldp, c->lconn_sb );
400         ldap_mark_select_write( *ldp, c->lconn_sb );
401
402         /* Make this connection an LDAP V3 protocol connection */
403         rc = LDAP_VERSION3;
404         ldap_set_option( *ldp, LDAP_OPT_PROTOCOL_VERSION, &rc );
405
406         return( LDAP_SUCCESS );
407 }