Merge branch 'master' of git://git.samba.org/samba into teventfix
[samba.git] / source4 / libcli / cldap / cldap.c
index 51bab37e97208e99c04a26ea60be4b180242b24e..b18ba12b1fc2ac8a77681bed834c6a1154fa2fcc 100644 (file)
@@ -7,7 +7,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
@@ -16,8 +16,7 @@
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 /*
@@ -34,8 +33,9 @@
 
 #include "includes.h"
 #include "lib/events/events.h"
-#include "lib/util/dlinklist.h"
+#include "../lib/util/dlinklist.h"
 #include "libcli/ldap/ldap.h"
+#include "libcli/ldap/ldap_ndr.h"
 #include "libcli/cldap/cldap.h"
 #include "lib/socket/socket.h"
 #include "libcli/security/security.h"
@@ -108,7 +108,7 @@ static void cldap_socket_recv(struct cldap_socket *cldap)
        }
 
        /* this initial decode is used to find the message id */
-       status = ldap_decode(asn1, ldap_msg);
+       status = ldap_decode(asn1, NULL, ldap_msg);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(2,("Failed to decode ldap message: %s\n", nt_errstr(status)));
                talloc_free(tmp_ctx);
@@ -144,11 +144,11 @@ static void cldap_socket_recv(struct cldap_socket *cldap)
 /*
   handle request timeouts
 */
