s4:libnet_GroupList: allocate children strings on the correct talloc parent
[kamenim/samba.git] / source4 / libnet / libnet_group.c
index cae6d6d2725d7eec0308020a72ff9d1e725ae392..7679b426107fa24763d31d22c494d82f00668807 100644 (file)
@@ -147,6 +147,7 @@ NTSTATUS libnet_CreateGroup_recv(struct composite_context *c,
                r->out.error_string = talloc_strdup(mem_ctx, nt_errstr(status));
        }
 
+       talloc_free(c);
        return status;
 }
 
@@ -172,7 +173,9 @@ NTSTATUS libnet_CreateGroup(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
 struct group_info_state {
        struct libnet_context *ctx;
        const char *domain_name;
+       enum libnet_GroupInfo_level level;
        const char *group_name;
+       const char *sid_string;
        struct libnet_LookupName lookup;
        struct libnet_DomainOpen domopen;
        struct libnet_rpc_groupinfo info;
@@ -203,7 +206,7 @@ struct composite_context* libnet_GroupInfo_send(struct libnet_context *ctx,
        struct composite_context *c;
        struct group_info_state *s;
        bool prereq_met = false;
-       struct composite_context *lookup_req;
+       struct composite_context *lookup_req, *info_req;
 
        /* composite context allocation and setup */
        c = composite_create(mem_ctx, ctx->event_ctx);
@@ -216,25 +219,54 @@ struct composite_context* libnet_GroupInfo_send(struct libnet_context *ctx,
 
        /* store arguments in the state structure */
        s->monitor_fn = monitor;
-       s->ctx = ctx;   
+       s->ctx = ctx;
        s->domain_name = talloc_strdup(c, io->in.domain_name);
-       s->group_name  = talloc_strdup(c, io->in.group_name);
+       s->level = io->in.level;
+       switch(s->level) {
+       case GROUP_INFO_BY_NAME:
+               s->group_name = talloc_strdup(c, io->in.data.group_name);
+               s->sid_string = NULL;
+               break;
+       case GROUP_INFO_BY_SID:
+               s->group_name = NULL;
+               s->sid_string = dom_sid_string(c, io->in.data.group_sid);
+               break;
+       }
 
        /* prerequisite: make sure the domain is opened */
        prereq_met = samr_domain_opened(ctx, s->domain_name, &c, &s->domopen,
                                        continue_domain_open_info, monitor);
        if (!prereq_met) return c;
-       
-       /* prepare arguments for LookupName call */
-       s->lookup.in.name        = s->group_name;
-       s->lookup.in.domain_name = s->domain_name;
 
-       /* send the request */
-       lookup_req = libnet_LookupName_send(s->ctx, c, &s->lookup, s->monitor_fn);
-       if (composite_nomem(lookup_req, c)) return c;
+       switch(s->level) {
+       case GROUP_INFO_BY_NAME:
+               /* prepare arguments for LookupName call */
+               s->lookup.in.name        = s->group_name;
+               s->lookup.in.domain_name = s->domain_name;
+
+               /* send the request */
+               lookup_req = libnet_LookupName_send(s->ctx, c, &s->lookup, s->monitor_fn);
+               if (composite_nomem(lookup_req, c)) return c;
+
+               /* set the next stage */
+               composite_continue(c, lookup_req, continue_name_found, c);
+               break;
+       case GROUP_INFO_BY_SID:
+               /* prepare arguments for groupinfo call */
+               s->info.in.domain_handle = s->ctx->samr.handle;
+               s->info.in.sid           = s->sid_string;
+               /* we're looking for all information available */
+               s->info.in.level         = GROUPINFOALL;
+
+               /* send the request */
+               info_req = libnet_rpc_groupinfo_send(s->ctx->samr.pipe, &s->info, s->monitor_fn);
+               if (composite_nomem(info_req, c)) return c;
+
+               /* set the next stage */
+               composite_continue(c, info_req, continue_group_info, c);
+               break;
+       }
 
-       /* set the next stage */
-       composite_continue(c, lookup_req, continue_name_found, c);
        return c;
 }
 
@@ -246,7 +278,7 @@ static void continue_domain_open_info(struct composite_context *ctx)
 {
        struct composite_context *c;
        struct group_info_state *s;
-       struct composite_context *lookup_req;
+       struct composite_context *lookup_req, *info_req;
        
        c = talloc_get_type(ctx->async.private_data, struct composite_context);
        s = talloc_get_type(c->private_data, struct group_info_state);
@@ -255,16 +287,35 @@ static void continue_domain_open_info(struct composite_context *ctx)
        c->status = libnet_DomainOpen_recv(ctx, s->ctx, c, &s->domopen);
        if (!composite_is_ok(c)) return;
 
-       /* prepare arguments for LookupName call */
-       s->lookup.in.name        = s->group_name;
-       s->lookup.in.domain_name = s->domain_name;
+       switch(s->level) {
+       case GROUP_INFO_BY_NAME:
+               /* prepare arguments for LookupName call */
+               s->lookup.in.name        = s->group_name;
+               s->lookup.in.domain_name = s->domain_name;
+
+               /* send the request */
+               lookup_req = libnet_LookupName_send(s->ctx, c, &s->lookup, s->monitor_fn);
+               if (composite_nomem(lookup_req, c)) return;
+
+               /* set the next stage */
+               composite_continue(c, lookup_req, continue_name_found, c);
+               break;
+       case GROUP_INFO_BY_SID:
+               /* prepare arguments for groupinfo call */
+               s->info.in.domain_handle = s->ctx->samr.handle;
+               s->info.in.sid           = s->sid_string;
+               /* we're looking for all information available */
+               s->info.in.level         = GROUPINFOALL;
+
+               /* send the request */
+               info_req = libnet_rpc_groupinfo_send(s->ctx->samr.pipe, &s->info, s->monitor_fn);
+               if (composite_nomem(info_req, c)) return;
+
+               /* set the next stage */
+               composite_continue(c, info_req, continue_group_info, c);
+               break;
 
-       /* send the request */
-       lookup_req = libnet_LookupName_send(s->ctx, c, &s->lookup, s->monitor_fn);
-       if (composite_nomem(lookup_req, c)) return;
-       
-       /* set the next stage */
-       composite_continue(c, lookup_req, continue_name_found, c);
+       }
 }
 
 
@@ -283,7 +334,7 @@ static void continue_name_found(struct composite_context *ctx)
        /* receive SID assiociated with name found */
        c->status = libnet_LookupName_recv(ctx, c, &s->lookup);
        if (!composite_is_ok(c)) return;
-       
+
        /* Is is a group SID actually ? */
        if (s->lookup.out.sid_type != SID_NAME_DOM_GRP &&
            s->lookup.out.sid_type != SID_NAME_ALIAS) {
@@ -344,7 +395,9 @@ NTSTATUS libnet_GroupInfo_recv(struct composite_context* c, TALLOC_CTX *mem_ctx,
        if (NT_STATUS_IS_OK(status)) {
                /* put the results into io structure if everything went fine */
                s = talloc_get_type(c->private_data, struct group_info_state);
-               
+
+               io->out.group_name = talloc_steal(mem_ctx,
+                                       s->info.out.info.all.name.string);
                io->out.group_sid = talloc_steal(mem_ctx, s->lookup.out.sid);
                io->out.num_members = s->info.out.info.all.num_members;
                io->out.description = talloc_steal(mem_ctx, s->info.out.info.all.description.string);
@@ -356,7 +409,6 @@ NTSTATUS libnet_GroupInfo_recv(struct composite_context* c, TALLOC_CTX *mem_ctx,
        }
 
        talloc_free(c);
-
        return status;
 }
 
@@ -395,10 +447,9 @@ struct grouplist_state {
 
 
 static void continue_lsa_domain_opened(struct composite_context *ctx);
-static void continue_domain_queried(struct rpc_request *req);
+static void continue_domain_queried(struct tevent_req *subreq);
 static void continue_samr_domain_opened(struct composite_context *ctx);
-static void continue_domain_queried(struct rpc_request *req);
-static void continue_groups_enumerated(struct rpc_request *req);
+static void continue_groups_enumerated(struct tevent_req *subreq);
 
 
 /**
@@ -417,7 +468,7 @@ struct composite_context *libnet_GroupList_send(struct libnet_context *ctx,
 {
        struct composite_context *c;
        struct grouplist_state *s;
-       struct rpc_request *query_req;
+       struct tevent_req *subreq;
        bool prereq_met = false;
 
        /* composite context allocation and setup */
@@ -432,7 +483,7 @@ struct composite_context *libnet_GroupList_send(struct libnet_context *ctx,
        /* store the arguments in the state structure */
        s->ctx          = ctx;
        s->page_size    = io->in.page_size;
-       s->resume_index = (uint32_t)io->in.resume_index;
+       s->resume_index = io->in.resume_index;
        s->domain_name  = talloc_strdup(c, io->in.domain_name);
        s->monitor_fn   = monitor;
 
@@ -448,10 +499,12 @@ struct composite_context *libnet_GroupList_send(struct libnet_context *ctx,
        if (composite_nomem(s->query_domain.out.info, c)) return c;
 
        /* send the request */
-       query_req = dcerpc_lsa_QueryInfoPolicy_send(ctx->lsa.pipe, c, &s->query_domain);
-       if (composite_nomem(query_req, c)) return c;
+       subreq = dcerpc_lsa_QueryInfoPolicy_r_send(s, c->event_ctx,
+                                                  ctx->lsa.pipe->binding_handle,
+                                                  &s->query_domain);
+       if (composite_nomem(subreq, c)) return c;
        
-       composite_continue_rpc(c, query_req, continue_domain_queried, c);
+       tevent_req_set_callback(subreq, continue_domain_queried, c);
        return c;
 }
 
@@ -464,7 +517,7 @@ static void continue_lsa_domain_opened(struct composite_context *ctx)
 {
        struct composite_context *c;
        struct grouplist_state *s;
-       struct rpc_request *query_req;
+       struct tevent_req *subreq;
        
        c = talloc_get_type(ctx->async.private_data, struct composite_context);
        s = talloc_get_type(c->private_data, struct grouplist_state);
@@ -476,12 +529,16 @@ static void continue_lsa_domain_opened(struct composite_context *ctx)
        /* prepare arguments of QueryDomainInfo call */
        s->query_domain.in.handle = &s->ctx->lsa.handle;
        s->query_domain.in.level  = LSA_POLICY_INFO_DOMAIN;
+       s->query_domain.out.info  = talloc_zero(c, union lsa_PolicyInformation *);
+       if (composite_nomem(s->query_domain.out.info, c)) return;
 
        /* send the request */
-       query_req = dcerpc_lsa_QueryInfoPolicy_send(s->ctx->lsa.pipe, c, &s->query_domain);
-       if (composite_nomem(query_req, c)) return;
+       subreq = dcerpc_lsa_QueryInfoPolicy_r_send(s, c->event_ctx,
+                                                  s->ctx->lsa.pipe->binding_handle,
+                                                  &s->query_domain);
+       if (composite_nomem(subreq, c)) return;
 
-       composite_continue_rpc(c, query_req, continue_domain_queried, c);
+       tevent_req_set_callback(subreq, continue_domain_queried, c);
 }
 
 
@@ -489,18 +546,18 @@ static void continue_lsa_domain_opened(struct composite_context *ctx)
  * Stage 1: receive domain info and request to enum groups
  * provided a valid samr handle is opened
  */
-static void continue_domain_queried(struct rpc_request *req)
+static void continue_domain_queried(struct tevent_req *subreq)
 {
        struct composite_context *c;
        struct grouplist_state *s;
-       struct rpc_request *enum_req;
        bool prereq_met = false;
        
-       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 grouplist_state);
 
        /* receive result of rpc request */
-       c->status = dcerpc_ndr_request_recv(req);
+       c->status = dcerpc_lsa_QueryInfoPolicy_r_recv(subreq, s);
+       TALLOC_FREE(subreq);
        if (!composite_is_ok(c)) return;
 
        /* get the returned domain info */
@@ -516,12 +573,18 @@ static void continue_domain_queried(struct rpc_request *req)
        s->group_list.in.max_size       = s->page_size;
        s->group_list.in.resume_handle  = &s->resume_index;
        s->group_list.out.resume_handle = &s->resume_index;
+       s->group_list.out.num_entries   = talloc(s, uint32_t);
+       if (composite_nomem(s->group_list.out.num_entries, c)) return;
+       s->group_list.out.sam           = talloc(s, struct samr_SamArray *);
+       if (composite_nomem(s->group_list.out.sam, c)) return;
 
        /* send the request */
-       enum_req = dcerpc_samr_EnumDomainGroups_send(s->ctx->samr.pipe, c, &s->group_list);
-       if (composite_nomem(enum_req, c)) return;
+       subreq = dcerpc_samr_EnumDomainGroups_r_send(s, c->event_ctx,
+                                                    s->ctx->samr.pipe->binding_handle,
+                                                    &s->group_list);
+       if (composite_nomem(subreq, c)) return;
 
-       composite_continue_rpc(c, enum_req, continue_groups_enumerated, c);
+       tevent_req_set_callback(subreq, continue_groups_enumerated, c);
 }
 
 
@@ -533,7 +596,7 @@ static void continue_samr_domain_opened(struct composite_context *ctx)
 {
        struct composite_context *c;
        struct grouplist_state *s;
-       struct rpc_request *enum_req;
+       struct tevent_req *subreq;
 
        c = talloc_get_type(ctx->async.private_data, struct composite_context);
        s = talloc_get_type(c->private_data, struct grouplist_state);
@@ -547,29 +610,36 @@ static void continue_samr_domain_opened(struct composite_context *ctx)
        s->group_list.in.max_size       = s->page_size;
        s->group_list.in.resume_handle  = &s->resume_index;
        s->group_list.out.resume_handle = &s->resume_index;
+       s->group_list.out.num_entries   = talloc(s, uint32_t);
+       if (composite_nomem(s->group_list.out.num_entries, c)) return;
+       s->group_list.out.sam           = talloc(s, struct samr_SamArray *);
+       if (composite_nomem(s->group_list.out.sam, c)) return;
 
        /* send the request */
-       enum_req = dcerpc_samr_EnumDomainGroups_send(s->ctx->samr.pipe, c, &s->group_list);
-       if (composite_nomem(enum_req, c)) return;
+       subreq = dcerpc_samr_EnumDomainGroups_r_send(s, c->event_ctx,
+                                                    s->ctx->samr.pipe->binding_handle,
+                                                    &s->group_list);
+       if (composite_nomem(subreq, c)) return;
 
-       composite_continue_rpc(c, enum_req, continue_groups_enumerated, c);
+       tevent_req_set_callback(subreq, continue_groups_enumerated, c);
 }
 
 
 /*
  * Stage 2: receive enumerated groups and their rids
  */
-static void continue_groups_enumerated(struct rpc_request *req)
+static void continue_groups_enumerated(struct tevent_req *subreq)
 {
        struct composite_context *c;
        struct grouplist_state *s;
-       int i;
+       uint32_t i;
 
-       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 grouplist_state);
 
        /* receive result of rpc request */
-       c->status = dcerpc_ndr_request_recv(req);
+       c->status = dcerpc_samr_EnumDomainGroups_r_recv(subreq, s);
+       TALLOC_FREE(subreq);
        if (!composite_is_ok(c)) return;
 
        /* get the actual status of the rpc call result
@@ -585,15 +655,15 @@ static void continue_groups_enumerated(struct rpc_request *req)
                /* get enumerated accounts counter and resume handle (the latter allows
                   making subsequent call to continue enumeration) */
                s->resume_index = *s->group_list.out.resume_handle;
-               s->count        = s->group_list.out.num_entries;
+               s->count        = *s->group_list.out.num_entries;
 
                /* prepare returned group accounts array */
-               s->groups       = talloc_array(c, struct grouplist, s->group_list.out.sam->count);
+               s->groups       = talloc_array(c, struct grouplist, (*s->group_list.out.sam)->count);
                if (composite_nomem(s->groups, c)) return;
 
-               for (i = 0; i < s->group_list.out.sam->count; i++) {
+               for (i = 0; i < (*s->group_list.out.sam)->count; i++) {
                        struct dom_sid *group_sid;
-                       struct samr_SamEntry *entry = &s->group_list.out.sam->entries[i];
+                       struct samr_SamEntry *entry = &(*s->group_list.out.sam)->entries[i];
                        struct dom_sid *domain_sid = (*s->query_domain.out.info)->domain.sid;
                        
                        /* construct group sid from returned rid and queried domain sid */
@@ -601,11 +671,11 @@ static void continue_groups_enumerated(struct rpc_request *req)
                        if (composite_nomem(group_sid, c)) return;
 
                        /* groupname */
-                       s->groups[i].groupname = talloc_strdup(c, entry->name.string);
+                       s->groups[i].groupname = talloc_strdup(s->groups, entry->name.string);
                        if (composite_nomem(s->groups[i].groupname, c)) return;
 
                        /* sid string */
-                       s->groups[i].sid = dom_sid_string(c, group_sid);
+                       s->groups[i].sid = dom_sid_string(s->groups, group_sid);
                        if (composite_nomem(s->groups[i].sid, c)) return;
                }
 
@@ -661,6 +731,7 @@ NTSTATUS libnet_GroupList_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
                io->out.error_string = talloc_asprintf(mem_ctx, "Error: %s", nt_errstr(status));
        }
 
+       talloc_free(c);
        return status;
 }