r7810: don't give errors when the ldap server sends us reference replies
[bbaumbach/samba-autobuild/.git] / source4 / libcli / ldap / ldap_client.c
index f2b09e89e326c7a42aa53a998767c93af2c2f130..a8463f78724202289c0c71580ee4190d2370b977 100644 (file)
@@ -28,6 +28,7 @@
 #include "dlinklist.h"
 #include "lib/events/events.h"
 #include "lib/socket/socket.h"
+#include "lib/tls/tls.h"
 #include "libcli/ldap/ldap.h"
 #include "libcli/ldap/ldap_client.h"
 
@@ -90,8 +91,8 @@ static void ldap_connection_dead(struct ldap_connection *conn)
                }
        }
 
-       talloc_free(conn->sock);
-       conn->sock = NULL;
+       talloc_free(conn->tls);
+       conn->tls = NULL;
 }
 
 
@@ -129,7 +130,8 @@ static void ldap_match_message(struct ldap_connection *conn, struct ldap_message
        req->replies[req->num_replies] = talloc_steal(req->replies, msg);
        req->num_replies++;
 
-       if (msg->type != LDAP_TAG_SearchResultEntry) {
+       if (msg->type != LDAP_TAG_SearchResultEntry &&
+           msg->type != LDAP_TAG_SearchResultReference) {
                /* currently only search results expect multiple
                   replies */
                req->state = LDAP_REQUEST_DONE;
@@ -156,6 +158,8 @@ static void ldap_try_decode_plain(struct ldap_connection *conn)
        /* try and decode - this will fail if we don't have a full packet yet */
        while (asn1.ofs < asn1.length) {
                struct ldap_message *msg = talloc(conn, struct ldap_message);
+               off_t saved_ofs = asn1.ofs;
+                       
                if (msg == NULL) {
                        ldap_connection_dead(conn);
                        return;
@@ -164,6 +168,7 @@ static void ldap_try_decode_plain(struct ldap_connection *conn)
                if (ldap_decode(&asn1, msg)) {
                        ldap_match_message(conn, msg);
                } else {
+                       asn1.ofs = saved_ofs;
                        talloc_free(msg);
                        break;
                }
@@ -171,7 +176,7 @@ static void ldap_try_decode_plain(struct ldap_connection *conn)
 
        /* keep any remaining data in conn->partial */
        data_blob_free(&conn->partial);
-       if (asn1.ofs != conn->partial.length) {
+       if (asn1.ofs != asn1.length) {
                conn->partial = data_blob_talloc(conn, 
                                                 asn1.data + asn1.ofs, 
                                                 asn1.length - asn1.ofs);
@@ -241,7 +246,7 @@ static void ldap_recv_handler(struct ldap_connection *conn)
        size_t npending=0, nread;
 
        /* work out how much data is pending */
-       status = socket_pending(conn->sock, &npending);
+       status = tls_socket_pending(conn->tls, &npending);
        if (!NT_STATUS_IS_OK(status) || npending == 0) {
                ldap_connection_dead(conn);
                return;
@@ -255,8 +260,8 @@ static void ldap_recv_handler(struct ldap_connection *conn)
        }
 
        /* receive the pending data */
-       status = socket_recv(conn->sock, conn->partial.data + conn->partial.length,
-                            npending, &nread, 0);
+       status = tls_socket_recv(conn->tls, conn->partial.data + conn->partial.length,
+                                npending, &nread);
        if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
                return;
        }
@@ -285,7 +290,7 @@ static void ldap_send_handler(struct ldap_connection *conn)
                size_t nsent;
                NTSTATUS status;
 
-               status = socket_send(conn->sock, &req->data, &nsent, 0);
+               status = tls_socket_send(conn->tls, &req->data, &nsent);
                if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
                        break;
                }
@@ -328,7 +333,7 @@ static void ldap_io_handler(struct event_context *ev, struct fd_event *fde,
        struct ldap_connection *conn = talloc_get_type(private, struct ldap_connection);
        if (flags & EVENT_FD_WRITE) {
                ldap_send_handler(conn);
-               if (conn->sock == NULL) return;
+               if (conn->tls == NULL) return;
        }
        if (flags & EVENT_FD_READ) {
                ldap_recv_handler(conn);
@@ -413,6 +418,14 @@ NTSTATUS ldap_connect(struct ldap_connection *conn, const char *url)
                return NT_STATUS_INTERNAL_ERROR;
        }
 
+       conn->tls = tls_init_client(conn->sock, conn->event.fde, conn->ldaps);
+       if (conn->tls == NULL) {
+               talloc_free(conn->sock);
+               return NT_STATUS_INTERNAL_ERROR;
+       }
+       talloc_steal(conn, conn->tls);
+       talloc_steal(conn->tls, conn->sock);
+
        return NT_STATUS_OK;
 }
 
@@ -457,7 +470,7 @@ struct ldap_request *ldap_request_send(struct ldap_connection *conn,
 {
        struct ldap_request *req;
 
-       if (conn->sock == NULL) {
+       if (conn->tls == NULL) {
                return NULL;
        }