LCOV - code coverage report
Current view: top level - source4/libnet - userinfo.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 148 161 91.9 %
Date: 2024-04-13 12:30:31 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Copyright (C) Rafal Szczesniak 2005
       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 user information via samr pipe
      22             : */
      23             : 
      24             : #include "includes.h"
      25             : #include "libcli/composite/composite.h"
      26             : #include "librpc/gen_ndr/security.h"
      27             : #include "libcli/security/security.h"
      28             : #include "libnet/libnet.h"
      29             : #include "librpc/gen_ndr/ndr_samr_c.h"
      30             : 
      31             : 
      32             : struct userinfo_state {
      33             :         struct dcerpc_binding_handle *binding_handle;
      34             :         struct policy_handle      domain_handle;
      35             :         struct policy_handle      user_handle;
      36             :         uint16_t                  level;
      37             :         struct samr_LookupNames   lookup;
      38             :         struct samr_OpenUser      openuser;
      39             :         struct samr_QueryUserInfo queryuserinfo;
      40             :         struct samr_Close         samrclose;    
      41             :         union  samr_UserInfo      *info;
      42             : 
      43             :         /* information about the progress */
      44             :         void (*monitor_fn)(struct monitor_msg *);
      45             : };
      46             : 
      47             : 
      48             : static void continue_userinfo_lookup(struct tevent_req *subreq);
      49             : static void continue_userinfo_openuser(struct tevent_req *subreq);
      50             : static void continue_userinfo_getuser(struct tevent_req *subreq);
      51             : static void continue_userinfo_closeuser(struct tevent_req *subreq);
      52             : 
      53             : 
      54             : /**
      55             :  * Stage 1 (optional): Look for a username in SAM server.
      56             :  */
      57          22 : static void continue_userinfo_lookup(struct tevent_req *subreq)
      58             : {
      59          22 :         struct composite_context *c;
      60          22 :         struct userinfo_state *s;
      61          22 :         struct monitor_msg msg;
      62          22 :         struct msg_rpc_lookup_name *msg_lookup;
      63             : 
      64          22 :         c = tevent_req_callback_data(subreq, struct composite_context);
      65          22 :         s = talloc_get_type_abort(c->private_data, struct userinfo_state);
      66             : 
      67             :         /* receive samr_Lookup reply */
      68          22 :         c->status = dcerpc_samr_LookupNames_r_recv(subreq, s);
      69          22 :         TALLOC_FREE(subreq);
      70          22 :         if (!composite_is_ok(c)) return;
      71             :         
      72             :         /* there could be a problem with name resolving itself */
      73          22 :         if (!NT_STATUS_IS_OK(s->lookup.out.result)) {
      74           0 :                 composite_error(c, s->lookup.out.result);
      75           0 :                 return;
      76             :         }
      77             : 
      78             :         /* issue a monitor message */
      79          22 :         if (s->monitor_fn) {
      80           1 :                 msg.type = mon_SamrLookupName;
      81           1 :                 msg_lookup = talloc(s, struct msg_rpc_lookup_name);
      82           1 :                 msg_lookup->rid = s->lookup.out.rids->ids;
      83           1 :                 msg_lookup->count = s->lookup.out.rids->count;
      84           1 :                 msg.data = (void*)msg_lookup;
      85           1 :                 msg.data_size = sizeof(*msg_lookup);
      86             :                 
      87           1 :                 s->monitor_fn(&msg);
      88             :         }
      89             :         
      90             : 
      91             :         /* have we actually got name resolved
      92             :            - we're looking for only one at the moment */
      93          22 :         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          22 :         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          22 :         s->openuser.in.domain_handle  = &s->domain_handle;
     106          22 :         s->openuser.in.access_mask    = SEC_FLAG_MAXIMUM_ALLOWED;
     107          22 :         s->openuser.in.rid            = s->lookup.out.rids->ids[0];
     108          22 :         s->openuser.out.user_handle   = &s->user_handle;
     109             : 
     110             :         /* send request */
     111          22 :         subreq = dcerpc_samr_OpenUser_r_send(s, c->event_ctx,
     112             :                                              s->binding_handle,
     113             :                                              &s->openuser);
     114          22 :         if (composite_nomem(subreq, c)) return;
     115             : 
     116          22 :         tevent_req_set_callback(subreq, continue_userinfo_openuser, c);
     117             : }
     118             : 
     119             : 
     120             : /**
     121             :  * Stage 2: Open user policy handle.
     122             :  */
     123          35 : static void continue_userinfo_openuser(struct tevent_req *subreq)
     124             : {
     125          35 :         struct composite_context *c;
     126          35 :         struct userinfo_state *s;
     127          35 :         struct monitor_msg msg;
     128          35 :         struct msg_rpc_open_user *msg_open;
     129             : 
     130          35 :         c = tevent_req_callback_data(subreq, struct composite_context);
     131          35 :         s = talloc_get_type_abort(c->private_data, struct userinfo_state);
     132             : 
     133             :         /* receive samr_OpenUser reply */
     134          35 :         c->status = dcerpc_samr_OpenUser_r_recv(subreq, s);
     135          35 :         TALLOC_FREE(subreq);
     136          35 :         if (!composite_is_ok(c)) return;
     137             : 
     138          35 :         if (!NT_STATUS_IS_OK(s->openuser.out.result)) {
     139           0 :                 composite_error(c, s->openuser.out.result);
     140           0 :                 return;
     141             :         }
     142             : 
     143             :         /* issue a monitor message */
     144          35 :         if (s->monitor_fn) {
     145           2 :                 msg.type = mon_SamrOpenUser;
     146           2 :                 msg_open = talloc(s, struct msg_rpc_open_user);
     147           2 :                 msg_open->rid = s->openuser.in.rid;
     148           2 :                 msg_open->access_mask = s->openuser.in.access_mask;
     149           2 :                 msg.data = (void*)msg_open;
     150           2 :                 msg.data_size = sizeof(*msg_open);
     151             :                 
     152           2 :                 s->monitor_fn(&msg);
     153             :         }
     154             :         
     155             :         /* prepare parameters for QueryUserInfo call */
     156          35 :         s->queryuserinfo.in.user_handle = &s->user_handle;
     157          35 :         s->queryuserinfo.in.level       = s->level;
     158          35 :         s->queryuserinfo.out.info       = talloc(s, union samr_UserInfo *);
     159          35 :         if (composite_nomem(s->queryuserinfo.out.info, c)) return;
     160             :         
     161             :         /* queue rpc call, set event handling and new state */
     162          35 :         subreq = dcerpc_samr_QueryUserInfo_r_send(s, c->event_ctx,
     163             :                                                   s->binding_handle,
     164             :                                                   &s->queryuserinfo);
     165          35 :         if (composite_nomem(subreq, c)) return;
     166             :         
     167          35 :         tevent_req_set_callback(subreq, continue_userinfo_getuser, c);
     168             : }
     169             : 
     170             : 
     171             : /**
     172             :  * Stage 3: Get requested user information.
     173             :  */
     174          35 : static void continue_userinfo_getuser(struct tevent_req *subreq)
     175             : {
     176          35 :         struct composite_context *c;
     177          35 :         struct userinfo_state *s;
     178          35 :         struct monitor_msg msg;
     179          35 :         struct msg_rpc_query_user *msg_query;
     180             : 
     181          35 :         c = tevent_req_callback_data(subreq, struct composite_context);
     182          35 :         s = talloc_get_type_abort(c->private_data, struct userinfo_state);
     183             : 
     184             :         /* receive samr_QueryUserInfo reply */
     185          35 :         c->status = dcerpc_samr_QueryUserInfo_r_recv(subreq, s);
     186          35 :         TALLOC_FREE(subreq);
     187          35 :         if (!composite_is_ok(c)) return;
     188             : 
     189             :         /* check if queryuser itself went ok */
     190          35 :         if (!NT_STATUS_IS_OK(s->queryuserinfo.out.result)) {
     191           0 :                 composite_error(c, s->queryuserinfo.out.result);
     192           0 :                 return;
     193             :         }
     194             : 
     195          35 :         s->info = talloc_steal(s, *(s->queryuserinfo.out.info));
     196             : 
     197             :         /* issue a monitor message */
     198          35 :         if (s->monitor_fn) {
     199           2 :                 msg.type = mon_SamrQueryUser;
     200           2 :                 msg_query = talloc(s, struct msg_rpc_query_user);
     201           2 :                 msg_query->level = s->queryuserinfo.in.level;
     202           2 :                 msg.data = (void*)msg_query;
     203           2 :                 msg.data_size = sizeof(*msg_query);
     204             :                 
     205           2 :                 s->monitor_fn(&msg);
     206             :         }
     207             :         
     208             :         /* prepare arguments for Close call */
     209          35 :         s->samrclose.in.handle  = &s->user_handle;
     210          35 :         s->samrclose.out.handle = &s->user_handle;
     211             :         
     212             :         /* queue rpc call, set event handling and new state */
     213          35 :         subreq = dcerpc_samr_Close_r_send(s, c->event_ctx,
     214             :                                           s->binding_handle,
     215             :                                           &s->samrclose);
     216          35 :         if (composite_nomem(subreq, c)) return;
     217             :         
     218          35 :         tevent_req_set_callback(subreq, continue_userinfo_closeuser, c);
     219             : }
     220             : 
     221             : 
     222             : /**
     223             :  * Stage 4: Close policy handle associated with opened user.
     224             :  */
     225          35 : static void continue_userinfo_closeuser(struct tevent_req *subreq)
     226             : {
     227          35 :         struct composite_context *c;
     228          35 :         struct userinfo_state *s;
     229          35 :         struct monitor_msg msg;
     230          35 :         struct msg_rpc_close_user *msg_close;
     231             : 
     232          35 :         c = tevent_req_callback_data(subreq, struct composite_context);
     233          35 :         s = talloc_get_type_abort(c->private_data, struct userinfo_state);
     234             : 
     235             :         /* receive samr_Close reply */
     236          35 :         c->status = dcerpc_samr_Close_r_recv(subreq, s);
     237          35 :         TALLOC_FREE(subreq);
     238          35 :         if (!composite_is_ok(c)) return;
     239             : 
     240          35 :         if (!NT_STATUS_IS_OK(s->samrclose.out.result)) {
     241           0 :                 composite_error(c, s->samrclose.out.result);
     242           0 :                 return;
     243             :         }
     244             : 
     245             :         /* issue a monitor message */
     246          35 :         if (s->monitor_fn) {
     247           2 :                 msg.type = mon_SamrClose;
     248           2 :                 msg_close = talloc(s, struct msg_rpc_close_user);
     249           2 :                 msg_close->rid = s->openuser.in.rid;
     250           2 :                 msg.data = (void*)msg_close;
     251           2 :                 msg.data_size = sizeof(*msg_close);
     252             : 
     253           2 :                 s->monitor_fn(&msg);
     254             :         }
     255             : 
     256          35 :         composite_done(c);
     257             : }
     258             : 
     259             : 
     260             : /**
     261             :  * Sends asynchronous userinfo request
     262             :  *
     263             :  * @param p dce/rpc call pipe 
     264             :  * @param io arguments and results of the call
     265             :  */
     266          35 : struct composite_context *libnet_rpc_userinfo_send(TALLOC_CTX *mem_ctx,
     267             :                                                    struct tevent_context *ev,
     268             :                                                    struct dcerpc_binding_handle *b,
     269             :                                                    struct libnet_rpc_userinfo *io,
     270             :                                                    void (*monitor)(struct monitor_msg*))
     271             : {
     272          35 :         struct composite_context *c;
     273          35 :         struct userinfo_state *s;
     274          35 :         struct dom_sid *sid;
     275          35 :         struct tevent_req *subreq;
     276             : 
     277          35 :         if (!b || !io) return NULL;
     278             :         
     279          35 :         c = composite_create(mem_ctx, ev);
     280          35 :         if (c == NULL) return c;
     281             :         
     282          35 :         s = talloc_zero(c, struct userinfo_state);
     283          35 :         if (composite_nomem(s, c)) return c;
     284             : 
     285          35 :         c->private_data = s;
     286             : 
     287          35 :         s->level         = io->in.level;
     288          35 :         s->binding_handle= b;
     289          35 :         s->domain_handle = io->in.domain_handle;
     290          35 :         s->monitor_fn    = monitor;
     291             : 
     292          35 :         if (io->in.sid) {
     293          13 :                 sid = dom_sid_parse_talloc(s, io->in.sid);
     294          13 :                 if (composite_nomem(sid, c)) return c;
     295             : 
     296          13 :                 s->openuser.in.domain_handle  = &s->domain_handle;
     297          13 :                 s->openuser.in.access_mask    = SEC_FLAG_MAXIMUM_ALLOWED;
     298          13 :                 s->openuser.in.rid            = sid->sub_auths[sid->num_auths - 1];
     299          13 :                 s->openuser.out.user_handle   = &s->user_handle;
     300             :                 
     301             :                 /* send request */
     302          13 :                 subreq = dcerpc_samr_OpenUser_r_send(s, c->event_ctx,
     303             :                                                      s->binding_handle,
     304             :                                                      &s->openuser);
     305          13 :                 if (composite_nomem(subreq, c)) return c;
     306             : 
     307          13 :                 tevent_req_set_callback(subreq, continue_userinfo_openuser, c);
     308             : 
     309             :         } else {
     310             :                 /* preparing parameters to send rpc request */
     311          22 :                 s->lookup.in.domain_handle    = &s->domain_handle;
     312          22 :                 s->lookup.in.num_names        = 1;
     313          22 :                 s->lookup.in.names            = talloc_array(s, struct lsa_String, 1);
     314          22 :                 if (composite_nomem(s->lookup.in.names, c)) return c;
     315          22 :                 s->lookup.out.rids         = talloc_zero(s, struct samr_Ids);
     316          22 :                 s->lookup.out.types        = talloc_zero(s, struct samr_Ids);
     317          22 :                 if (composite_nomem(s->lookup.out.rids, c)) return c;
     318          22 :                 if (composite_nomem(s->lookup.out.types, c)) return c;
     319             : 
     320          22 :                 s->lookup.in.names[0].string  = talloc_strdup(s, io->in.username);
     321          22 :                 if (composite_nomem(s->lookup.in.names[0].string, c)) return c;
     322             :                 
     323             :                 /* send request */
     324          22 :                 subreq = dcerpc_samr_LookupNames_r_send(s, c->event_ctx,
     325             :                                                         s->binding_handle,
     326             :                                                         &s->lookup);
     327          22 :                 if (composite_nomem(subreq, c)) return c;
     328             :                 
     329          22 :                 tevent_req_set_callback(subreq, continue_userinfo_lookup, c);
     330             :         }
     331             : 
     332           0 :         return c;
     333             : }
     334             : 
     335             : 
     336             : /**
     337             :  * Waits for and receives result of asynchronous userinfo call
     338             :  * 
     339             :  * @param c composite context returned by asynchronous userinfo call
     340             :  * @param mem_ctx memory context of the call
     341             :  * @param io pointer to results (and arguments) of the call
     342             :  * @return nt status code of execution
     343             :  */
     344             : 
     345          35 : NTSTATUS libnet_rpc_userinfo_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
     346             :                                   struct libnet_rpc_userinfo *io)
     347             : {
     348          35 :         NTSTATUS status;
     349          35 :         struct userinfo_state *s;
     350             :         
     351             :         /* wait for results of sending request */
     352          35 :         status = composite_wait(c);
     353             :         
     354          35 :         if (NT_STATUS_IS_OK(status) && io) {
     355          35 :                 s = talloc_get_type_abort(c->private_data, struct userinfo_state);
     356          35 :                 talloc_steal(mem_ctx, s->info);
     357          35 :                 io->out.info = *s->info;
     358             :         }
     359             :         
     360             :         /* memory context associated to composite context is no longer needed */
     361          35 :         talloc_free(c);
     362          35 :         return status;
     363             : }
     364             : 
     365             : 
     366             : /**
     367             :  * Synchronous version of userinfo call
     368             :  *
     369             :  * @param pipe dce/rpc call pipe
     370             :  * @param mem_ctx memory context for the call
     371             :  * @param io arguments and results of the call
     372             :  * @return nt status code of execution
     373             :  */
     374             : 
     375          12 : NTSTATUS libnet_rpc_userinfo(struct tevent_context *ev,
     376             :                              struct dcerpc_binding_handle *b,
     377             :                              TALLOC_CTX *mem_ctx,
     378             :                              struct libnet_rpc_userinfo *io)
     379             : {
     380          12 :         struct composite_context *c = libnet_rpc_userinfo_send(mem_ctx, ev, b, io, NULL);
     381          12 :         return libnet_rpc_userinfo_recv(c, mem_ctx, io);
     382             : }

Generated by: LCOV version 1.14