LCOV - code coverage report
Current view: top level - source4/libnet - groupinfo.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 122 161 75.8 %
Date: 2024-02-28 12:06:22 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Copyright (C) Rafal Szczesniak 2007
       5             :    
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             :    
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             :    
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : /*
      21             :   a composite function for getting group information via samr pipe
      22             : */
      23             : 
      24             : 
      25             : #include "includes.h"
      26             : #include "libcli/composite/composite.h"
      27             : #include "librpc/gen_ndr/security.h"
      28             : #include "libcli/security/security.h"
      29             : #include "libnet/libnet.h"
      30             : #include "librpc/gen_ndr/ndr_samr_c.h"
      31             : 
      32             : 
      33             : struct groupinfo_state {
      34             :         struct dcerpc_binding_handle *binding_handle;
      35             :         struct policy_handle       domain_handle;
      36             :         struct policy_handle       group_handle;
      37             :         uint16_t                   level;
      38             :         struct samr_LookupNames    lookup;
      39             :         struct samr_OpenGroup      opengroup;
      40             :         struct samr_QueryGroupInfo querygroupinfo;
      41             :         struct samr_Close          samrclose;
      42             :         union  samr_GroupInfo      *info;
      43             : 
      44             :         /* information about the progress */
      45             :         void (*monitor_fn)(struct monitor_msg *);
      46             : };
      47             : 
      48             : 
      49             : static void continue_groupinfo_lookup(struct tevent_req *subreq);
      50             : static void continue_groupinfo_opengroup(struct tevent_req *subreq);
      51             : static void continue_groupinfo_getgroup(struct tevent_req *subreq);
      52             : static void continue_groupinfo_closegroup(struct tevent_req *subreq);
      53             : 
      54             : 
      55             : /**
      56             :  * Stage 1 (optional): Look for a group name in SAM server.
      57             :  */
      58           1 : static void continue_groupinfo_lookup(struct tevent_req *subreq)
      59             : {
      60           1 :         struct composite_context *c;
      61           1 :         struct groupinfo_state *s;
      62           1 :         struct monitor_msg msg;
      63           1 :         struct msg_rpc_lookup_name *msg_lookup;
      64             : 
      65           1 :         c = tevent_req_callback_data(subreq, struct composite_context);
      66           1 :         s = talloc_get_type(c->private_data, struct groupinfo_state);
      67             : 
      68             :         /* receive samr_Lookup reply */
      69           1 :         c->status = dcerpc_samr_LookupNames_r_recv(subreq, s);
      70           1 :         TALLOC_FREE(subreq);
      71           1 :         if (!composite_is_ok(c)) return;
      72             :         
      73             :         /* there could be a problem with name resolving itself */
      74           1 :         if (!NT_STATUS_IS_OK(s->lookup.out.result)) {
      75           0 :                 composite_error(c, s->lookup.out.result);
      76           0 :                 return;
      77             :         }
      78             : 
      79             :         /* issue a monitor message */
      80           1 :         if (s->monitor_fn) {
      81           0 :                 msg.type = mon_SamrLookupName;
      82           0 :                 msg_lookup = talloc(s, struct msg_rpc_lookup_name);
      83           0 :                 msg_lookup->rid = s->lookup.out.rids->ids;
      84           0 :                 msg_lookup->count = s->lookup.out.rids->count;
      85           0 :                 msg.data = (void*)msg_lookup;
      86           0 :                 msg.data_size = sizeof(*msg_lookup);
      87             :                 
      88           0 :                 s->monitor_fn(&msg);
      89             :         }
      90             :         
      91             :         /* have we actually got name resolved
      92             :            - we're looking for only one at the moment */
      93           1 :         if (s->lookup.out.rids->count != s->lookup.in.num_names) {
      94           0 :                 composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
      95           0 :                 return;
      96             :         }
      97           1 :         if (s->lookup.out.types->count != s->lookup.in.num_names) {
      98           0 :                 composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
      99           0 :                 return;
     100             :         }
     101             : 
     102             :         /* TODO: find proper status code for more than one rid found */
     103             : 
     104             :         /* prepare parameters for LookupNames */
     105           1 :         s->opengroup.in.domain_handle   = &s->domain_handle;
     106           1 :         s->opengroup.in.access_mask     = SEC_FLAG_MAXIMUM_ALLOWED;
     107           1 :         s->opengroup.in.rid             = s->lookup.out.rids->ids[0];
     108           1 :         s->opengroup.out.group_handle   = &s->group_handle;
     109             : 
     110             :         /* send request */
     111           1 :         subreq = dcerpc_samr_OpenGroup_r_send(s, c->event_ctx,
     112             :                                               s->binding_handle,
     113             :                                               &s->opengroup);
     114           1 :         if (composite_nomem(subreq, c)) return;
     115             : 
     116           1 :         tevent_req_set_callback(subreq, continue_groupinfo_opengroup, c);
     117             : }
     118             : 
     119             : 
     120             : /**
     121             :  * Stage 2: Open group policy handle.
     122             :  */
     123           3 : static void continue_groupinfo_opengroup(struct tevent_req *subreq)
     124             : {
     125           3 :         struct composite_context *c;
     126           3 :         struct groupinfo_state *s;
     127           3 :         struct monitor_msg msg;
     128           3 :         struct msg_rpc_open_group *msg_open;
     129             : 
     130           3 :         c = tevent_req_callback_data(subreq, struct composite_context);
     131           3 :         s = talloc_get_type(c->private_data, struct groupinfo_state);
     132             : 
     133             :         /* receive samr_OpenGroup reply */
     134           3 :         c->status = dcerpc_samr_OpenGroup_r_recv(subreq, s);
     135           3 :         TALLOC_FREE(subreq);
     136           3 :         if (!composite_is_ok(c)) return;
     137             : 
     138           3 :         if (!NT_STATUS_IS_OK(s->opengroup.out.result)) {
     139           0 :                 composite_error(c, s->opengroup.out.result);
     140           0 :                 return;
     141             :         }
     142             : 
     143             :         /* issue a monitor message */
     144           3 :         if (s->monitor_fn) {
     145           0 :                 msg.type = mon_SamrOpenGroup;
     146           0 :                 msg_open = talloc(s, struct msg_rpc_open_group);
     147           0 :                 msg_open->rid = s->opengroup.in.rid;
     148           0 :                 msg_open->access_mask = s->opengroup.in.access_mask;
     149           0 :                 msg.data = (void*)msg_open;
     150           0 :                 msg.data_size = sizeof(*msg_open);
     151             :                 
     152           0 :                 s->monitor_fn(&msg);
     153             :         }
     154             :         
     155             :         /* prepare parameters for QueryGroupInfo call */
     156           3 :         s->querygroupinfo.in.group_handle = &s->group_handle;
     157           3 :         s->querygroupinfo.in.level        = s->level;
     158           3 :         s->querygroupinfo.out.info        = talloc(s, union samr_GroupInfo *);
     159           3 :         if (composite_nomem(s->querygroupinfo.out.info, c)) return;
     160             :         
     161             :         /* queue rpc call, set event handling and new state */
     162           3 :         subreq = dcerpc_samr_QueryGroupInfo_r_send(s,
     163             :                                                    c->event_ctx,
     164             :                                                    s->binding_handle,
     165             :                                                    &s->querygroupinfo);
     166           3 :         if (composite_nomem(subreq, c)) return;
     167             :         
     168           3 :         tevent_req_set_callback(subreq, continue_groupinfo_getgroup, c);
     169             : }
     170             : 
     171             : 
     172             : /**
     173             :  * Stage 3: Get requested group information.
     174             :  */
     175           3 : static void continue_groupinfo_getgroup(struct tevent_req *subreq)
     176             : {
     177           3 :         struct composite_context *c;
     178           3 :         struct groupinfo_state *s;
     179           3 :         struct monitor_msg msg;
     180           3 :         struct msg_rpc_query_group *msg_query;
     181             : 
     182           3 :         c = tevent_req_callback_data(subreq, struct composite_context);
     183           3 :         s = talloc_get_type(c->private_data, struct groupinfo_state);
     184             : 
     185             :         /* receive samr_QueryGroupInfo reply */
     186           3 :         c->status = dcerpc_samr_QueryGroupInfo_r_recv(subreq, s);
     187           3 :         TALLOC_FREE(subreq);
     188           3 :         if (!composite_is_ok(c)) return;
     189             : 
     190             :         /* check if querygroup itself went ok */
     191           3 :         if (!NT_STATUS_IS_OK(s->querygroupinfo.out.result)) {
     192           0 :                 composite_error(c, s->querygroupinfo.out.result);
     193           0 :                 return;
     194             :         }
     195             : 
     196           3 :         s->info = talloc_steal(s, *s->querygroupinfo.out.info);
     197             : 
     198             :         /* issue a monitor message */
     199           3 :         if (s->monitor_fn) {
     200           0 :                 msg.type = mon_SamrQueryGroup;
     201           0 :                 msg_query = talloc(s, struct msg_rpc_query_group);
     202           0 :                 msg_query->level = s->querygroupinfo.in.level;
     203           0 :                 msg.data = (void*)msg_query;
     204           0 :                 msg.data_size = sizeof(*msg_query);
     205             :                 
     206           0 :                 s->monitor_fn(&msg);
     207             :         }
     208             :         
     209             :         /* prepare arguments for Close call */
     210           3 :         s->samrclose.in.handle  = &s->group_handle;
     211           3 :         s->samrclose.out.handle = &s->group_handle;
     212             :         
     213             :         /* queue rpc call, set event handling and new state */
     214           3 :         subreq = dcerpc_samr_Close_r_send(s, c->event_ctx,
     215             :                                           s->binding_handle,
     216             :                                           &s->samrclose);
     217           3 :         if (composite_nomem(subreq, c)) return;
     218             :         
     219           3 :         tevent_req_set_callback(subreq, continue_groupinfo_closegroup, c);
     220             : }
     221             : 
     222             : 
     223             : /**
     224             :  * Stage 4: Close policy handle associated with opened group.
     225             :  */
     226           3 : static void continue_groupinfo_closegroup(struct tevent_req *subreq)
     227             : {
     228           3 :         struct composite_context *c;
     229           3 :         struct groupinfo_state *s;
     230           3 :         struct monitor_msg msg;
     231           3 :         struct msg_rpc_close_group *msg_close;
     232             : 
     233           3 :         c = tevent_req_callback_data(subreq, struct composite_context);
     234           3 :         s = talloc_get_type(c->private_data, struct groupinfo_state);
     235             : 
     236             :         /* receive samr_Close reply */
     237           3 :         c->status = dcerpc_samr_Close_r_recv(subreq, s);
     238           3 :         TALLOC_FREE(subreq);
     239           3 :         if (!composite_is_ok(c)) return;
     240             : 
     241           3 :         if (!NT_STATUS_IS_OK(s->samrclose.out.result)) {
     242           0 :                 composite_error(c, s->samrclose.out.result);
     243           0 :                 return;
     244             :         }
     245             : 
     246             :         /* issue a monitor message */
     247           3 :         if (s->monitor_fn) {
     248           0 :                 msg.type = mon_SamrClose;
     249           0 :                 msg_close = talloc(s, struct msg_rpc_close_group);
     250           0 :                 msg_close->rid = s->opengroup.in.rid;
     251           0 :                 msg.data = (void*)msg_close;
     252           0 :                 msg.data_size = sizeof(*msg_close);
     253             : 
     254           0 :                 s->monitor_fn(&msg);
     255             :         }
     256             : 
     257           3 :         composite_done(c);
     258             : }
     259             : 
     260             : 
     261             : /**
     262             :  * Sends asynchronous groupinfo request
     263             :  *
     264             :  * @param p dce/rpc call pipe 
     265             :  * @param io arguments and results of the call
     266             :  */
     267           3 : struct composite_context *libnet_rpc_groupinfo_send(TALLOC_CTX *mem_ctx,
     268             :                                                     struct tevent_context *ev,
     269             :                                                     struct dcerpc_binding_handle *b,
     270             :                                                     struct libnet_rpc_groupinfo *io,
     271             :                                                     void (*monitor)(struct monitor_msg*))
     272             : {
     273           3 :         struct composite_context *c;
     274           3 :         struct groupinfo_state *s;
     275           3 :         struct dom_sid *sid;
     276           3 :         struct tevent_req *subreq;
     277             : 
     278           3 :         if (!b || !io) return NULL;
     279             :         
     280           3 :         c = composite_create(mem_ctx, ev);
     281           3 :         if (c == NULL) return c;
     282             :         
     283           3 :         s = talloc_zero(c, struct groupinfo_state);
     284           3 :         if (composite_nomem(s, c)) return c;
     285             : 
     286           3 :         c->private_data = s;
     287             : 
     288           3 :         s->level         = io->in.level;
     289           3 :         s->binding_handle= b;
     290           3 :         s->domain_handle = io->in.domain_handle;
     291           3 :         s->monitor_fn    = monitor;
     292             : 
     293           3 :         if (io->in.sid) {
     294           2 :                 sid = dom_sid_parse_talloc(s, io->in.sid);
     295           2 :                 if (composite_nomem(sid, c)) return c;
     296             : 
     297           2 :                 s->opengroup.in.domain_handle  = &s->domain_handle;
     298           2 :                 s->opengroup.in.access_mask    = SEC_FLAG_MAXIMUM_ALLOWED;
     299           2 :                 s->opengroup.in.rid            = sid->sub_auths[sid->num_auths - 1];
     300           2 :                 s->opengroup.out.group_handle  = &s->group_handle;
     301             :                 
     302             :                 /* send request */
     303           2 :                 subreq = dcerpc_samr_OpenGroup_r_send(s, c->event_ctx,
     304             :                                                       s->binding_handle,
     305             :                                                       &s->opengroup);
     306           2 :                 if (composite_nomem(subreq, c)) return c;
     307             : 
     308           2 :                 tevent_req_set_callback(subreq, continue_groupinfo_opengroup, c);
     309             : 
     310             :         } else {
     311             :                 /* preparing parameters to send rpc request */
     312           1 :                 s->lookup.in.domain_handle    = &s->domain_handle;
     313           1 :                 s->lookup.in.num_names        = 1;
     314           1 :                 s->lookup.in.names            = talloc_array(s, struct lsa_String, 1);
     315           1 :                 if (composite_nomem(s->lookup.in.names, c)) return c;
     316             : 
     317           1 :                 s->lookup.in.names[0].string  = talloc_strdup(s, io->in.groupname);
     318           1 :                 if (composite_nomem(s->lookup.in.names[0].string, c)) return c;
     319           1 :                 s->lookup.out.rids         = talloc_zero(s, struct samr_Ids);
     320           1 :                 s->lookup.out.types        = talloc_zero(s, struct samr_Ids);
     321           1 :                 if (composite_nomem(s->lookup.out.rids, c)) return c;
     322           1 :                 if (composite_nomem(s->lookup.out.types, c)) return c;
     323             : 
     324             :                 /* send request */
     325           1 :                 subreq = dcerpc_samr_LookupNames_r_send(s, c->event_ctx,
     326             :                                                         s->binding_handle,
     327             :                                                         &s->lookup);
     328           1 :                 if (composite_nomem(subreq, c)) return c;
     329             :                 
     330           1 :                 tevent_req_set_callback(subreq, continue_groupinfo_lookup, c);
     331             :         }
     332             : 
     333           0 :         return c;
     334             : }
     335             : 
     336             : 
     337             : /**
     338             :  * Waits for and receives result of asynchronous groupinfo call
     339             :  * 
     340             :  * @param c composite context returned by asynchronous groupinfo call
     341             :  * @param mem_ctx memory context of the call
     342             :  * @param io pointer to results (and arguments) of the call
     343             :  * @return nt status code of execution
     344             :  */
     345             : 
     346           3 : NTSTATUS libnet_rpc_groupinfo_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
     347             :                                    struct libnet_rpc_groupinfo *io)
     348             : {
     349           3 :         NTSTATUS status;
     350           3 :         struct groupinfo_state *s;
     351             :         
     352             :         /* wait for results of sending request */
     353           3 :         status = composite_wait(c);
     354             :         
     355           3 :         if (NT_STATUS_IS_OK(status) && io) {
     356           3 :                 s = talloc_get_type(c->private_data, struct groupinfo_state);
     357           3 :                 talloc_steal(mem_ctx, s->info);
     358           3 :                 io->out.info = *s->info;
     359             :         }
     360             :         
     361             :         /* memory context associated to composite context is no longer needed */
     362           3 :         talloc_free(c);
     363           3 :         return status;
     364             : }
     365             : 
     366             : 
     367             : /**
     368             :  * Synchronous version of groupinfo call
     369             :  *
     370             :  * @param pipe dce/rpc call pipe
     371             :  * @param mem_ctx memory context for the call
     372             :  * @param io arguments and results of the call
     373             :  * @return nt status code of execution
     374             :  */
     375             : 
     376           2 : NTSTATUS libnet_rpc_groupinfo(struct tevent_context *ev,
     377             :                               struct dcerpc_binding_handle *b,
     378             :                               TALLOC_CTX *mem_ctx,
     379             :                               struct libnet_rpc_groupinfo *io)
     380             : {
     381           2 :         struct composite_context *c = libnet_rpc_groupinfo_send(mem_ctx, ev, b,
     382             :                                                                 io, NULL);
     383           2 :         return libnet_rpc_groupinfo_recv(c, mem_ctx, io);
     384             : }

Generated by: LCOV version 1.14