s4-libnet: force IDL printing for high debug levels
[kai/samba.git] / source4 / libnet / libnet_rpc.c
index 28cbba2933e87ebd55f6e3cd1af40f235e149caf..fbf002f2ed9cfe86c3d144989d2be2a0365a3429 100644 (file)
@@ -22,7 +22,6 @@
 #include "libnet/libnet.h"
 #include "libcli/libcli.h"
 #include "libcli/composite/composite.h"
-#include "librpc/rpc/dcerpc.h"
 #include "librpc/rpc/dcerpc_proto.h"
 #include "librpc/gen_ndr/ndr_lsa_c.h"
 #include "librpc/gen_ndr/ndr_samr.h"
@@ -106,8 +105,18 @@ static struct composite_context* libnet_RpcConnectSrv_send(struct libnet_context
                return c;
        }
 
+       switch (r->level) {
+       case LIBNET_RPC_CONNECT_SERVER:
+       case LIBNET_RPC_CONNECT_SERVER_ADDRESS:
+               b->flags = r->in.dcerpc_flags;
+       }
+
+       if (DEBUGLEVEL >= 10) {
+               b->flags |= DCERPC_DEBUG_PRINT_BOTH;
+       }
+
        if (r->level == LIBNET_RPC_CONNECT_SERVER_ADDRESS) {
-               b->target_hostname = talloc_reference(b, r->in.name);
+               b->target_hostname = talloc_strdup(b, r->in.name);
                if (composite_nomem(b->target_hostname, c)) {
                        return c;
                }
@@ -218,7 +227,7 @@ struct rpc_connect_dc_state {
 };
 
 
-static void continue_lookup_dc(struct composite_context *ctx);
+static void continue_lookup_dc(struct tevent_req *req);
 static void continue_rpc_connect(struct composite_context *ctx);
 
 
@@ -238,7 +247,7 @@ static struct composite_context* libnet_RpcConnectDC_send(struct libnet_context
 {
        struct composite_context *c;
        struct rpc_connect_dc_state *s;
-       struct composite_context *lookup_dc_req;
+       struct tevent_req *lookup_dc_req;
 
        /* composite context allocation and setup */
        c = composite_create(ctx, ctx->event_ctx);
@@ -275,7 +284,7 @@ static struct composite_context* libnet_RpcConnectDC_send(struct libnet_context
        lookup_dc_req = libnet_LookupDCs_send(ctx, c, &s->f);
        if (composite_nomem(lookup_dc_req, c)) return c;
 
-       composite_continue(c, lookup_dc_req, continue_lookup_dc, c);
+       tevent_req_set_callback(lookup_dc_req, continue_lookup_dc, c);
        return c;
 }
 
@@ -284,19 +293,19 @@ static struct composite_context* libnet_RpcConnectDC_send(struct libnet_context
   Step 2 of RpcConnectDC: get domain controller name and
   initiate RpcConnect to it
 */
-static void continue_lookup_dc(struct composite_context *ctx)
+static void continue_lookup_dc(struct tevent_req *req)
 {
        struct composite_context *c;
        struct rpc_connect_dc_state *s;
        struct composite_context *rpc_connect_req;
        struct monitor_msg msg;
        struct msg_net_lookup_dc data;
-       
-       c = talloc_get_type(ctx->async.private_data, struct composite_context);
-       s = talloc_get_type(c->private_data, struct rpc_connect_dc_state);
+
+       c = tevent_req_callback_data(req, struct composite_context);
+       s = talloc_get_type_abort(c->private_data, struct rpc_connect_dc_state);
        
        /* receive result of domain controller lookup */
-       c->status = libnet_LookupDCs_recv(ctx, c, &s->f);
+       c->status = libnet_LookupDCs_recv(req, c, &s->f);
        if (!composite_is_ok(c)) return;
 
        /* decide on preferred address type depending on DC type */
@@ -323,6 +332,7 @@ static void continue_lookup_dc(struct composite_context *ctx)
        s->r2.in.name          = talloc_strdup(s, s->connect_name);
        s->r2.in.address       = talloc_steal(s, s->f.out.dcs[0].address);
        s->r2.in.dcerpc_iface  = s->r.in.dcerpc_iface;  
+       s->r2.in.dcerpc_flags  = s->r.in.dcerpc_flags;
 
        /* send rpc connect request to the server */
        rpc_connect_req = libnet_RpcConnectSrv_send(s->ctx, c, &s->r2, s->monitor_fn);
@@ -393,8 +403,17 @@ static NTSTATUS libnet_RpcConnectDC_recv(struct composite_context *c,
 
        status = composite_wait(c);
        if (NT_STATUS_IS_OK(status)) {
-               /* move connected rpc pipe between memory contexts */
-               r->out.dcerpc_pipe = talloc_steal(mem_ctx, s->r.out.dcerpc_pipe);
+               /* move connected rpc pipe between memory contexts 
+                  
+                  The use of talloc_reparent(talloc_parent(), ...) is
+                  bizarre, but it is needed because of the absolutely
+                  atrocious use of talloc in this code. We need to
+                  force the original parent to change, but finding
+                  the original parent is well nigh impossible at this
+                  point in the code (yes, I tried).
+                */
+               r->out.dcerpc_pipe = talloc_reparent(talloc_parent(s->r.out.dcerpc_pipe), 
+                                                    mem_ctx, s->r.out.dcerpc_pipe);
 
                /* reference created pipe structure to long-term libnet_context
                   so that it can be used by other api functions even after short-term
@@ -438,9 +457,9 @@ struct rpc_connect_dci_state {
 
 
 static void continue_dci_rpc_connect(struct composite_context *ctx);
-static void continue_lsa_policy(struct rpc_request *req);
-static void continue_lsa_query_info(struct rpc_request *req);
-static void continue_lsa_query_info2(struct rpc_request *req);
+static void continue_lsa_policy(struct tevent_req *subreq);
+static void continue_lsa_query_info(struct tevent_req *subreq);
+static void continue_lsa_query_info2(struct tevent_req *subreq);
 static void continue_epm_map_binding(struct composite_context *ctx);
 static void continue_secondary_conn(struct composite_context *ctx);
 static void continue_epm_map_binding_send(struct composite_context *c);
@@ -478,14 +497,18 @@ static struct composite_context* libnet_RpcConnectDCInfo_send(struct libnet_cont
        s->r   = *r;
        ZERO_STRUCT(s->r.out);
 
+
        /* proceed to pure rpc connection if the binding string is provided,
           otherwise try to connect domain controller */
        if (r->in.binding == NULL) {
-               s->rpc_conn.in.name    = r->in.name;
-               s->rpc_conn.level      = LIBNET_RPC_CONNECT_DC;
+               /* Pass on any binding flags (such as anonymous fallback) that have been set */
+               s->rpc_conn.in.dcerpc_flags = r->in.dcerpc_flags;
+
+               s->rpc_conn.in.name         = r->in.name;
+               s->rpc_conn.level           = LIBNET_RPC_CONNECT_DC;
        } else {
-               s->rpc_conn.in.binding = r->in.binding;
-               s->rpc_conn.level      = LIBNET_RPC_CONNECT_BINDING;
+               s->rpc_conn.in.binding      = r->in.binding;
+               s->rpc_conn.level           = LIBNET_RPC_CONNECT_BINDING;
        }
 
        /* we need to query information on lsarpc interface first */
@@ -508,7 +531,7 @@ static void continue_dci_rpc_connect(struct composite_context *ctx)
 {
        struct composite_context *c;
        struct rpc_connect_dci_state *s;
-       struct rpc_request *open_pol_req;
+       struct tevent_req *subreq;
 
        c = talloc_get_type(ctx->async.private_data, struct composite_context);
        s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
@@ -553,10 +576,12 @@ static void continue_dci_rpc_connect(struct composite_context *ctx)
        s->lsa_open_policy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
        s->lsa_open_policy.out.handle     = &s->lsa_handle;
 
-       open_pol_req = dcerpc_lsa_OpenPolicy2_send(s->lsa_pipe, c, &s->lsa_open_policy);
-       if (composite_nomem(open_pol_req, c)) return;
+       subreq = dcerpc_lsa_OpenPolicy2_r_send(s, c->event_ctx,
+                                              s->lsa_pipe->binding_handle,
+                                              &s->lsa_open_policy);
+       if (composite_nomem(subreq, c)) return;
 
-       composite_continue_rpc(c, open_pol_req, continue_lsa_policy, c);
+       tevent_req_set_callback(subreq, continue_lsa_policy, c);
 }
 
 
@@ -564,16 +589,16 @@ static void continue_dci_rpc_connect(struct composite_context *ctx)
   Step 3 of RpcConnectDCInfo: Get policy handle and query lsa info
   for kerberos realm (dns name) and guid. The query may fail.
 */
-static void continue_lsa_policy(struct rpc_request *req)
+static void continue_lsa_policy(struct tevent_req *subreq)
 {
        struct composite_context *c;
        struct rpc_connect_dci_state *s;
-       struct rpc_request *query_info_req;
 
-       c = talloc_get_type(req->async.private_data, struct composite_context);
+       c = tevent_req_callback_data(subreq, struct composite_context);
        s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
 
-       c->status = dcerpc_ndr_request_recv(req);
+       c->status = dcerpc_lsa_OpenPolicy2_r_recv(subreq, s);
+       TALLOC_FREE(subreq);
        if (!NT_STATUS_IS_OK(c->status)) {
                composite_error(c, c->status);
                return;
@@ -607,11 +632,15 @@ static void continue_lsa_policy(struct rpc_request *req)
        /* query lsa info for dns domain name and guid */
        s->lsa_query_info2.in.handle = &s->lsa_handle;
        s->lsa_query_info2.in.level  = LSA_POLICY_INFO_DNS;
+       s->lsa_query_info2.out.info  = talloc_zero(c, union lsa_PolicyInformation *);
+       if (composite_nomem(s->lsa_query_info2.out.info, c)) return;
 
-       query_info_req = dcerpc_lsa_QueryInfoPolicy2_send(s->lsa_pipe, c, &s->lsa_query_info2);
-       if (composite_nomem(query_info_req, c)) return;
+       subreq = dcerpc_lsa_QueryInfoPolicy2_r_send(s, c->event_ctx,
+                                                   s->lsa_pipe->binding_handle,
+                                                   &s->lsa_query_info2);
+       if (composite_nomem(subreq, c)) return;
 
-       composite_continue_rpc(c, query_info_req, continue_lsa_query_info2, c);
+       tevent_req_set_callback(subreq, continue_lsa_query_info2, c);
 }
 
 
@@ -619,22 +648,22 @@ static void continue_lsa_policy(struct rpc_request *req)
   Step 4 of RpcConnectDCInfo: Get realm and guid if provided (rpc call
   may result in failure) and query lsa info for domain name and sid.
 */
-static void continue_lsa_query_info2(struct rpc_request *req)
+static void continue_lsa_query_info2(struct tevent_req *subreq)
 {      
        struct composite_context *c;
        struct rpc_connect_dci_state *s;
-       struct rpc_request *query_info_req;
 
-       c = talloc_get_type(req->async.private_data, struct composite_context);
+       c = tevent_req_callback_data(subreq, struct composite_context);
        s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
 
-       c->status = dcerpc_ndr_request_recv(req);
+       c->status = dcerpc_lsa_QueryInfoPolicy2_r_recv(subreq, s);
+       TALLOC_FREE(subreq);
        
        /* In case of error just null the realm and guid and proceed
           to the next step. After all, it doesn't have to be AD domain
           controller we talking to - NT-style PDC also counts */
 
-       if (NT_STATUS_EQUAL(c->status, NT_STATUS_NET_WRITE_FAULT)) {
+       if (NT_STATUS_EQUAL(c->status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
                s->r.out.realm = NULL;
                s->r.out.guid  = NULL;
 
@@ -658,13 +687,13 @@ static void continue_lsa_query_info2(struct rpc_request *req)
                /* Copy the dns domain name and guid from the query result */
 
                /* this should actually be a conversion from lsa_StringLarge */
-               s->r.out.realm = s->lsa_query_info2.out.info->dns.dns_domain.string;
+               s->r.out.realm = (*s->lsa_query_info2.out.info)->dns.dns_domain.string;
                s->r.out.guid  = talloc(c, struct GUID);
                if (composite_nomem(s->r.out.guid, c)) {
                        s->r.out.error_string = NULL;
                        return;
                }
-               *s->r.out.guid = s->lsa_query_info2.out.info->dns.domain_guid;
+               *s->r.out.guid = (*s->lsa_query_info2.out.info)->dns.domain_guid;
        }
 
        /* post monitor message */
@@ -680,26 +709,31 @@ static void continue_lsa_query_info2(struct rpc_request *req)
        /* query lsa info for domain name and sid */
        s->lsa_query_info.in.handle = &s->lsa_handle;
        s->lsa_query_info.in.level  = LSA_POLICY_INFO_DOMAIN;
+       s->lsa_query_info.out.info  = talloc_zero(c, union lsa_PolicyInformation *);
+       if (composite_nomem(s->lsa_query_info.out.info, c)) return;
 
-       query_info_req = dcerpc_lsa_QueryInfoPolicy_send(s->lsa_pipe, c, &s->lsa_query_info);
-       if (composite_nomem(query_info_req, c)) return;
+       subreq = dcerpc_lsa_QueryInfoPolicy_r_send(s, c->event_ctx,
+                                                  s->lsa_pipe->binding_handle,
+                                                  &s->lsa_query_info);
+       if (composite_nomem(subreq, c)) return;
 
-       composite_continue_rpc(c, query_info_req, continue_lsa_query_info, c);
+       tevent_req_set_callback(subreq, continue_lsa_query_info, c);
 }
 
 
 /*
   Step 5 of RpcConnectDCInfo: Get domain name and sid
 */
-static void continue_lsa_query_info(struct rpc_request *req)
+static void continue_lsa_query_info(struct tevent_req *subreq)
 {
        struct composite_context *c;
        struct rpc_connect_dci_state *s;
 
-       c = talloc_get_type(req->async.private_data, struct composite_context);
+       c = tevent_req_callback_data(subreq, struct composite_context);
        s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
 
-       c->status = dcerpc_ndr_request_recv(req);
+       c->status = dcerpc_lsa_QueryInfoPolicy_r_recv(subreq, s);
+       TALLOC_FREE(subreq);
        if (!NT_STATUS_IS_OK(c->status)) {
                s->r.out.error_string = talloc_asprintf(c,
                                                        "lsa_QueryInfoPolicy failed: %s",
@@ -719,8 +753,8 @@ static void continue_lsa_query_info(struct rpc_request *req)
        }
 
        /* Copy the domain name and sid from the query result */
-       s->r.out.domain_sid  = s->lsa_query_info.out.info->domain.sid;
-       s->r.out.domain_name = s->lsa_query_info.out.info->domain.name.string;
+       s->r.out.domain_sid  = (*s->lsa_query_info.out.info)->domain.sid;
+       s->r.out.domain_name = (*s->lsa_query_info.out.info)->domain.name.string;
 
        continue_epm_map_binding_send(c);
 }
@@ -860,9 +894,11 @@ static NTSTATUS libnet_RpcConnectDCInfo_recv(struct composite_context *c, struct
                   mem_ctx is freed */
                if (r->in.dcerpc_iface == &ndr_table_samr) {
                        ctx->samr.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
+                       ctx->samr.samr_handle = ctx->samr.pipe->binding_handle;
 
                } else if (r->in.dcerpc_iface == &ndr_table_lsarpc) {
                        ctx->lsa.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
+                       ctx->lsa.lsa_handle = ctx->lsa.pipe->binding_handle;
                }
 
        } else {