Author: mimir
Date: 2007-05-07 05:42:26 +0000 (Mon, 07 May 2007)
New Revision: 22734

WebSVN: 
http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=22734

Log:
- use samr pipe if it is already opened
- close connection handle after domains enumeration
- collect domain names in subsequent rounds of enumeration
  (if there are more than one)


rafal


Modified:
   branches/SAMBA_4_0/source/libnet/libnet_domain.c


Changeset:
Modified: branches/SAMBA_4_0/source/libnet/libnet_domain.c
===================================================================
--- branches/SAMBA_4_0/source/libnet/libnet_domain.c    2007-05-07 03:16:54 UTC 
(rev 22733)
+++ branches/SAMBA_4_0/source/libnet/libnet_domain.c    2007-05-07 05:42:26 UTC 
(rev 22734)
@@ -852,6 +852,7 @@
        struct libnet_RpcConnect rpcconn;
        struct samr_Connect samrconn;
        struct samr_EnumDomains enumdom;
+       struct samr_Close samrclose;
        const char *hostname;
        struct policy_handle connect_handle;
        int buf_size;
@@ -866,6 +867,7 @@
 static void continue_rpc_connect(struct composite_context *c);
 static void continue_samr_connect(struct rpc_request *c);
 static void continue_samr_enum_domains(struct rpc_request *req);
+static void continue_samr_close_handle(struct rpc_request *req);
 
 static struct domainlist* get_domain_list(TALLOC_CTX *mem_ctx, struct 
domain_list_state *s);
 
@@ -927,13 +929,15 @@
 
 /*
   Stage 3: Receive domain names available and repeat the request
-  enumeration is not complete yet
+  enumeration is not complete yet. Close samr connection handle
+  upon completion.
 */
 static void continue_samr_enum_domains(struct rpc_request *req)
 {
        struct composite_context *c;
        struct domain_list_state *s;
        struct rpc_request *enumdom_req;
+       struct rpc_request *samrclose_req;
 
        c = talloc_get_type(req->async.private, struct composite_context);
        s = talloc_get_type(c->private_data, struct domain_list_state);
@@ -944,17 +948,18 @@
        if (NT_STATUS_IS_OK(s->enumdom.out.result)) {
 
                s->domains = get_domain_list(c, s);
-               composite_done(c);
 
        } else if (NT_STATUS_EQUAL(s->enumdom.out.result, STATUS_MORE_ENTRIES)) 
{
                
                s->domains = get_domain_list(c, s);
                
+               /* prepare next round of enumeration */
                s->enumdom.in.connect_handle = &s->connect_handle;
                s->enumdom.in.resume_handle  = &s->resume_handle;
                s->enumdom.in.buf_size       = s->buf_size;
                s->enumdom.out.resume_handle = &s->resume_handle;
 
+               /* send the request */
                enumdom_req = dcerpc_samr_EnumDomains_send(s->ctx->samr.pipe, 
c, &s->enumdom);
                if (composite_nomem(enumdom_req, c)) return;
 
@@ -962,11 +967,45 @@
 
        } else {
                composite_error(c, s->enumdom.out.result);
+               return;
        }
+
+       /* close samr connection handle */
+       s->samrclose.in.handle  = &s->connect_handle;
+       s->samrclose.out.handle = &s->connect_handle;
+       
+       /* send the request */
+       samrclose_req = dcerpc_samr_Close_send(s->ctx->samr.pipe, c, 
&s->samrclose);
+       if (composite_nomem(samrclose_req, c)) return;
+
+       composite_continue_rpc(c, samrclose_req, continue_samr_close_handle, c);
 }
 
 
 /*
+  Stage 4: Receive result of closing samr connection handle.
+*/
+static void continue_samr_close_handle(struct rpc_request *req)
+{
+       struct composite_context *c;
+       struct domain_list_state *s;
+
+       c = talloc_get_type(req->async.private, struct composite_context);
+       s = talloc_get_type(c->private_data, struct domain_list_state);
+
+       c->status = dcerpc_ndr_request_recv(req);
+       if (!composite_is_ok(c)) return;
+
+       /* did everything go fine ? */
+       if (!NT_STATUS_IS_OK(s->samrclose.out.result)) {
+               composite_error(c, s->samrclose.out.result);
+       }
+
+       composite_done(c);
+}
+
+
+/*
   Utility function to copy domain names from result of samr_EnumDomains call
 */
 static struct domainlist* get_domain_list(TALLOC_CTX *mem_ctx, struct 
domain_list_state *s)
@@ -974,20 +1013,28 @@
        int i;
        if (mem_ctx == NULL || s == NULL) return NULL;
 
