LCOV - code coverage report
Current view: top level - source3/winbindd - wb_queryuser.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 162 225 72.0 %
Date: 2024-06-13 04:01:37 Functions: 8 9 88.9 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    async queryuser
       4             :    Copyright (C) Volker Lendecke 2009
       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             : #include "includes.h"
      21             : #include "util/debug.h"
      22             : #include "winbindd.h"
      23             : #include "librpc/gen_ndr/ndr_winbind_c.h"
      24             : #include "../libcli/security/security.h"
      25             : #include "libsmb/samlogon_cache.h"
      26             : #include "librpc/gen_ndr/ndr_winbind.h"
      27             : 
      28             : struct wb_queryuser_state {
      29             :         struct tevent_context *ev;
      30             :         struct wbint_userinfo *info;
      31             :         const struct wb_parent_idmap_config *idmap_cfg;
      32             :         bool tried_dclookup;
      33             : };
      34             : 
      35             : static void wb_queryuser_idmap_setup_done(struct tevent_req *subreq);
      36             : static void wb_queryuser_got_uid(struct tevent_req *subreq);
      37             : static void wb_queryuser_got_domain(struct tevent_req *subreq);
      38             : static void wb_queryuser_got_dc(struct tevent_req *subreq);
      39             : static void wb_queryuser_got_gid(struct tevent_req *subreq);
      40             : static void wb_queryuser_got_group_name(struct tevent_req *subreq);
      41             : static void wb_queryuser_done(struct tevent_req *subreq);
      42             : 
      43        4784 : struct tevent_req *wb_queryuser_send(TALLOC_CTX *mem_ctx,
      44             :                                      struct tevent_context *ev,
      45             :                                      const struct dom_sid *user_sid)
      46             : {
      47             :         struct tevent_req *req, *subreq;
      48             :         struct wb_queryuser_state *state;
      49             :         struct wbint_userinfo *info;
      50             :         struct dom_sid_buf buf;
      51             : 
      52        4784 :         req = tevent_req_create(mem_ctx, &state, struct wb_queryuser_state);
      53        4784 :         if (req == NULL) {
      54           0 :                 return NULL;
      55             :         }
      56        4784 :         D_INFO("WB command queryuser start.\nQuery user sid %s\n",
      57             :                dom_sid_str_buf(user_sid, &buf));
      58        4784 :         state->ev = ev;
      59             : 
      60        4784 :         state->info = talloc_zero(state, struct wbint_userinfo);
      61        4784 :         if (tevent_req_nomem(state->info, req)) {
      62           0 :                 return tevent_req_post(req, ev);
      63             :         }
      64        4784 :         info = state->info;
      65             : 
      66        4784 :         info->primary_gid = (gid_t)-1;
      67             : 
      68        4784 :         sid_copy(&info->user_sid, user_sid);
      69             : 
      70        4784 :         subreq = wb_parent_idmap_setup_send(state, state->ev);
      71        4784 :         if (tevent_req_nomem(subreq, req)) {
      72           0 :                 return tevent_req_post(req, ev);
      73             :         }
      74        4784 :         tevent_req_set_callback(subreq, wb_queryuser_idmap_setup_done, req);
      75        4784 :         return req;
      76             : }
      77             : 
      78        4784 : static void wb_queryuser_idmap_setup_done(struct tevent_req *subreq)
      79             : {
      80        4784 :         struct tevent_req *req = tevent_req_callback_data(
      81             :                 subreq, struct tevent_req);
      82        4784 :         struct wb_queryuser_state *state = tevent_req_data(
      83             :                 req, struct wb_queryuser_state);
      84             :         NTSTATUS status;
      85             :         struct dom_sid_buf buf;
      86             : 
      87        4784 :         status = wb_parent_idmap_setup_recv(subreq, &state->idmap_cfg);
      88        4784 :         TALLOC_FREE(subreq);
      89        4784 :         if (tevent_req_nterror(req, status)) {
      90           0 :                 D_WARNING("wb_parent_idmap_setup_recv() failed with %s.\n",
      91             :                           nt_errstr(status));
      92           0 :                 return;
      93             :         }
      94             : 
      95        4784 :         D_DEBUG("Convert the user SID %s to XID.\n",
      96             :                 dom_sid_str_buf(&state->info->user_sid, &buf));
      97        4784 :         subreq = wb_sids2xids_send(
      98        4784 :                 state, state->ev, &state->info->user_sid, 1);
      99        4784 :         if (tevent_req_nomem(subreq, req)) {
     100           0 :                 return;
     101             :         }
     102        4784 :         tevent_req_set_callback(subreq, wb_queryuser_got_uid, req);
     103        4784 :         return;
     104             : }
     105             : 
     106        4784 : static void wb_queryuser_got_uid(struct tevent_req *subreq)
     107             : {
     108        4784 :         struct tevent_req *req = tevent_req_callback_data(
     109             :                 subreq, struct tevent_req);
     110        4784 :         struct wb_queryuser_state *state = tevent_req_data(
     111             :                 req, struct wb_queryuser_state);
     112        4784 :         struct wbint_userinfo *info = state->info;
     113             :         struct netr_SamInfo3 *info3;
     114        4784 :         struct dcerpc_binding_handle *child_binding_handle = NULL;
     115             :         struct unixid xid;
     116             :         NTSTATUS status;
     117             :         struct dom_sid_buf buf, buf1;
     118             : 
     119        4784 :         status = wb_sids2xids_recv(subreq, &xid, 1);
     120        4784 :         TALLOC_FREE(subreq);
     121        4784 :         if (tevent_req_nterror(req, status)) {
     122           0 :                 D_WARNING("wb_sids2xids_recv() failed with %s.\n",
     123             :                           nt_errstr(status));
     124        2801 :                 return;
     125             :         }
     126             : 
     127        4784 :         if ((xid.type != ID_TYPE_UID) && (xid.type != ID_TYPE_BOTH)) {
     128          48 :                 D_WARNING("XID type is %d, should be ID_TYPE_UID or ID_TYPE_BOTH.\n",
     129             :                           xid.type);
     130          48 :                 tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
     131          48 :                 return;
     132             :         }
     133             : 
     134        4736 :         D_DEBUG("Received XID %"PRIu32" for SID %s.\n",
     135             :                 xid.id,
     136             :                 dom_sid_str_buf(&info->user_sid, &buf1));
     137        4736 :         info->uid = xid.id;
     138             : 
     139             :         /*
     140             :          * Default the group sid to "Domain Users" in the user's
     141             :          * domain. The samlogon cache or the query_user call later on
     142             :          * can override this.
     143             :          */
     144        4736 :         sid_copy(&info->group_sid, &info->user_sid);
     145        4736 :         sid_split_rid(&info->group_sid, NULL);
     146        4736 :         sid_append_rid(&info->group_sid, DOMAIN_RID_USERS);
     147             : 
     148        4736 :         D_DEBUG("Preconfigured 'Domain Users' RID %u was used to create group SID %s from user SID %s.\n",
     149             :                 DOMAIN_RID_USERS,
     150             :                 dom_sid_str_buf(&info->group_sid, &buf),
     151             :                 dom_sid_str_buf(&info->user_sid, &buf1));
     152             : 
     153        4736 :         info->homedir = talloc_strdup(info, lp_template_homedir());
     154        4736 :         D_DEBUG("Setting 'homedir' to the template '%s'.\n", info->homedir);
     155        4736 :         if (tevent_req_nomem(info->homedir, req)) {
     156           0 :                 return;
     157             :         }
     158             : 
     159        4736 :         info->shell = talloc_strdup(info, lp_template_shell());
     160        4736 :         D_DEBUG("Setting 'shell' to the template '%s'.\n", info->shell);
     161        4736 :         if (tevent_req_nomem(info->shell, req)) {
     162           0 :                 return;
     163             :         }
     164             : 
     165        4736 :         info3 = netsamlogon_cache_get(state, &info->user_sid);
     166        4736 :         if (info3 != NULL) {
     167        1983 :                 D_DEBUG("Filling data received from netsamlogon_cache\n");
     168        1983 :                 sid_compose(&info->group_sid, info3->base.domain_sid,
     169             :                             info3->base.primary_gid);
     170        1983 :                 info->acct_name = talloc_move(
     171             :                         info, &info3->base.account_name.string);
     172        1983 :                 info->full_name = talloc_move(
     173             :                         info, &info3->base.full_name.string);
     174             : 
     175        1983 :                 info->domain_name = talloc_move(
     176             :                         state, &info3->base.logon_domain.string);
     177             : 
     178        1983 :                 TALLOC_FREE(info3);
     179             :         }
     180             : 
     181        4736 :         NDR_PRINT_DEBUG_LEVEL(DBGLVL_DEBUG, wbint_userinfo, state->info);
     182        4736 :         if (info->domain_name == NULL) {
     183        2753 :                 D_DEBUG("Domain name is empty, calling wb_lookupsid_send() to get it.\n");
     184        2753 :                 subreq = wb_lookupsid_send(state, state->ev, &info->user_sid);
     185        2753 :                 if (tevent_req_nomem(subreq, req)) {
     186           0 :                         return;
     187             :                 }
     188        2753 :                 tevent_req_set_callback(subreq, wb_queryuser_got_domain, req);
     189        2753 :                 return;
     190             :         }
     191             : 
     192             :         /*
     193             :          * Note wb_sids2xids_send/recv was called before,
     194             :          * so we're sure that wb_parent_idmap_setup_send/recv
     195             :          * was already called.
     196             :          */
     197        1983 :         child_binding_handle = idmap_child_handle();
     198        1983 :         D_DEBUG("Domain name is set, calling dcerpc_wbint_GetNssInfo_send()\n");
     199        1983 :         subreq = dcerpc_wbint_GetNssInfo_send(
     200             :                 state, state->ev, child_binding_handle, info);
     201        1983 :         if (tevent_req_nomem(subreq, req)) {
     202           0 :                 return;
     203             :         }
     204        1983 :         tevent_req_set_callback(subreq, wb_queryuser_done, req);
     205             : }
     206             : 
     207        2753 : static void wb_queryuser_got_domain(struct tevent_req *subreq)
     208             : {
     209        2753 :         struct tevent_req *req = tevent_req_callback_data(
     210             :                 subreq, struct tevent_req);
     211        2753 :         struct wb_queryuser_state *state = tevent_req_data(
     212             :                 req, struct wb_queryuser_state);
     213        2753 :         struct wbint_userinfo *info = state->info;
     214             :         enum lsa_SidType type;
     215        2753 :         struct dcerpc_binding_handle *child_binding_handle = NULL;
     216             :         NTSTATUS status;
     217             : 
     218        2753 :         status = wb_lookupsid_recv(subreq, state, &type,
     219             :                                    &info->domain_name, &info->acct_name);
     220        2753 :         TALLOC_FREE(subreq);
     221        2753 :         if (tevent_req_nterror(req, status)) {
     222           0 :                 D_WARNING("wb_lookupsid_recv failed with %s.\n",
     223             :                           nt_errstr(status));
     224           0 :                 return;
     225             :         }
     226             : 
     227        2753 :         NDR_PRINT_DEBUG_LEVEL(DBGLVL_DEBUG, wbint_userinfo, state->info);
     228        2753 :         switch (type) {
     229        2745 :         case SID_NAME_USER:
     230             :         case SID_NAME_COMPUTER:
     231             :                 /*
     232             :                  * user case: we only need the account name from lookup_sids
     233             :                  */
     234        2745 :                 break;
     235           8 :         case SID_NAME_DOM_GRP:
     236             :         case SID_NAME_ALIAS:
     237             :         case SID_NAME_WKN_GRP:
     238             :                 /*
     239             :                  * also treat group-type SIDs (they might map to ID_TYPE_BOTH)
     240             :                  */
     241           8 :                 sid_copy(&info->group_sid, &info->user_sid);
     242           8 :                 break;
     243           0 :         default:
     244           0 :                 D_WARNING("Unknown type:%d, return NT_STATUS_NO_SUCH_USER.\n",
     245             :                           type);
     246           0 :                 tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
     247           0 :                 return;
     248             :         }
     249             : 
     250             :         /*
     251             :          * Note wb_sids2xids_send/recv was called before,
     252             :          * so we're sure that wb_parent_idmap_setup_send/recv
     253             :          * was already called.
     254             :          */
     255        2753 :         child_binding_handle = idmap_child_handle();
     256        2753 :         D_DEBUG("About to call dcerpc_wbint_GetNssInfo_send()\n");
     257        2753 :         subreq = dcerpc_wbint_GetNssInfo_send(
     258             :                 state, state->ev, child_binding_handle, info);
     259        2753 :         if (tevent_req_nomem(subreq, req)) {
     260           0 :                 return;
     261             :         }
     262        2753 :         tevent_req_set_callback(subreq, wb_queryuser_done, req);
     263             : }
     264             : 
     265        4736 : static void wb_queryuser_done(struct tevent_req *subreq)
     266             : {
     267        4736 :         struct tevent_req *req = tevent_req_callback_data(
     268             :                 subreq, struct tevent_req);
     269        4736 :         struct wb_queryuser_state *state = tevent_req_data(
     270             :                 req, struct wb_queryuser_state);
     271        4736 :         struct wbint_userinfo *info = state->info;
     272             :         NTSTATUS status, result;
     273        4736 :         bool need_group_name = false;
     274        4736 :         const char *tmpl = NULL;
     275             : 
     276        4736 :         status = dcerpc_wbint_GetNssInfo_recv(subreq, info, &result);
     277        4736 :         TALLOC_FREE(subreq);
     278        4736 :         if (tevent_req_nterror(req, status)) {
     279           0 :                 D_WARNING("GetNssInfo failed with %s.\n", nt_errstr(status));
     280        4734 :                 return;
     281             :         }
     282             : 
     283        4736 :         if (NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) &&
     284           0 :             !state->tried_dclookup) {
     285           0 :                 D_DEBUG("GetNssInfo got DOMAIN_CONTROLLER_NOT_FOUND, calling wb_dsgetdcname_send()\n");
     286           0 :                 subreq = wb_dsgetdcname_send(
     287           0 :                         state, state->ev, state->info->domain_name, NULL, NULL,
     288             :                         DS_RETURN_DNS_NAME);
     289           0 :                 if (tevent_req_nomem(subreq, req)) {
     290           0 :                         return;
     291             :                 }
     292           0 :                 tevent_req_set_callback(subreq, wb_queryuser_got_dc, req);
     293           0 :                 return;
     294             :         }
     295             : 
     296             :         /*
     297             :          * Ignore failure in "result" here. We'll try to fill in stuff
     298             :          * that misses further down.
     299             :          */
     300             : 
     301        4736 :         if (state->info->primary_gid == (gid_t)-1) {
     302        4734 :                 D_DEBUG("Calling wb_sids2xids_send() to resolve primary gid.\n");
     303        4734 :                 subreq = wb_sids2xids_send(
     304        4734 :                         state, state->ev, &info->group_sid, 1);
     305        4734 :                 if (tevent_req_nomem(subreq, req)) {
     306           0 :                         return;
     307             :                 }
     308        4734 :                 tevent_req_set_callback(subreq, wb_queryuser_got_gid, req);
     309        4734 :                 return;
     310             :         }
     311             : 
     312           2 :         tmpl = lp_template_homedir();
     313           2 :         if(strstr_m(tmpl, "%g") || strstr_m(tmpl, "%G")) {
     314           0 :                 need_group_name = true;
     315             :         }
     316           2 :         tmpl = lp_template_shell();
     317           2 :         if(strstr_m(tmpl, "%g") || strstr_m(tmpl, "%G")) {
     318           0 :                 need_group_name = true;
     319             :         }
     320             : 
     321           2 :         if (need_group_name && state->info->primary_group_name == NULL) {
     322           0 :                 D_DEBUG("Calling wb_lookupsid_send() to resolve primary group name.\n");
     323           0 :                 subreq = wb_lookupsid_send(state, state->ev, &info->group_sid);
     324           0 :                 if (tevent_req_nomem(subreq, req)) {
     325           0 :                         return;
     326             :                 }
     327           0 :                 tevent_req_set_callback(subreq, wb_queryuser_got_group_name,
     328             :                                         req);
     329           0 :                 return;
     330             :         }
     331             : 
     332           2 :         NDR_PRINT_DEBUG_LEVEL(DBGLVL_DEBUG, wbint_userinfo, state->info);
     333           2 :         tevent_req_done(req);
     334             : }
     335             : 
     336           0 : static void wb_queryuser_got_dc(struct tevent_req *subreq)
     337             : {
     338           0 :         struct tevent_req *req = tevent_req_callback_data(
     339             :                 subreq, struct tevent_req);
     340           0 :         struct wb_queryuser_state *state = tevent_req_data(
     341             :                 req, struct wb_queryuser_state);
     342           0 :         struct wbint_userinfo *info = state->info;
     343             :         struct netr_DsRGetDCNameInfo *dcinfo;
     344           0 :         struct dcerpc_binding_handle *child_binding_handle = NULL;
     345             :         NTSTATUS status;
     346             : 
     347           0 :         status = wb_dsgetdcname_recv(subreq, state, &dcinfo);
     348           0 :         TALLOC_FREE(subreq);
     349           0 :         if (tevent_req_nterror(req, status)) {
     350           0 :                 D_WARNING("wb_dsgetdcname_recv() failed with %s.\n",
     351             :                           nt_errstr(status));
     352           0 :                 return;
     353             :         }
     354             : 
     355           0 :         state->tried_dclookup = true;
     356             : 
     357           0 :         D_DEBUG("Got DC name, calling wb_dsgetdcname_gencache_set().\n");
     358           0 :         status = wb_dsgetdcname_gencache_set(info->domain_name, dcinfo);
     359           0 :         if (tevent_req_nterror(req, status)) {
     360           0 :                 D_WARNING("wb_dsgetdcname_gencache_set() failed with %s.\n",
     361             :                           nt_errstr(status));
     362           0 :                 return;
     363             :         }
     364           0 :         NDR_PRINT_DEBUG_LEVEL(DBGLVL_DEBUG, wbint_userinfo, state->info);
     365             : 
     366             :         /*
     367             :          * Note wb_sids2xids_send/recv was called before,
     368             :          * so we're sure that wb_parent_idmap_setup_send/recv
     369             :          * was already called.
     370             :          */
     371           0 :         child_binding_handle = idmap_child_handle();
     372           0 :         subreq = dcerpc_wbint_GetNssInfo_send(
     373             :                 state, state->ev, child_binding_handle, info);
     374           0 :         if (tevent_req_nomem(subreq, req)) {
     375           0 :                 return;
     376             :         }
     377           0 :         tevent_req_set_callback(subreq, wb_queryuser_done, req);
     378             : }
     379             : 
     380        4734 : static void wb_queryuser_got_gid(struct tevent_req *subreq)
     381             : {
     382        4734 :         struct tevent_req *req = tevent_req_callback_data(
     383             :                 subreq, struct tevent_req);
     384        4734 :         struct wb_queryuser_state *state = tevent_req_data(
     385             :                 req, struct wb_queryuser_state);
     386             :         struct unixid xid;
     387             :         NTSTATUS status;
     388        4734 :         bool need_group_name = false;
     389        4734 :         const char *tmpl = NULL;
     390             :         struct dom_sid_buf buf;
     391             : 
     392        4734 :         status = wb_sids2xids_recv(subreq, &xid, 1);
     393        4734 :         TALLOC_FREE(subreq);
     394        4734 :         if (tevent_req_nterror(req, status)) {
     395           0 :                 D_WARNING("wb_sids2xids_recv() failed with %s.\n",
     396             :                           nt_errstr(status));
     397        1594 :                 return;
     398             :         }
     399             : 
     400        4734 :         D_DEBUG("Got XID %"PRIu32" with type %d.\n", xid.id, xid.type);
     401        4734 :         if ((xid.type != ID_TYPE_GID) && (xid.type != ID_TYPE_BOTH)) {
     402          30 :                 D_WARNING("Returning NT_STATUS_NO_SUCH_USER\n"
     403             :                           "xid.type must be ID_TYPE_UID or ID_TYPE_BOTH.\n");
     404          30 :                 tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
     405          30 :                 return;
     406             :         }
     407             : 
     408        4704 :         state->info->primary_gid = xid.id;
     409             : 
     410        4704 :         tmpl = lp_template_homedir();
     411        4704 :         if(strstr_m(tmpl, "%g") || strstr_m(tmpl, "%G")) {
     412        1564 :                 need_group_name = true;
     413             :         }
     414        4704 :         tmpl = lp_template_shell();
     415        4704 :         if(strstr_m(tmpl, "%g") || strstr_m(tmpl, "%G")) {
     416           0 :                 need_group_name = true;
     417             :         }
     418             : 
     419        4704 :         NDR_PRINT_DEBUG_LEVEL(DBGLVL_DEBUG, wbint_userinfo, state->info);
     420             : 
     421        4704 :         if (need_group_name && state->info->primary_group_name == NULL) {
     422        1564 :                 D_DEBUG("Calling wb_lookupsid_send for group SID %s.\n",
     423             :                           dom_sid_str_buf(&state->info->group_sid, &buf));
     424        1564 :                 subreq = wb_lookupsid_send(state, state->ev,
     425        1564 :                                            &state->info->group_sid);
     426        1564 :                 if (tevent_req_nomem(subreq, req)) {
     427           0 :                         return;
     428             :                 }
     429        1564 :                 tevent_req_set_callback(subreq, wb_queryuser_got_group_name,
     430             :                                         req);
     431        1564 :                 return;
     432             :         }
     433             : 
     434        3140 :         D_DEBUG("No need to lookup primary group name. Request is done!\n");
     435        3140 :         tevent_req_done(req);
     436             : }
     437             : 
     438        1564 : static void wb_queryuser_got_group_name(struct tevent_req *subreq)
     439             : {
     440        1564 :         struct tevent_req *req = tevent_req_callback_data(
     441             :                 subreq, struct tevent_req);
     442        1564 :         struct wb_queryuser_state *state = tevent_req_data(
     443             :                 req, struct wb_queryuser_state);
     444             :         enum lsa_SidType type;
     445             :         NTSTATUS status;
     446             :         const char *domain_name;
     447             : 
     448        1564 :         status = wb_lookupsid_recv(subreq, state->info, &type, &domain_name,
     449        1564 :                                    &state->info->primary_group_name);
     450        1564 :         TALLOC_FREE(subreq);
     451        1564 :         if (tevent_req_nterror(req, status)) {
     452           0 :                 D_WARNING("wb_lookupsid_recv() failed with %s.\n",
     453             :                           nt_errstr(status));
     454           0 :                 return;
     455             :         }
     456        1564 :         tevent_req_done(req);
     457             : }
     458             : 
     459        4784 : NTSTATUS wb_queryuser_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     460             :                            struct wbint_userinfo **pinfo)
     461             : {
     462        4784 :         struct wb_queryuser_state *state = tevent_req_data(
     463             :                 req, struct wb_queryuser_state);
     464             :         NTSTATUS status;
     465             : 
     466        4784 :         D_INFO("WB command queryuser end.\n");
     467        4784 :         NDR_PRINT_DEBUG_LEVEL(DBGLVL_INFO, wbint_userinfo, state->info);
     468        4784 :         if (tevent_req_is_nterror(req, &status)) {
     469          78 :                 return status;
     470             :         }
     471        4706 :         *pinfo = talloc_move(mem_ctx, &state->info);
     472        4706 :         return NT_STATUS_OK;
     473             : }

Generated by: LCOV version 1.13