s3-libads: Use ldap_init_fd() to connect to AD server in socket_wrapper
authorAndrew Bartlett <abartlet@samba.org>
Tue, 26 Apr 2011 03:53:45 +0000 (13:53 +1000)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 28 Apr 2011 03:30:21 +0000 (05:30 +0200)
This means that we control the connection setup, don't rely on signals
for timeouts and the connection uses socket_wrapper where that is
required in our test environment.

According to bug reports, this method is also used by curl and other
tools, so we are not the first to (ab)use the OpenLDAP libs in this
way.

It is ONLY enabled for socket_wrapper at this time, as this is the
best way to get 'make test' working for S3 winbind tests in an S4
domain.

Andrew Bartlett

source3/include/smb_ldap.h
source3/libads/ldap.c
source3/winbindd/winbindd_msrpc.c
source3/wscript

index 45e586859dbd2aee051bda0136e43c69e85065ef..7165de19bf3bbd720613dce9c589a45cffc4fcbe 100644 (file)
@@ -37,7 +37,14 @@ typedef int ber_int_t;
 #endif
 
 /* function declarations not included in proto.h */
-LDAP *ldap_open_with_timeout(const char *server, int port, unsigned int to);
+LDAP *ldap_open_with_timeout(const char *server,
+                            struct sockaddr_storage *ss,
+                            int port, unsigned int to);
+
+#ifdef HAVE_LDAP_PVT_H
+#include <ldap_pvt.h>
+#endif
+int ldap_init_fd(ber_socket_t fd, int proto, char *uri, LDAP **ldp);
 
 #endif /* HAVE_LDAP_H */
 
index 793b689361a8354861fe9a3985e33f459ff44690..eff851047ec0a5a7f16a9bb5ea097a4762e422a1 100644 (file)
@@ -59,14 +59,47 @@ static void gotalarm_sig(int signum)
        gotalarm = 1;
 }
 
- LDAP *ldap_open_with_timeout(const char *server, int port, unsigned int to)
+ LDAP *ldap_open_with_timeout(const char *server,
+                             struct sockaddr_storage *ss,
+                             int port, unsigned int to)
 {
        LDAP *ldp = NULL;
 
+       int fd, ldap_err;
+       NTSTATUS status;
+       char *uri;
 
        DEBUG(10, ("Opening connection to LDAP server '%s:%d', timeout "
                   "%u seconds\n", server, port, to));
 
+#if defined(HAVE_LDAP_INIT_FD) && defined(SOCKET_WRAPPER)
+       /* Only use this private LDAP function if we are in make test,
+        * as this is the best way to get the emulated TCP socket into
+        * OpenLDAP */
+       if (socket_wrapper_dir() != NULL) {
+               status = open_socket_out(ss, port, to, &fd);
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       return NULL;
+               }
+
+#ifndef LDAP_PROTO_TCP
+#define LDAP_PROTO_TCP 1
+#endif
+               uri = talloc_asprintf(talloc_tos(), "ldap://%s:%u", server, port);
+               if (uri == NULL) {
+                       return NULL;
+               }
+               ldap_err = ldap_init_fd(fd, LDAP_PROTO_TCP, uri, &ldp);
+               talloc_free(uri);
+
+               if (ldap_err != LDAP_SUCCESS) {
+                       return NULL;
+               }
+               return ldp;
+       }
+#endif
+
        /* Setup timeout */
        gotalarm = 0;
        CatchSignal(SIGALRM, gotalarm_sig);
@@ -655,6 +688,7 @@ got_connection:
        /* Otherwise setup the TCP LDAP session */
 
        ads->ldap.ld = ldap_open_with_timeout(ads->config.ldap_server_name,
+                                             &ads->ldap.ss,
                                              ads->ldap.port, lp_ldap_timeout());
        if (ads->ldap.ld == NULL) {
                status = ADS_ERROR(LDAP_OPERATIONS_ERROR);
index 921cdb5a8bc3cd36076df396e8765a36d2f0bb0b..1f8b398fd00ad03a7b2c10a97016164147f15d97 100644 (file)
@@ -762,7 +762,7 @@ static NTSTATUS msrpc_lookup_groupmem(struct winbindd_domain *domain,
 
 #include <ldap.h>
 
-static int get_ldap_seq(const char *server, int port, uint32 *seq)
+static int get_ldap_seq(const char *server, struct sockaddr_storage *ss, int port, uint32 *seq)
 {
        int ret = -1;
        struct timeval to;
@@ -778,7 +778,7 @@ static int get_ldap_seq(const char *server, int port, uint32 *seq)
         * search timeout doesn't seem to apply to doing an open as well. JRA.
         */
 
-       ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
+       ldp = ldap_open_with_timeout(server, ss, port, lp_ldap_timeout());
        if (ldp == NULL)
                return -1;
 
@@ -822,7 +822,7 @@ static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
        char addr[INET6_ADDRSTRLEN];
 
        print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
-       if ((ret = get_ldap_seq(addr, LDAP_PORT, seq)) == 0) {
+       if ((ret = get_ldap_seq(addr, &domain->dcaddr, LDAP_PORT, seq)) == 0) {
                DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
                          "number for Domain (%s) from DC (%s)\n",
                        domain->name, addr));
index 7f178a4c55d2bfdb4aef032cdaebb647560923de..175bbf12ef956e53dcce93241f1d2f49028317d3 100644 (file)
@@ -574,7 +574,7 @@ msg.msg_acctrightslen = sizeof(fd);
 
     # Check for LDAP
     if Options.options.with_ldap:
-        conf.CHECK_HEADERS('ldap.h lber.h')
+        conf.CHECK_HEADERS('ldap.h lber.h ldap_pvt.h')
         conf.CHECK_TYPE('ber_tag_t', 'unsigned int', headers='ldap.h lber.h')
         conf.CHECK_FUNCS_IN('ber_scanf ber_sockbuf_add_io', 'lber')
         conf.CHECK_VARIABLE('LDAP_OPT_SOCKBUF', headers='ldap.h')
@@ -584,7 +584,7 @@ msg.msg_acctrightslen = sizeof(fd);
         conf.CHECK_VARIABLE('LBER_OPT_LOG_PRINT_FN',
                             define='HAVE_LBER_LOG_PRINT_FN', headers='lber.h')
 
-        conf.CHECK_FUNCS_IN('ldap_init ldap_initialize ldap_set_rebind_proc', 'ldap')
+        conf.CHECK_FUNCS_IN('ldap_init ldap_init_fd ldap_initialize ldap_set_rebind_proc', 'ldap')
         conf.CHECK_FUNCS_IN('ldap_add_result_entry', 'ldap')
 
         # Check if ldap_set_rebind_proc() takes three arguments