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 } 509