-static void cldap_request_timeout(struct event_context *event_ctx, 
-                                 struct timed_event *te, struct timeval t,
-                                 void *private)
+static void cldap_request_timeout(struct tevent_context *event_ctx, 
+                                 struct tevent_timer *te, struct timeval t,
+                                 void *private_data)
 {
-       struct cldap_request *req = talloc_get_type(private, struct cldap_request);
+       struct cldap_request *req = talloc_get_type(private_data, struct cldap_request);
 
        /* possibly try again */
        if (req->num_retries != 0) {
@@ -223,10 +223,10 @@ static void cldap_socket_send(struct cldap_socket *cldap)
 /*
   handle fd events on a cldap_socket
 */
-static void cldap_socket_handler(struct event_context *ev, struct fd_event *fde,
-                                uint16_t flags, void *private)
+static void cldap_socket_handler(struct tevent_context *ev, struct tevent_fd *fde,
+                                uint16_t flags, void *private_data)
 {
-       struct cldap_socket *cldap = talloc_get_type(private, struct cldap_socket);
+       struct cldap_socket *cldap = talloc_get_type(private_data, struct cldap_socket);
        if (flags & EVENT_FD_WRITE) {
                cldap_socket_send(cldap);
        } 
@@ -240,7 +240,8 @@ static void cldap_socket_handler(struct event_context *ev, struct fd_event *fde,
   then operations will use that event context
 */
 struct cldap_socket *cldap_socket_init(TALLOC_CTX *mem_ctx, 
-                                      struct event_context *event_ctx)
+                                      struct tevent_context *event_ctx,
+                                      struct smb_iconv_convenience *iconv_convenience)
 {
        struct cldap_socket *cldap;
        NTSTATUS status;
@@ -248,11 +249,7 @@ struct cldap_socket *cldap_socket_init(TALLOC_CTX *mem_ctx,
        cldap = talloc(mem_ctx, struct cldap_socket);
        if (cldap == NULL) goto failed;
 
-       if (event_ctx == NULL) {
-               cldap->event_ctx = event_context_init(cldap);
-       } else {
-               cldap->event_ctx = talloc_reference(cldap, event_ctx);
-       }
+       cldap->event_ctx = talloc_reference(cldap, event_ctx);
        if (cldap->event_ctx == NULL) goto failed;
 
        cldap->idr = idr_init(cldap);
@@ -269,6 +266,7 @@ struct cldap_socket *cldap_socket_init(TALLOC_CTX *mem_ctx,
 
        cldap->send_queue = NULL;
        cldap->incoming.handler = NULL;
+       cldap->iconv_convenience = iconv_convenience;
        
        return cldap;
 
@@ -284,10 +282,10 @@ failed:
 NTSTATUS cldap_set_incoming_handler(struct cldap_socket *cldap,
                                  void (*handler)(struct cldap_socket *, struct ldap_message *, 
                                                  struct socket_address *),
-                                 void *private)
+                                 void *private_data)
 {
        cldap->incoming.handler = handler;
-       cldap->incoming.private = private;
+       cldap->incoming.private_data = private_data;
        EVENT_FD_READABLE(cldap->fde);
        return NT_STATUS_OK;
 }
@@ -309,14 +307,15 @@ struct cldap_request *cldap_search_send(struct cldap_socket *cldap,
        req->state       = CLDAP_REQUEST_SEND;
        req->timeout     = io->in.timeout;
        req->num_retries = io->in.retries;
-       req->is_reply    = False;
+       req->is_reply    = false;
        req->asn1        = asn1_init(req);
        if (!req->asn1) {
                goto failed;
        }
 
        req->dest = socket_address_from_strings(req, cldap->sock->backend_name,
-                                               io->in.dest_address, lp_cldap_port());
+                                               io->in.dest_address, 
+                                               io->in.dest_port);
        if (!req->dest) goto failed;
 
        req->message_id = idr_get_new_random(cldap->idr, req, UINT16_MAX);
@@ -336,7 +335,7 @@ struct cldap_request *cldap_search_send(struct cldap_socket *cldap,
        search->deref          = LDAP_DEREFERENCE_NEVER;
        search->timelimit      = 0;
        search->sizelimit      = 0;
-       search->attributesonly = False;
+       search->attributesonly = false;
        search->num_attributes = str_list_length(io->in.attributes);
        search->attributes     = io->in.attributes;
        search->tree           = ldb_parse_tree(req, io->in.filter);
@@ -344,7 +343,7 @@ struct cldap_request *cldap_search_send(struct cldap_socket *cldap,
                goto failed;
        }
 
-       if (!ldap_encode(msg, &req->encoded, req)) {
+       if (!ldap_encode(msg, NULL, &req->encoded, req)) {
                DEBUG(0,("Failed to encode cldap message to %s:%d\n",
                         req->dest->addr, req->dest->port));
                goto failed;
@@ -377,7 +376,7 @@ NTSTATUS cldap_reply_send(struct cldap_socket *cldap, struct cldap_reply *io)
 
        req->cldap       = cldap;
        req->state       = CLDAP_REQUEST_SEND;
-       req->is_reply    = True;
+       req->is_reply    = true;
        req->asn1        = asn1_init(req);
        if (!req->asn1) {
                goto failed;
@@ -397,7 +396,7 @@ NTSTATUS cldap_reply_send(struct cldap_socket *cldap, struct cldap_reply *io)
                msg->type = LDAP_TAG_SearchResultEntry;
                msg->r.SearchResultEntry = *io->response;
 
-               if (!ldap_encode(msg, &blob1, req)) {
+               if (!ldap_encode(msg, NULL, &blob1, req)) {
                        DEBUG(0,("Failed to encode cldap message to %s:%d\n",
                                 req->dest->addr, req->dest->port));
                        status = NT_STATUS_INVALID_PARAMETER;
@@ -410,7 +409,7 @@ NTSTATUS cldap_reply_send(struct cldap_socket *cldap, struct cldap_reply *io)
        msg->type = LDAP_TAG_SearchResultDone;
        msg->r.SearchResultDone = *io->result;
 
-       if (!ldap_encode(msg, &blob2, req)) {
+       if (!ldap_encode(msg, NULL, &blob2, req)) {
                DEBUG(0,("Failed to encode cldap message to %s:%d\n",
                         req->dest->addr, req->dest->port));
                status = NT_STATUS_INVALID_PARAMETER;
@@ -464,7 +463,7 @@ NTSTATUS cldap_search_recv(struct cldap_request *req,
        ldap_msg = talloc(mem_ctx, struct ldap_message);
        NT_STATUS_HAVE_NO_MEMORY(ldap_msg);
 
-       status = ldap_decode(req->asn1, ldap_msg);
+       status = ldap_decode(req->asn1, NULL, ldap_msg);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(2,("Failed to decode cldap search reply: %s\n", nt_errstr(status)));
                talloc_free(req);
@@ -480,7 +479,7 @@ NTSTATUS cldap_search_recv(struct cldap_request *req,
                *io->out.response = ldap_msg->r.SearchResultEntry;
 
                /* decode the 2nd part */
-               status = ldap_decode(req->asn1, ldap_msg);
+               status = ldap_decode(req->asn1, NULL, ldap_msg);
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(2,("Failed to decode cldap search result entry: %s\n", nt_errstr(status)));
                        talloc_free(req);
@@ -535,26 +534,26 @@ struct cldap_request *cldap_netlogon_send(struct cldap_socket *cldap,
                                 ldap_encode_ndr_uint32(tmp_ctx, io->in.version));
        if (filter == NULL) goto failed;
        if (io->in.user) {
-               filter = talloc_asprintf_append(filter, "(User=%s)", io->in.user);
+               filter = talloc_asprintf_append_buffer(filter, "(User=%s)", io->in.user);
                if (filter == NULL) goto failed;
        }
        if (io->in.host) {
-               filter = talloc_asprintf_append(filter, "(Host=%s)", io->in.host);
+               filter = talloc_asprintf_append_buffer(filter, "(Host=%s)", io->in.host);
                if (filter == NULL) goto failed;
        }
        if (io->in.realm) {
-               filter = talloc_asprintf_append(filter, "(DnsDomain=%s)", io->in.realm);
+               filter = talloc_asprintf_append_buffer(filter, "(DnsDomain=%s)", io->in.realm);
                if (filter == NULL) goto failed;
        }
        if (io->in.acct_control != -1) {
-               filter = talloc_asprintf_append(filter, "(AAC=%s)", 
+               filter = talloc_asprintf_append_buffer(filter, "(AAC=%s)", 
                                                ldap_encode_ndr_uint32(tmp_ctx, io->in.acct_control));
                if (filter == NULL) goto failed;
        }
        if (io->in.domain_sid) {
                struct dom_sid *sid = dom_sid_parse_talloc(tmp_ctx, io->in.domain_sid);
                if (sid == NULL) goto failed;
-               filter = talloc_asprintf_append(filter, "(domainSid=%s)",
+               filter = talloc_asprintf_append_buffer(filter, "(domainSid=%s)",
                                                ldap_encode_ndr_dom_sid(tmp_ctx, sid));
                if (filter == NULL) goto failed;
        }
@@ -563,14 +562,15 @@ struct cldap_request *cldap_netlogon_send(struct cldap_socket *cldap,
                NTSTATUS status;
                status = GUID_from_string(io->in.domain_guid, &guid);
                if (!NT_STATUS_IS_OK(status)) goto failed;
-               filter = talloc_asprintf_append(filter, "(DomainGuid=%s)",
+               filter = talloc_asprintf_append_buffer(filter, "(DomainGuid=%s)",
                                                ldap_encode_ndr_GUID(tmp_ctx, &guid));
                if (filter == NULL) goto failed;
        }
-       filter = talloc_asprintf_append(filter, ")");
+       filter = talloc_asprintf_append_buffer(filter, ")");
        if (filter == NULL) goto failed;
 
        search.in.dest_address = io->in.dest_address;
+       search.in.dest_port    = io->in.dest_port;
        search.in.filter       = filter;
        search.in.attributes   = attr;
        search.in.timeout      = 2;
@@ -595,8 +595,11 @@ NTSTATUS cldap_netlogon_recv(struct cldap_request *req,
 {
        NTSTATUS status;
        struct cldap_search search;
+       struct cldap_socket *cldap;
        DATA_BLOB *data;
 
+       cldap = req->cldap;
+
        status = cldap_search_recv(req, mem_ctx, &search);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
@@ -613,16 +616,16 @@ NTSTATUS cldap_netlogon_recv(struct cldap_request *req,
        }
        data = search.out.response->attributes[0].values;
 
-       status = ndr_pull_union_blob(data, mem_ctx, &io->out.netlogon, 
-                                    io->in.version & 0xF,
-                                    (ndr_pull_flags_fn_t)ndr_pull_nbt_cldap_netlogon);
+       status = pull_netlogon_samlogon_response(data, mem_ctx, req->cldap->iconv_convenience,
+                                                &io->out.netlogon);
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(2,("cldap failed to parse netlogon response of type 0x%02x\n",
-                        SVAL(data->data, 0)));
-               dump_data(10, data->data, data->length);
+               return status;
        }
-
-       return status;
+       
+       if (io->in.map_response) {
+               map_netlogon_samlogon_response(&io->out.netlogon);
+       }
+       return NT_STATUS_OK;
 }
 
 /*
@@ -696,7 +699,7 @@ NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap,
                              uint32_t message_id,
                              struct socket_address *src,
                              uint32_t version,
-                             union nbt_cldap_netlogon *netlogon)
+                             struct netlogon_samlogon_response *netlogon)
 {
        NTSTATUS status;
        struct cldap_reply reply;
@@ -705,13 +708,11 @@ NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap,
        TALLOC_CTX *tmp_ctx = talloc_new(cldap);
        DATA_BLOB blob;
 
-       status = ndr_push_union_blob(&blob, tmp_ctx, netlogon, version & 0xF, 
-                                    (ndr_push_flags_fn_t)ndr_push_nbt_cldap_netlogon);
+       status = push_netlogon_samlogon_response(&blob, tmp_ctx, cldap->iconv_convenience,
+                                                netlogon);
        if (!NT_STATUS_IS_OK(status)) {
-               talloc_free(tmp_ctx);
                return status;
        }
-
        reply.messageid    = message_id;
        reply.dest         = src;
        reply.response     = &response;