root/source4/libnet/groupinfo.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. continue_groupinfo_lookup
  2. continue_groupinfo_opengroup
  3. continue_groupinfo_getgroup
  4. continue_groupinfo_closegroup
  5. libnet_rpc_groupinfo_send
  6. libnet_rpc_groupinfo_recv
  7. libnet_rpc_groupinfo

   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_pipe         *pipe;
  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 rpc_request *req);
  50 static void continue_groupinfo_opengroup(struct rpc_request *req);
  51 static void continue_groupinfo_getgroup(struct rpc_request *req);
  52 static void continue_groupinfo_closegroup(struct rpc_request *req);
  53 
  54 
  55 /**
  56  * Stage 1 (optional): Look for a group name in SAM server.
  57  */
  58 static void continue_groupinfo_lookup(struct rpc_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
  59 {
  60         struct composite_context *c;
  61         struct groupinfo_state *s;
  62         struct rpc_request *opengroup_req;
  63         struct monitor_msg msg;
  64         struct msg_rpc_lookup_name *msg_lookup;
  65 
  66         c = talloc_get_type(req->async.private_data, struct composite_context);
  67         s = talloc_get_type(c->private_data, struct groupinfo_state);
  68 
  69         /* receive samr_Lookup reply */
  70         c->status = dcerpc_ndr_request_recv(req);
  71         if (!composite_is_ok(c)) return;
  72         
  73         /* there could be a problem with name resolving itself */
  74         if (!NT_STATUS_IS_OK(s->lookup.out.result)) {
  75                 composite_error(c, s->lookup.out.result);
  76                 return;
  77         }
  78 
  79         /* issue a monitor message */
  80         if (s->monitor_fn) {
  81                 msg.type = mon_SamrLookupName;
  82                 msg_lookup = talloc(s, struct msg_rpc_lookup_name);
  83                 msg_lookup->rid = s->lookup.out.rids->ids;
  84                 msg_lookup->count = s->lookup.out.rids->count;
  85                 msg.data = (void*)msg_lookup;
  86                 msg.data_size = sizeof(*msg_lookup);
  87                 
  88                 s->monitor_fn(&msg);
  89         }
  90         
  91 
  92         /* have we actually got name resolved
  93            - we're looking for only one at the moment */
  94         if (s->lookup.out.rids->count == 0) {
  95                 composite_error(c, NT_STATUS_NO_SUCH_USER);
  96         }
  97 
  98         /* TODO: find proper status code for more than one rid found */
  99 
 100         /* prepare parameters for LookupNames */
 101         s->opengroup.in.domain_handle   = &s->domain_handle;
 102         s->opengroup.in.access_mask     = SEC_FLAG_MAXIMUM_ALLOWED;
 103         s->opengroup.in.rid             = s->lookup.out.rids->ids[0];
 104         s->opengroup.out.group_handle   = &s->group_handle;
 105 
 106         /* send request */
 107         opengroup_req = dcerpc_samr_OpenGroup_send(s->pipe, c, &s->opengroup);
 108         if (composite_nomem(opengroup_req, c)) return;
 109 
 110         composite_continue_rpc(c, opengroup_req, continue_groupinfo_opengroup, c);
 111 }
 112 
 113 
 114 /**
 115  * Stage 2: Open group policy handle.
 116  */
 117 static void continue_groupinfo_opengroup(struct rpc_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 118 {
 119         struct composite_context *c;
 120         struct groupinfo_state *s;
 121         struct rpc_request *querygroup_req;
 122         struct monitor_msg msg;
 123         struct msg_rpc_open_group *msg_open;
 124 
 125         c = talloc_get_type(req->async.private_data, struct composite_context);
 126         s = talloc_get_type(c->private_data, struct groupinfo_state);
 127 
 128         /* receive samr_OpenGroup reply */
 129         c->status = dcerpc_ndr_request_recv(req);
 130         if (!composite_is_ok(c)) return;
 131 
 132         if (!NT_STATUS_IS_OK(s->querygroupinfo.out.result)) {
 133                 composite_error(c, s->querygroupinfo.out.result);
 134                 return;
 135         }
 136 
 137         /* issue a monitor message */
 138         if (s->monitor_fn) {
 139                 msg.type = mon_SamrOpenGroup;
 140                 msg_open = talloc(s, struct msg_rpc_open_group);
 141                 msg_open->rid = s->opengroup.in.rid;
 142                 msg_open->access_mask = s->opengroup.in.access_mask;
 143                 msg.data = (void*)msg_open;
 144                 msg.data_size = sizeof(*msg_open);
 145                 
 146                 s->monitor_fn(&msg);
 147         }
 148         
 149         /* prepare parameters for QueryGroupInfo call */
 150         s->querygroupinfo.in.group_handle = &s->group_handle;
 151         s->querygroupinfo.in.level        = s->level;
 152         s->querygroupinfo.out.info        = talloc(s, union samr_GroupInfo *);
 153         if (composite_nomem(s->querygroupinfo.out.info, c)) return;
 154         
 155         /* queue rpc call, set event handling and new state */
 156         querygroup_req = dcerpc_samr_QueryGroupInfo_send(s->pipe, c, &s->querygroupinfo);
 157         if (composite_nomem(querygroup_req, c)) return;
 158         
 159         composite_continue_rpc(c, querygroup_req, continue_groupinfo_getgroup, c);
 160 }
 161 
 162 
 163 /**
 164  * Stage 3: Get requested group information.
 165  */
 166 static void continue_groupinfo_getgroup(struct rpc_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 167 {
 168         struct composite_context *c;
 169         struct groupinfo_state *s;
 170         struct rpc_request *close_req;
 171         struct monitor_msg msg;
 172         struct msg_rpc_query_group *msg_query;
 173 
 174         c = talloc_get_type(req->async.private_data, struct composite_context);
 175         s = talloc_get_type(c->private_data, struct groupinfo_state);
 176 
 177         /* receive samr_QueryGroupInfo reply */
 178         c->status = dcerpc_ndr_request_recv(req);
 179         if (!composite_is_ok(c)) return;
 180 
 181         /* check if querygroup itself went ok */
 182         if (!NT_STATUS_IS_OK(s->querygroupinfo.out.result)) {
 183                 composite_error(c, s->querygroupinfo.out.result);
 184                 return;
 185         }
 186 
 187         s->info = talloc_steal(s, *s->querygroupinfo.out.info);
 188 
 189         /* issue a monitor message */
 190         if (s->monitor_fn) {
 191                 msg.type = mon_SamrQueryGroup;
 192                 msg_query = talloc(s, struct msg_rpc_query_group);
 193                 msg_query->level = s->querygroupinfo.in.level;
 194                 msg.data = (void*)msg_query;
 195                 msg.data_size = sizeof(*msg_query);
 196                 
 197                 s->monitor_fn(&msg);
 198         }
 199         
 200         /* prepare arguments for Close call */
 201         s->samrclose.in.handle  = &s->group_handle;
 202         s->samrclose.out.handle = &s->group_handle;
 203         
 204         /* queue rpc call, set event handling and new state */
 205         close_req = dcerpc_samr_Close_send(s->pipe, c, &s->samrclose);
 206         if (composite_nomem(close_req, c)) return;
 207         
 208         composite_continue_rpc(c, close_req, continue_groupinfo_closegroup, c);
 209 }
 210 
 211 
 212 /**
 213  * Stage 4: Close policy handle associated with opened group.
 214  */
 215 static void continue_groupinfo_closegroup(struct rpc_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 216 {
 217         struct composite_context *c;
 218         struct groupinfo_state *s;
 219         struct monitor_msg msg;
 220         struct msg_rpc_close_group *msg_close;
 221 
 222         c = talloc_get_type(req->async.private_data, struct composite_context);
 223         s = talloc_get_type(c->private_data, struct groupinfo_state);
 224 
 225         /* receive samr_Close reply */
 226         c->status = dcerpc_ndr_request_recv(req);
 227         if (!composite_is_ok(c)) return;
 228 
 229         if (!NT_STATUS_IS_OK(s->samrclose.out.result)) {
 230                 composite_error(c, s->samrclose.out.result);
 231                 return;
 232         }
 233 
 234         /* issue a monitor message */
 235         if (s->monitor_fn) {
 236                 msg.type = mon_SamrClose;
 237                 msg_close = talloc(s, struct msg_rpc_close_group);
 238                 msg_close->rid = s->opengroup.in.rid;
 239                 msg.data = (void*)msg_close;
 240                 msg.data_size = sizeof(*msg_close);
 241 
 242                 s->monitor_fn(&msg);
 243         }
 244 
 245         composite_done(c);
 246 }
 247 
 248 
 249 /**
 250  * Sends asynchronous groupinfo request
 251  *
 252  * @param p dce/rpc call pipe 
 253  * @param io arguments and results of the call
 254  */
 255 struct composite_context *libnet_rpc_groupinfo_send(struct dcerpc_pipe *p,
     /* [<][>][^][v][top][bottom][index][help] */
 256                                                     struct libnet_rpc_groupinfo *io,
 257                                                     void (*monitor)(struct monitor_msg*))
 258 {
 259         struct composite_context *c;
 260         struct groupinfo_state *s;
 261         struct dom_sid *sid;
 262         struct rpc_request *opengroup_req, *lookup_req;
 263 
 264         if (!p || !io) return NULL;
 265         
 266         c = composite_create(p, dcerpc_event_context(p));
 267         if (c == NULL) return c;
 268         
 269         s = talloc_zero(c, struct groupinfo_state);
 270         if (composite_nomem(s, c)) return c;
 271 
 272         c->private_data = s;
 273 
 274         s->level         = io->in.level;
 275         s->pipe          = p;
 276         s->domain_handle = io->in.domain_handle;
 277         s->monitor_fn    = monitor;
 278 
 279         if (io->in.sid) {
 280                 sid = dom_sid_parse_talloc(s, io->in.sid);
 281                 if (composite_nomem(sid, c)) return c;
 282 
 283                 s->opengroup.in.domain_handle  = &s->domain_handle;
 284                 s->opengroup.in.access_mask    = SEC_FLAG_MAXIMUM_ALLOWED;
 285                 s->opengroup.in.rid            = sid->sub_auths[sid->num_auths - 1];
 286                 s->opengroup.out.group_handle  = &s->group_handle;
 287                 
 288                 /* send request */
 289                 opengroup_req = dcerpc_samr_OpenGroup_send(p, c, &s->opengroup);
 290                 if (composite_nomem(opengroup_req, c)) return c;
 291 
 292                 composite_continue_rpc(c, opengroup_req, continue_groupinfo_opengroup, c);
 293 
 294         } else {
 295                 /* preparing parameters to send rpc request */
 296                 s->lookup.in.domain_handle    = &s->domain_handle;
 297                 s->lookup.in.num_names        = 1;
 298                 s->lookup.in.names            = talloc_array(s, struct lsa_String, 1);
 299                 if (composite_nomem(s->lookup.in.names, c)) return c;
 300 
 301                 s->lookup.in.names[0].string  = talloc_strdup(s, io->in.groupname);
 302                 if (composite_nomem(s->lookup.in.names[0].string, c)) return c;
 303                 s->lookup.out.rids         = talloc_zero(s, struct samr_Ids);
 304                 s->lookup.out.types        = talloc_zero(s, struct samr_Ids);
 305                 if (composite_nomem(s->lookup.out.rids, c)) return c;
 306                 if (composite_nomem(s->lookup.out.types, c)) return c;
 307 
 308                 /* send request */
 309                 lookup_req = dcerpc_samr_LookupNames_send(p, c, &s->lookup);
 310                 if (composite_nomem(lookup_req, c)) return c;
 311                 
 312                 composite_continue_rpc(c, lookup_req, continue_groupinfo_lookup, c);
 313         }
 314 
 315         return c;
 316 }
 317 
 318 
 319 /**
 320  * Waits for and receives result of asynchronous groupinfo call
 321  * 
 322  * @param c composite context returned by asynchronous groupinfo call
 323  * @param mem_ctx memory context of the call
 324  * @param io pointer to results (and arguments) of the call
 325  * @return nt status code of execution
 326  */
 327 
 328 NTSTATUS libnet_rpc_groupinfo_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 329                                    struct libnet_rpc_groupinfo *io)
 330 {
 331         NTSTATUS status;
 332         struct groupinfo_state *s;
 333         
 334         /* wait for results of sending request */
 335         status = composite_wait(c);
 336         
 337         if (NT_STATUS_IS_OK(status) && io) {
 338                 s = talloc_get_type(c->private_data, struct groupinfo_state);
 339                 talloc_steal(mem_ctx, s->info);
 340                 io->out.info = *s->info;
 341         }
 342         
 343         /* memory context associated to composite context is no longer needed */
 344         talloc_free(c);
 345         return status;
 346 }
 347 
 348 
 349 /**
 350  * Synchronous version of groupinfo call
 351  *
 352  * @param pipe dce/rpc call pipe
 353  * @param mem_ctx memory context for the call
 354  * @param io arguments and results of the call
 355  * @return nt status code of execution
 356  */
 357 
 358 NTSTATUS libnet_rpc_groupinfo(struct dcerpc_pipe *p,
     /* [<][>][^][v][top][bottom][index][help] */
 359                               TALLOC_CTX *mem_ctx,
 360                               struct libnet_rpc_groupinfo *io)
 361 {
 362         struct composite_context *c = libnet_rpc_groupinfo_send(p, io, NULL);
 363         return libnet_rpc_groupinfo_recv(c, mem_ctx, io);
 364 }

/* [<][>][^][v][top][bottom][index][help] */