-       /* number of entries returned (domains enumerated) */
-       s->count = s->enumdom.out.num_entries;
-       
        /* copy domain names returned from samr_EnumDomains call */
-       s->domains = talloc_array(mem_ctx, struct domainlist, 
s->enumdom.out.num_entries);
-       for (i = 0; i < s->enumdom.out.num_entries; i++)
+       if (s->domains == NULL) {
+               s->domains = talloc_array(mem_ctx, struct domainlist,
+                                         s->enumdom.out.num_entries);
+       } else {
+               s->domains = talloc_realloc(mem_ctx, s->domains, struct 
domainlist,
+                                           s->count + 
s->enumdom.out.num_entries);
+       }
+
+       for (i = s->count; i < s->count + s->enumdom.out.num_entries; i++)
        {
+               struct lsa_String *domain_name = &s->enumdom.out.sam->entries[i 
- s->count].name;
+
                /* strdup name as a child of allocated array to make it follow 
the array
                   in case of talloc_steal or talloc_free */
-               s->domains[i].name = talloc_strdup(s->domains,
-                                                  
s->enumdom.out.sam->entries[i].name.string);
+               s->domains[i].name = talloc_strdup(s->domains, 
domain_name->string);
                s->domains[i].sid  = NULL;  /* this is to be filled out later */
        }
 
+       /* number of entries returned (domains enumerated) */
+       s->count += s->enumdom.out.num_entries;
+       
        return s->domains;
 }
 
@@ -1009,6 +1056,7 @@
        struct composite_context *c;
        struct domain_list_state *s;
        struct composite_context *rpcconn_req;
+       struct rpc_request *samrconn_req;
 
        /* composite context and state structure allocation */
        c = composite_create(ctx, ctx->event_ctx);
@@ -1027,15 +1075,30 @@
        /* set the default buffer size if not stated explicitly */
        s->buf_size = (io->in.buf_size == 0) ? 512 : io->in.buf_size;
 
-       /* prepare rpc connect call */
-       s->rpcconn.level           = LIBNET_RPC_CONNECT_SERVER;
-       s->rpcconn.in.name         = s->hostname;
-       s->rpcconn.in.dcerpc_iface = &dcerpc_table_samr;
+       /* check whether samr pipe has already been opened */
+       if (ctx->samr.pipe == NULL) {
+               /* prepare rpc connect call */
+               s->rpcconn.level           = LIBNET_RPC_CONNECT_SERVER;
+               s->rpcconn.in.name         = s->hostname;
+               s->rpcconn.in.dcerpc_iface = &dcerpc_table_samr;
 
-       rpcconn_req = libnet_RpcConnect_send(ctx, c, &s->rpcconn);
-       if (composite_nomem(rpcconn_req, c)) return c;
+               rpcconn_req = libnet_RpcConnect_send(ctx, c, &s->rpcconn);
+               if (composite_nomem(rpcconn_req, c)) return c;
+               
+               composite_continue(c, rpcconn_req, continue_rpc_connect, c);
 
-       composite_continue(c, rpcconn_req, continue_rpc_connect, c);
+       } else {
+               /* prepare samr_Connect call */
+               s->samrconn.in.system_name     = 0;
+               s->samrconn.in.access_mask     = SEC_GENERIC_READ;
+               s->samrconn.out.connect_handle = &s->connect_handle;
+               
+               samrconn_req = dcerpc_samr_Connect_send(s->ctx->samr.pipe, c, 
&s->samrconn);
+               if (composite_nomem(samrconn_req, c)) return c;
+
+               composite_continue_rpc(c, samrconn_req, continue_samr_connect, 
c);
+       }
+
        return c;
 }
 

Reply via email to