static CURLcode ldap_setup_connection(struct connectdata *conn) { ldapconninfo *li; LDAPURLDesc *lud; struct SessionHandle *data=conn->data; int rc, proto; CURLcode status; rc = ldap_url_parse(data->change.url, &lud); if(rc != LDAP_URL_SUCCESS) { const char *msg = "url parsing problem"; status = CURLE_URL_MALFORMAT; if(rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) { if(rc == LDAP_URL_ERR_MEM) status = CURLE_OUT_OF_MEMORY; msg = url_errs[rc]; } failf(conn->data, "LDAP local: %s", msg); return status; } proto = ldap_pvt_url_scheme2proto(lud->lud_scheme); ldap_free_urldesc(lud); li = calloc(1, sizeof(ldapconninfo)); if(!li) return CURLE_OUT_OF_MEMORY; li->proto = proto; conn->proto.generic = li; connkeep(conn, "OpenLDAP default"); /* TODO: * - provide option to choose SASL Binds instead of Simple */ return CURLE_OK; }
int ldap_int_open_connection( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv, int async ) { int rc = -1; char *host; int port, proto; Debug( LDAP_DEBUG_TRACE, "ldap_int_open_connection\n", 0, 0, 0 ); switch ( proto = ldap_pvt_url_scheme2proto( srv->lud_scheme ) ) { case LDAP_PROTO_TCP: port = srv->lud_port; if ( srv->lud_host == NULL || *srv->lud_host == 0 ) { host = NULL; } else { host = srv->lud_host; } if( !port ) { if( strcmp(srv->lud_scheme, "ldaps") == 0 ) { port = LDAPS_PORT; } else { port = LDAP_PORT; } } rc = ldap_connect_to_host( ld, conn->lconn_sb, proto, host, port, async ); if ( rc == -1 ) return rc; #ifdef LDAP_DEBUG ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, LBER_SBIOD_LEVEL_PROVIDER, (void *)"tcp_" ); #endif ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_tcp, LBER_SBIOD_LEVEL_PROVIDER, NULL ); break; #ifdef LDAP_CONNECTIONLESS case LDAP_PROTO_UDP: port = srv->lud_port; if ( srv->lud_host == NULL || *srv->lud_host == 0 ) { host = NULL; } else { host = srv->lud_host; } if( !port ) port = LDAP_PORT; LDAP_IS_UDP(ld) = 1; rc = ldap_connect_to_host( ld, conn->lconn_sb, proto, host, port, async ); if ( rc == -1 ) return rc; #ifdef LDAP_DEBUG ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, LBER_SBIOD_LEVEL_PROVIDER, (void *)"udp_" ); #endif ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_udp, LBER_SBIOD_LEVEL_PROVIDER, NULL ); ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_readahead, LBER_SBIOD_LEVEL_PROVIDER, NULL ); break; #endif case LDAP_PROTO_IPC: #ifdef LDAP_PF_LOCAL /* only IPC mechanism supported is PF_LOCAL (PF_UNIX) */ rc = ldap_connect_to_path( ld, conn->lconn_sb, srv->lud_host, async ); if ( rc == -1 ) return rc; #ifdef LDAP_DEBUG ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, LBER_SBIOD_LEVEL_PROVIDER, (void *)"ipc_" ); #endif ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_fd, LBER_SBIOD_LEVEL_PROVIDER, NULL ); break; #endif /* LDAP_PF_LOCAL */ default: return -1; break; } conn->lconn_created = time( NULL ); #ifdef LDAP_DEBUG ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, INT_MAX, (void *)"ldap_" ); #endif #ifdef LDAP_CONNECTIONLESS if( proto == LDAP_PROTO_UDP ) return 0; #endif #ifdef HAVE_TLS if (ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD || strcmp( srv->lud_scheme, "ldaps" ) == 0 ) { ++conn->lconn_refcnt; /* avoid premature free */ rc = ldap_int_tls_start( ld, conn, srv ); --conn->lconn_refcnt; if (rc != LDAP_SUCCESS) { return -1; } } #endif return( 0 ); }
static int slap_open_listener( const char* url, int *listeners, int *cur ) { int num, tmp, rc; Listener l; Listener *li; LDAPURLDesc *lud; unsigned short port; int err, addrlen = 0; struct sockaddr **sal, **psal; int socktype = SOCK_STREAM; /* default to COTS */ #if defined(LDAP_PF_LOCAL) || defined(SLAP_X_LISTENER_MOD) /* * use safe defaults */ int crit = 1; #endif /* LDAP_PF_LOCAL || SLAP_X_LISTENER_MOD */ rc = ldap_url_parse( url, &lud ); if( rc != LDAP_URL_SUCCESS ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, ERR, "slap_open_listener: listen URL \"%s\" parse error %d\n", url, rc , 0 ); #else Debug( LDAP_DEBUG_ANY, "daemon: listen URL \"%s\" parse error=%d\n", url, rc, 0 ); #endif return rc; } l.sl_url.bv_val = NULL; l.sl_is_mute = 0; #ifndef HAVE_TLS if( ldap_pvt_url_scheme2tls( lud->lud_scheme ) ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, INFO, "slap_open_listener: TLS is not supported (%s)\n", url, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "daemon: TLS not supported (%s)\n", url, 0, 0 ); #endif ldap_free_urldesc( lud ); return -1; } if(! lud->lud_port ) { lud->lud_port = LDAP_PORT; } #else l.sl_is_tls = ldap_pvt_url_scheme2tls( lud->lud_scheme ); if(! lud->lud_port ) { lud->lud_port = l.sl_is_tls ? LDAPS_PORT : LDAP_PORT; } #endif port = (unsigned short) lud->lud_port; tmp = ldap_pvt_url_scheme2proto(lud->lud_scheme); if ( tmp == LDAP_PROTO_IPC ) { #ifdef LDAP_PF_LOCAL if ( lud->lud_host == NULL || lud->lud_host[0] == '\0' ) { err = slap_get_listener_addresses(LDAPI_SOCK, 0, &sal); } else { err = slap_get_listener_addresses(lud->lud_host, 0, &sal); } #else #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, INFO, "slap_open_listener: URL scheme is not supported: %s\n", url, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "daemon: URL scheme not supported: %s", url, 0, 0); #endif ldap_free_urldesc( lud ); return -1; #endif } else { if( lud->lud_host == NULL || lud->lud_host[0] == '\0' || strcmp(lud->lud_host, "*") == 0 ) { err = slap_get_listener_addresses(NULL, port, &sal); } else { err = slap_get_listener_addresses(lud->lud_host, port, &sal); } } #ifdef LDAP_CONNECTIONLESS l.sl_is_udp = ( tmp == LDAP_PROTO_UDP ); #endif #if defined(LDAP_PF_LOCAL) || defined(SLAP_X_LISTENER_MOD) if ( lud->lud_exts ) { err = get_url_perms( lud->lud_exts, &l.sl_perms, &crit ); } else { l.sl_perms = S_IRWXU; } #endif /* LDAP_PF_LOCAL || SLAP_X_LISTENER_MOD */ ldap_free_urldesc( lud ); if ( err ) { return -1; } /* If we got more than one address returned, we need to make space * for it in the slap_listeners array. */ for ( num=0; sal[num]; num++ ); if ( num > 1 ) { *listeners += num-1; slap_listeners = ch_realloc( slap_listeners, (*listeners + 1) * sizeof(Listener *) ); } psal = sal; while ( *sal != NULL ) { switch( (*sal)->sa_family ) { case AF_INET: #ifdef LDAP_PF_INET6 case AF_INET6: #endif #ifdef LDAP_PF_LOCAL case AF_LOCAL: #endif break; default: sal++; continue; } #ifdef LDAP_CONNECTIONLESS if( l.sl_is_udp ) socktype = SOCK_DGRAM; #endif l.sl_sd = socket( (*sal)->sa_family, socktype, 0); if ( l.sl_sd == AC_SOCKET_INVALID ) { int err = sock_errno(); #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, ERR, "slap_open_listener: socket() failed errno=%d (%s)\n", err, sock_errstr(err), 0 ); #else Debug( LDAP_DEBUG_ANY, "daemon: socket() failed errno=%d (%s)\n", err, sock_errstr(err), 0 ); #endif sal++; continue; } #ifndef HAVE_WINSOCK if ( l.sl_sd >= dtblsize ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, ERR, "slap_open_listener: listener descriptor %ld is too " "great %ld\n", (long)l.sl_sd, (long)dtblsize, 0 ); #else Debug( LDAP_DEBUG_ANY, "daemon: listener descriptor %ld is too great %ld\n", (long) l.sl_sd, (long) dtblsize, 0 ); #endif tcp_close( l.sl_sd ); sal++; continue; } #endif #ifdef LDAP_PF_LOCAL if ( (*sal)->sa_family == AF_LOCAL ) { unlink ( ((struct sockaddr_un *)*sal)->sun_path ); } else #endif { #ifdef SO_REUSEADDR /* enable address reuse */ tmp = 1; rc = setsockopt( l.sl_sd, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp, sizeof(tmp) ); if ( rc == AC_SOCKET_ERROR ) { int err = sock_errno(); #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, INFO, "slap_open_listener: setsockopt( %ld, SO_REUSEADDR ) " "failed errno %d (%s)\n", (long)l.sl_sd, err, sock_errstr(err) ); #else Debug( LDAP_DEBUG_ANY, "slapd(%ld): setsockopt(SO_REUSEADDR) failed errno=%d (%s)\n", (long) l.sl_sd, err, sock_errstr(err) ); #endif } #endif } switch( (*sal)->sa_family ) { case AF_INET: addrlen = sizeof(struct sockaddr_in); break; #ifdef LDAP_PF_INET6 case AF_INET6: #ifdef IPV6_V6ONLY /* Try to use IPv6 sockets for IPv6 only */ tmp = 1; rc = setsockopt( l.sl_sd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &tmp, sizeof(tmp) ); if ( rc == AC_SOCKET_ERROR ) { int err = sock_errno(); #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, INFO, "slap_open_listener: setsockopt( %ld, IPV6_V6ONLY ) failed errno %d (%s)\n", (long)l.sl_sd, err, sock_errstr(err) ); #else Debug( LDAP_DEBUG_ANY, "slapd(%ld): setsockopt(IPV6_V6ONLY) failed errno=%d (%s)\n", (long) l.sl_sd, err, sock_errstr(err) ); #endif } #endif addrlen = sizeof(struct sockaddr_in6); break; #endif #ifdef LDAP_PF_LOCAL case AF_LOCAL: addrlen = sizeof(struct sockaddr_un); break; #endif } if (bind(l.sl_sd, *sal, addrlen)) { err = sock_errno(); #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, INFO, "slap_open_listener: bind(%ld) failed errno=%d (%s)\n", (long)l.sl_sd, err, sock_errstr(err) ); #else Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed errno=%d (%s)\n", (long) l.sl_sd, err, sock_errstr(err) ); #endif tcp_close( l.sl_sd ); sal++; continue; } switch ( (*sal)->sa_family ) { #ifdef LDAP_PF_LOCAL case AF_LOCAL: { char *addr = ((struct sockaddr_un *)*sal)->sun_path; if ( chmod( addr, l.sl_perms ) < 0 && crit ) { int err = sock_errno(); #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, INFO, "slap_open_listener: fchmod(%ld) failed errno=%d (%s)\n", (long)l.sl_sd, err, sock_errstr(err) ); #else Debug( LDAP_DEBUG_ANY, "daemon: fchmod(%ld) failed errno=%d (%s)", (long) l.sl_sd, err, sock_errstr(err) ); #endif tcp_close( l.sl_sd ); slap_free_listener_addresses(psal); return -1; } l.sl_name.bv_len = strlen(addr) + sizeof("PATH=") - 1; l.sl_name.bv_val = ber_memalloc( l.sl_name.bv_len + 1 ); snprintf( l.sl_name.bv_val, l.sl_name.bv_len + 1, "PATH=%s", addr ); } break; #endif /* LDAP_PF_LOCAL */ case AF_INET: { char *s; #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP ) char addr[INET_ADDRSTRLEN]; inet_ntop( AF_INET, &((struct sockaddr_in *)*sal)->sin_addr, addr, sizeof(addr) ); s = addr; #else s = inet_ntoa( ((struct sockaddr_in *) *sal)->sin_addr ); #endif port = ntohs( ((struct sockaddr_in *)*sal) ->sin_port ); l.sl_name.bv_val = ber_memalloc( sizeof("IP=255.255.255.255:65535") ); snprintf( l.sl_name.bv_val, sizeof("IP=255.255.255.255:65535"), "IP=%s:%d", s != NULL ? s : SLAP_STRING_UNKNOWN, port ); l.sl_name.bv_len = strlen( l.sl_name.bv_val ); } break; #ifdef LDAP_PF_INET6 case AF_INET6: { char addr[INET6_ADDRSTRLEN]; inet_ntop( AF_INET6, &((struct sockaddr_in6 *)*sal)->sin6_addr, addr, sizeof addr); port = ntohs( ((struct sockaddr_in6 *)*sal)->sin6_port ); l.sl_name.bv_len = strlen(addr) + sizeof("IP= 65535"); l.sl_name.bv_val = ber_memalloc( l.sl_name.bv_len ); snprintf( l.sl_name.bv_val, l.sl_name.bv_len, "IP=%s %d", addr, port ); l.sl_name.bv_len = strlen( l.sl_name.bv_val ); } break; #endif /* LDAP_PF_INET6 */ default: #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, INFO, "slap_open_listener: unsupported address family (%d)\n", (int)(*sal)->sa_family, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "daemon: unsupported address family (%d)\n", (int) (*sal)->sa_family, 0, 0 ); #endif break; } AC_MEMCPY(&l.sl_sa, *sal, addrlen); ber_str2bv( url, 0, 1, &l.sl_url); li = ch_malloc( sizeof( Listener ) ); *li = l; slap_listeners[*cur] = li; (*cur)++; sal++; } /* while ( *sal != NULL ) */ slap_free_listener_addresses(psal); if ( l.sl_url.bv_val == NULL ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, RESULTS, "slap_open_listener: failed on %s\n", url, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "slap_open_listener: failed on %s\n", url, 0, 0 ); #endif return -1; } #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, RESULTS, "slap_open_listener: daemon initialized %s\n", l.sl_url.bv_val, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "daemon: initialized %s\n", l.sl_url.bv_val, 0, 0 ); #endif return 0; }