LCOV - code coverage report
Current view: top level - source3/winbindd - wb_getgrsid.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 66 83 79.5 %
Date: 2024-06-13 04:01:37 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    async getgrsid
       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 "winbindd.h"
      22             : #include "librpc/gen_ndr/ndr_winbind_c.h"
      23             : #include "../libcli/security/security.h"
      24             : #include "lib/dbwrap/dbwrap_rbt.h"
      25             : 
      26             : struct wb_getgrsid_state {
      27             :         struct tevent_context *ev;
      28             :         struct dom_sid sid;
      29             :         int max_nesting;
      30             :         const char *domname;
      31             :         const char *name;
      32             :         enum lsa_SidType type;
      33             :         gid_t gid;
      34             :         struct db_context *members;
      35             : };
      36             : 
      37             : static void wb_getgrsid_lookupsid_done(struct tevent_req *subreq);
      38             : static void wb_getgrsid_sid2gid_done(struct tevent_req *subreq);
      39             : static void wb_getgrsid_got_members(struct tevent_req *subreq);
      40             : 
      41        2904 : struct tevent_req *wb_getgrsid_send(TALLOC_CTX *mem_ctx,
      42             :                                     struct tevent_context *ev,
      43             :                                     const struct dom_sid *group_sid,
      44             :                                     int max_nesting)
      45             : {
      46             :         struct tevent_req *req, *subreq;
      47             :         struct wb_getgrsid_state *state;
      48             :         struct dom_sid_buf buf;
      49             : 
      50        2904 :         req = tevent_req_create(mem_ctx, &state, struct wb_getgrsid_state);
      51        2904 :         if (req == NULL) {
      52           0 :                 return NULL;
      53             :         }
      54             : 
      55        2904 :         D_INFO("WB command getgrsid start.\nLooking up group SID %s.\n", dom_sid_str_buf(group_sid, &buf));
      56             : 
      57        2904 :         sid_copy(&state->sid, group_sid);
      58        2904 :         state->ev = ev;
      59        2904 :         state->max_nesting = max_nesting;
      60             : 
      61        2904 :         if (dom_sid_in_domain(&global_sid_Unix_Groups, group_sid)) {
      62             :                 /* unmapped Unix groups must be resolved locally */
      63           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
      64           0 :                 return tevent_req_post(req, ev);
      65             :         }
      66             : 
      67        2904 :         subreq = wb_lookupsid_send(state, ev, &state->sid);
      68        2904 :         if (tevent_req_nomem(subreq, req)) {
      69           0 :                 return tevent_req_post(req, ev);
      70             :         }
      71        2904 :         tevent_req_set_callback(subreq, wb_getgrsid_lookupsid_done, req);
      72        2904 :         return req;
      73             : }
      74             : 
      75        2904 : static void wb_getgrsid_lookupsid_done(struct tevent_req *subreq)
      76             : {
      77        2904 :         struct tevent_req *req = tevent_req_callback_data(
      78             :                 subreq, struct tevent_req);
      79        2904 :         struct wb_getgrsid_state *state = tevent_req_data(
      80             :                 req, struct wb_getgrsid_state);
      81             :         NTSTATUS status;
      82             : 
      83        2904 :         status = wb_lookupsid_recv(subreq, state, &state->type,
      84             :                                    &state->domname, &state->name);
      85        2904 :         TALLOC_FREE(subreq);
      86        2904 :         if (tevent_req_nterror(req, status)) {
      87           0 :                 return;
      88             :         }
      89             : 
      90        2904 :         switch (state->type) {
      91        2904 :         case SID_NAME_DOM_GRP:
      92             :         case SID_NAME_ALIAS:
      93             :         case SID_NAME_WKN_GRP:
      94             :         /*
      95             :          * also treat user-type SIDS (they might map to ID_TYPE_BOTH)
      96             :          */
      97             :         case SID_NAME_USER:
      98             :         case SID_NAME_COMPUTER:
      99        2904 :                 break;
     100           0 :         default:
     101           0 :                 tevent_req_nterror(req, NT_STATUS_NO_SUCH_GROUP);
     102           0 :                 return;
     103             :         }
     104             : 
     105        2904 :         subreq = wb_sids2xids_send(state, state->ev, &state->sid, 1);
     106        2904 :         if (tevent_req_nomem(subreq, req)) {
     107           0 :                 return;
     108             :         }
     109        2904 :         tevent_req_set_callback(subreq, wb_getgrsid_sid2gid_done, req);
     110             : }
     111             : 
     112        2904 : static void wb_getgrsid_sid2gid_done(struct tevent_req *subreq)
     113             : {
     114        2904 :         struct tevent_req *req = tevent_req_callback_data(
     115             :                 subreq, struct tevent_req);
     116        2904 :         struct wb_getgrsid_state *state = tevent_req_data(
     117             :                 req, struct wb_getgrsid_state);
     118             :         NTSTATUS status;
     119             :         struct unixid xids[1];
     120             : 
     121        2904 :         status = wb_sids2xids_recv(subreq, xids, ARRAY_SIZE(xids));
     122        2904 :         TALLOC_FREE(subreq);
     123        2904 :         if (tevent_req_nterror(req, status)) {
     124          10 :                 return;
     125             :         }
     126             : 
     127             :         /*
     128             :          * We are filtering further down in sids2xids, but that filtering
     129             :          * depends on the actual type of the sid handed in (as determined
     130             :          * by lookupsids). Here we need to filter for the type of object
     131             :          * actually requested, in this case uid.
     132             :          */
     133        2904 :         if (!(xids[0].type == ID_TYPE_GID || xids[0].type == ID_TYPE_BOTH)) {
     134           2 :                 tevent_req_nterror(req, NT_STATUS_NONE_MAPPED);
     135           2 :                 return;
     136             :         }
     137             : 
     138        2902 :         state->gid = (gid_t)xids[0].id;
     139             : 
     140        2902 :         if (state->type == SID_NAME_USER || state->type == SID_NAME_COMPUTER) {
     141             :                 /*
     142             :                  * special treatment for a user sid that is
     143             :                  * mapped to ID_TYPE_BOTH:
     144             :                  * create a group with the sid/xid as only member
     145             :                  */
     146             :                 const char *name;
     147             : 
     148           8 :                 if (xids[0].type != ID_TYPE_BOTH) {
     149           0 :                         tevent_req_nterror(req, NT_STATUS_NO_SUCH_GROUP);
     150           0 :                         return;
     151             :                 }
     152             : 
     153           8 :                 state->members = db_open_rbt(state);
     154           8 :                 if (tevent_req_nomem(state->members, req)) {
     155           0 :                         return;
     156             :                 }
     157             : 
     158           8 :                 name = fill_domain_username_talloc(talloc_tos(),
     159             :                                                    state->domname,
     160             :                                                    state->name,
     161             :                                                    true /* can_assume */);
     162           8 :                 if (tevent_req_nomem(name, req)) {
     163           0 :                         return;
     164             :                 }
     165             : 
     166           8 :                 status = add_member_to_db(state->members, &state->sid, name);
     167           8 :                 if (!NT_STATUS_IS_OK(status)) {
     168           0 :                         tevent_req_nterror(req, status);
     169           0 :                         return;
     170             :                 }
     171             : 
     172           8 :                 tevent_req_done(req);
     173           8 :                 return;
     174             :         }
     175             : 
     176             :         /*
     177             :          * the "regular" case of a group type sid.
     178             :          */
     179             : 
     180        2894 :         subreq = wb_group_members_send(state, state->ev, &state->sid,
     181             :                                        state->type, state->max_nesting);
     182        2894 :         if (tevent_req_nomem(subreq, req)) {
     183           0 :                 return;
     184             :         }
     185        2894 :         tevent_req_set_callback(subreq, wb_getgrsid_got_members, req);
     186             : }
     187             : 
     188        2894 : static void wb_getgrsid_got_members(struct tevent_req *subreq)
     189             : {
     190        2894 :         struct tevent_req *req = tevent_req_callback_data(
     191             :                 subreq, struct tevent_req);
     192        2894 :         struct wb_getgrsid_state *state = tevent_req_data(
     193             :                 req, struct wb_getgrsid_state);
     194             :         NTSTATUS status;
     195             : 
     196        2894 :         status = wb_group_members_recv(subreq, state, &state->members);
     197        2894 :         TALLOC_FREE(subreq);
     198        2894 :         if (tevent_req_nterror(req, status)) {
     199           0 :                 return;
     200             :         }
     201        2894 :         tevent_req_done(req);
     202             : }
     203             : 
     204        2904 : NTSTATUS wb_getgrsid_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     205             :                           const char **domname, const char **name, gid_t *gid,
     206             :                           struct db_context **members)
     207             : {
     208        2904 :         struct wb_getgrsid_state *state = tevent_req_data(
     209             :                 req, struct wb_getgrsid_state);
     210             :         NTSTATUS status;
     211             : 
     212        2904 :         D_INFO("WB command getgrsid end.\n");
     213        2904 :         if (tevent_req_is_nterror(req, &status)) {
     214           2 :                 D_WARNING("Failed with %s.\n", nt_errstr(status));
     215           2 :                 return status;
     216             :         }
     217        2902 :         *domname = talloc_move(mem_ctx, &state->domname);
     218        2902 :         *name = talloc_move(mem_ctx, &state->name);
     219        2902 :         *gid = state->gid;
     220        2902 :         *members = talloc_move(mem_ctx, &state->members);
     221        2902 :         return NT_STATUS_OK;
     222             : }

Generated by: LCOV version 1.13