1 /* $NetBSD: open.c,v 1.1.1.2 2010/03/08 02:14:20 lukem Exp $ */ 2 3 /* OpenLDAP: pkg/ldap/libraries/libldap/open.c,v 1.110.2.12 2009/11/18 22:19:02 quanah Exp */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1998-2009 The OpenLDAP Foundation. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted only as authorized by the OpenLDAP 11 * Public License. 12 * 13 * A copy of this license is available in the file LICENSE in the 14 * top-level directory of the distribution or, alternatively, at 15 * <http://www.OpenLDAP.org/license.html>. 16 */ 17 /* Portions Copyright (c) 1995 Regents of the University of Michigan. 18 * All rights reserved. 19 */ 20 21 #include "portable.h" 22 23 #include <stdio.h> 24 #ifdef HAVE_LIMITS_H 25 #include <limits.h> 26 #endif 27 28 #include <ac/stdlib.h> 29 30 #include <ac/param.h> 31 #include <ac/socket.h> 32 #include <ac/string.h> 33 #include <ac/time.h> 34 35 #include <ac/unistd.h> 36 37 #include "ldap-int.h" 38 #include "ldap_log.h" 39 40 /* Caller should hold the req_mutex if simultaneous accesses are possible */ 41 int ldap_open_defconn( LDAP *ld ) 42 { 43 ld->ld_defconn = ldap_new_connection( ld, 44 &ld->ld_options.ldo_defludp, 1, 1, NULL ); 45 46 if( ld->ld_defconn == NULL ) { 47 ld->ld_errno = LDAP_SERVER_DOWN; 48 return -1; 49 } 50 51 ++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */ 52 return 0; 53 } 54 55 /* 56 * ldap_open - initialize and connect to an ldap server. A magic cookie to 57 * be used for future communication is returned on success, NULL on failure. 58 * "host" may be a space-separated list of hosts or IP addresses 59 * 60 * Example: 61 * LDAP *ld; 62 * ld = ldap_open( hostname, port ); 63 */ 64 65 LDAP * 66 ldap_open( LDAP_CONST char *host, int port ) 67 { 68 int rc; 69 LDAP *ld; 70 71 Debug( LDAP_DEBUG_TRACE, "ldap_open(%s, %d)\n", 72 host, port, 0 ); 73 74 ld = ldap_init( host, port ); 75 if ( ld == NULL ) { 76 return( NULL ); 77 } 78 79 rc = ldap_open_defconn( ld ); 80 81 if( rc < 0 ) { 82 ldap_ld_free( ld, 0, NULL, NULL ); 83 ld = NULL; 84 } 85 86 Debug( LDAP_DEBUG_TRACE, "ldap_open: %s\n", 87 ld != NULL ? "succeeded" : "failed", 0, 0 ); 88 89 return ld; 90 } 91 92 93 94 int 95 ldap_create( LDAP **ldp ) 96 { 97 LDAP *ld; 98 struct ldapoptions *gopts; 99 100 *ldp = NULL; 101 /* Get pointer to global option structure */ 102 if ( (gopts = LDAP_INT_GLOBAL_OPT()) == NULL) { 103 return LDAP_NO_MEMORY; 104 } 105 106 /* Initialize the global options, if not already done. */ 107 if( gopts->ldo_valid != LDAP_INITIALIZED ) { 108 ldap_int_initialize(gopts, NULL); 109 if ( gopts->ldo_valid != LDAP_INITIALIZED ) 110 return LDAP_LOCAL_ERROR; 111 } 112 113 Debug( LDAP_DEBUG_TRACE, "ldap_create\n", 0, 0, 0 ); 114 115 if ( (ld = (LDAP *) LDAP_CALLOC( 1, sizeof(LDAP) )) == NULL ) { 116 return( LDAP_NO_MEMORY ); 117 } 118 119 /* copy the global options */ 120 AC_MEMCPY(&ld->ld_options, gopts, sizeof(ld->ld_options)); 121 122 ld->ld_valid = LDAP_VALID_SESSION; 123 124 /* but not pointers to malloc'ed items */ 125 ld->ld_options.ldo_sctrls = NULL; 126 ld->ld_options.ldo_cctrls = NULL; 127 ld->ld_options.ldo_defludp = NULL; 128 ld->ld_options.ldo_conn_cbs = NULL; 129 130 #ifdef HAVE_CYRUS_SASL 131 ld->ld_options.ldo_def_sasl_mech = gopts->ldo_def_sasl_mech 132 ? LDAP_STRDUP( gopts->ldo_def_sasl_mech ) : NULL; 133 ld->ld_options.ldo_def_sasl_realm = gopts->ldo_def_sasl_realm 134 ? LDAP_STRDUP( gopts->ldo_def_sasl_realm ) : NULL; 135 ld->ld_options.ldo_def_sasl_authcid = gopts->ldo_def_sasl_authcid 136 ? LDAP_STRDUP( gopts->ldo_def_sasl_authcid ) : NULL; 137 ld->ld_options.ldo_def_sasl_authzid = gopts->ldo_def_sasl_authzid 138 ? LDAP_STRDUP( gopts->ldo_def_sasl_authzid ) : NULL; 139 #endif 140 141 #ifdef HAVE_TLS 142 /* We explicitly inherit the SSL_CTX, don't need the names/paths. Leave 143 * them empty to allow new SSL_CTX's to be created from scratch. 144 */ 145 memset( &ld->ld_options.ldo_tls_info, 0, 146 sizeof( ld->ld_options.ldo_tls_info )); 147 ld->ld_options.ldo_tls_ctx = NULL; 148 #endif 149 150 if ( gopts->ldo_defludp ) { 151 ld->ld_options.ldo_defludp = ldap_url_duplist(gopts->ldo_defludp); 152 153 if ( ld->ld_options.ldo_defludp == NULL ) goto nomem; 154 } 155 156 if (( ld->ld_selectinfo = ldap_new_select_info()) == NULL ) goto nomem; 157 158 ld->ld_lberoptions = LBER_USE_DER; 159 160 ld->ld_sb = ber_sockbuf_alloc( ); 161 if ( ld->ld_sb == NULL ) goto nomem; 162 163 #ifdef LDAP_R_COMPILE 164 ldap_pvt_thread_mutex_init( &ld->ld_req_mutex ); 165 ldap_pvt_thread_mutex_init( &ld->ld_res_mutex ); 166 ldap_pvt_thread_mutex_init( &ld->ld_conn_mutex ); 167 #endif 168 *ldp = ld; 169 return LDAP_SUCCESS; 170 171 nomem: 172 ldap_free_select_info( ld->ld_selectinfo ); 173 ldap_free_urllist( ld->ld_options.ldo_defludp ); 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_init_fd( 247 ber_socket_t fd, 248 int proto, 249 LDAP_CONST char *url, 250 LDAP **ldp 251 ) 252 { 253 int rc; 254 LDAP *ld; 255 LDAPConn *conn; 256 257 *ldp = NULL; 258 rc = ldap_create( &ld ); 259 if( rc != LDAP_SUCCESS ) 260 return( rc ); 261 262 if (url != NULL) { 263 rc = ldap_set_option(ld, LDAP_OPT_URI, url); 264 if ( rc != LDAP_SUCCESS ) { 265 ldap_ld_free(ld, 1, NULL, NULL); 266 return rc; 267 } 268 } 269 270 /* Attach the passed socket as the LDAP's connection */ 271 conn = ldap_new_connection( ld, NULL, 1, 0, NULL); 272 if( conn == NULL ) { 273 ldap_unbind_ext( ld, NULL, NULL ); 274 return( LDAP_NO_MEMORY ); 275 } 276 if( url ) 277 conn->lconn_server = ldap_url_dup( ld->ld_options.ldo_defludp ); 278 ber_sockbuf_ctrl( conn->lconn_sb, LBER_SB_OPT_SET_FD, &fd ); 279 ld->ld_defconn = conn; 280 ++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */ 281 282 switch( proto ) { 283 case LDAP_PROTO_TCP: 284 #ifdef LDAP_DEBUG 285 ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, 286 LBER_SBIOD_LEVEL_PROVIDER, (void *)"tcp_" ); 287 #endif 288 ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_tcp, 289 LBER_SBIOD_LEVEL_PROVIDER, NULL ); 290 break; 291 292 #ifdef LDAP_CONNECTIONLESS 293 case LDAP_PROTO_UDP: 294 #ifdef LDAP_DEBUG 295 ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, 296 LBER_SBIOD_LEVEL_PROVIDER, (void *)"udp_" ); 297 #endif 298 ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_udp, 299 LBER_SBIOD_LEVEL_PROVIDER, NULL ); 300 ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_readahead, 301 LBER_SBIOD_LEVEL_PROVIDER, NULL ); 302 break; 303 #endif /* LDAP_CONNECTIONLESS */ 304 305 case LDAP_PROTO_IPC: 306 #ifdef LDAP_DEBUG 307 ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, 308 LBER_SBIOD_LEVEL_PROVIDER, (void *)"ipc_" ); 309 #endif 310 ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_fd, 311 LBER_SBIOD_LEVEL_PROVIDER, NULL ); 312 break; 313 314 case LDAP_PROTO_EXT: 315 /* caller must supply sockbuf handlers */ 316 break; 317 318 default: 319 ldap_unbind_ext( ld, NULL, NULL ); 320 return LDAP_PARAM_ERROR; 321 } 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 /* Add the connection to the *LDAP's select pool */ 329 ldap_mark_select_read( ld, conn->lconn_sb ); 330 ldap_mark_select_write( ld, conn->lconn_sb ); 331 332 *ldp = ld; 333 return LDAP_SUCCESS; 334 } 335 336 int 337 ldap_int_open_connection( 338 LDAP *ld, 339 LDAPConn *conn, 340 LDAPURLDesc *srv, 341 int async ) 342 { 343 int rc = -1; 344 int proto; 345 346 Debug( LDAP_DEBUG_TRACE, "ldap_int_open_connection\n", 0, 0, 0 ); 347 348 switch ( proto = ldap_pvt_url_scheme2proto( srv->lud_scheme ) ) { 349 case LDAP_PROTO_TCP: 350 rc = ldap_connect_to_host( ld, conn->lconn_sb, 351 proto, srv, async ); 352 353 if ( rc == -1 ) return rc; 354 #ifdef LDAP_DEBUG 355 ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, 356 LBER_SBIOD_LEVEL_PROVIDER, (void *)"tcp_" ); 357 #endif 358 ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_tcp, 359 LBER_SBIOD_LEVEL_PROVIDER, NULL ); 360 361 break; 362 363 #ifdef LDAP_CONNECTIONLESS 364 case LDAP_PROTO_UDP: 365 LDAP_IS_UDP(ld) = 1; 366 rc = ldap_connect_to_host( ld, conn->lconn_sb, 367 proto, srv, async ); 368 369 if ( rc == -1 ) return rc; 370 #ifdef LDAP_DEBUG 371 ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, 372 LBER_SBIOD_LEVEL_PROVIDER, (void *)"udp_" ); 373 #endif 374 ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_udp, 375 LBER_SBIOD_LEVEL_PROVIDER, NULL ); 376 377 ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_readahead, 378 LBER_SBIOD_LEVEL_PROVIDER, NULL ); 379 380 break; 381 #endif 382 case LDAP_PROTO_IPC: 383 #ifdef LDAP_PF_LOCAL 384 /* only IPC mechanism supported is PF_LOCAL (PF_UNIX) */ 385 rc = ldap_connect_to_path( ld, conn->lconn_sb, 386 srv, async ); 387 if ( rc == -1 ) return rc; 388 #ifdef LDAP_DEBUG 389 ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, 390 LBER_SBIOD_LEVEL_PROVIDER, (void *)"ipc_" ); 391 #endif 392 ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_fd, 393 LBER_SBIOD_LEVEL_PROVIDER, NULL ); 394 395 break; 396 #endif /* LDAP_PF_LOCAL */ 397 default: 398 return -1; 399 break; 400 } 401 402 conn->lconn_created = time( NULL ); 403 404 #ifdef LDAP_DEBUG 405 ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, 406 INT_MAX, (void *)"ldap_" ); 407 #endif 408 409 #ifdef LDAP_CONNECTIONLESS 410 if( proto == LDAP_PROTO_UDP ) return 0; 411 #endif 412 413 #ifdef HAVE_TLS 414 if (ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD || 415 strcmp( srv->lud_scheme, "ldaps" ) == 0 ) 416 { 417 ++conn->lconn_refcnt; /* avoid premature free */ 418 419 rc = ldap_int_tls_start( ld, conn, srv ); 420 421 --conn->lconn_refcnt; 422 423 if (rc != LDAP_SUCCESS) { 424 return -1; 425 } 426 } 427 #endif 428 429 return( 0 ); 430 } 431 432 433 int 434 ldap_open_internal_connection( LDAP **ldp, ber_socket_t *fdp ) 435 { 436 int rc; 437 LDAPConn *c; 438 LDAPRequest *lr; 439 440 rc = ldap_create( ldp ); 441 if( rc != LDAP_SUCCESS ) { 442 *ldp = NULL; 443 return( rc ); 444 } 445 446 /* Make it appear that a search request, msgid 0, was sent */ 447 lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest )); 448 if( lr == NULL ) { 449 ldap_unbind_ext( *ldp, NULL, NULL ); 450 *ldp = NULL; 451 return( LDAP_NO_MEMORY ); 452 } 453 memset(lr, 0, sizeof( LDAPRequest )); 454 lr->lr_msgid = 0; 455 lr->lr_status = LDAP_REQST_INPROGRESS; 456 lr->lr_res_errno = LDAP_SUCCESS; 457 /* no mutex lock needed, we just created this ld here */ 458 (*ldp)->ld_requests = lr; 459 460 /* Attach the passed socket as the *LDAP's connection */ 461 c = ldap_new_connection( *ldp, NULL, 1, 0, NULL); 462 if( c == NULL ) { 463 ldap_unbind_ext( *ldp, NULL, NULL ); 464 *ldp = NULL; 465 return( LDAP_NO_MEMORY ); 466 } 467 ber_sockbuf_ctrl( c->lconn_sb, LBER_SB_OPT_SET_FD, fdp ); 468 #ifdef LDAP_DEBUG 469 ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_debug, 470 LBER_SBIOD_LEVEL_PROVIDER, (void *)"int_" ); 471 #endif 472 ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_tcp, 473 LBER_SBIOD_LEVEL_PROVIDER, NULL ); 474 (*ldp)->ld_defconn = c; 475 476 /* Add the connection to the *LDAP's select pool */ 477 ldap_mark_select_read( *ldp, c->lconn_sb ); 478 ldap_mark_select_write( *ldp, c->lconn_sb ); 479 480 /* Make this connection an LDAP V3 protocol connection */ 481 rc = LDAP_VERSION3; 482 ldap_set_option( *ldp, LDAP_OPT_PROTOCOL_VERSION, &rc ); 483 484 return( LDAP_SUCCESS ); 485 } 486