1/* 2 Unix SMB/CIFS implementation. 3 async sid2gid 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/cli_wbint.h" 23 24struct wb_sid2gid_state { 25 struct tevent_context *ev; 26 struct dom_sid sid; 27 char *dom_name; 28 uint64 gid64; 29 gid_t gid; 30}; 31 32static void wb_sid2gid_lookup_done(struct tevent_req *subreq); 33static void wb_sid2gid_done(struct tevent_req *subreq); 34 35 36struct tevent_req *wb_sid2gid_send(TALLOC_CTX *mem_ctx, 37 struct tevent_context *ev, 38 const struct dom_sid *sid) 39{ 40 struct tevent_req *req, *subreq; 41 struct wb_sid2gid_state *state; 42 bool expired; 43 44 req = tevent_req_create(mem_ctx, &state, struct wb_sid2gid_state); 45 if (req == NULL) { 46 return NULL; 47 } 48 sid_copy(&state->sid, sid); 49 state->ev = ev; 50 51 if (winbindd_use_idmap_cache() 52 && idmap_cache_find_sid2gid(sid, &state->gid, &expired)) { 53 54 DEBUG(10, ("idmap_cache_find_sid2gid found %d%s\n", 55 (int)state->gid, expired ? " (expired)": "")); 56 57 if (!expired || is_domain_offline(find_our_domain())) { 58 if (state->gid == -1) { 59 tevent_req_nterror(req, NT_STATUS_NONE_MAPPED); 60 } else { 61 tevent_req_done(req); 62 } 63 return tevent_req_post(req, ev); 64 } 65 } 66 67 /* 68 * We need to make sure the sid is of the right type to not flood 69 * idmap with wrong entries 70 */ 71 72 subreq = wb_lookupsid_send(state, ev, &state->sid); 73 if (tevent_req_nomem(subreq, req)) { 74 return tevent_req_post(req, ev); 75 } 76 tevent_req_set_callback(subreq, wb_sid2gid_lookup_done, req); 77 return req; 78} 79 80static void wb_sid2gid_lookup_done(struct tevent_req *subreq) 81{ 82 struct tevent_req *req = tevent_req_callback_data( 83 subreq, struct tevent_req); 84 struct wb_sid2gid_state *state = tevent_req_data( 85 req, struct wb_sid2gid_state); 86 struct winbindd_domain *domain; 87 const char *domname; 88 const char *name; 89 enum lsa_SidType type; 90 NTSTATUS status; 91 struct winbindd_child *child; 92 93 status = wb_lookupsid_recv(subreq, talloc_tos(), &type, &domname, 94 &name); 95 if (!NT_STATUS_IS_OK(status)) { 96 tevent_req_nterror(req, status); 97 return; 98 } 99 100 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) 101 && (type != SID_NAME_WKN_GRP)) { 102 DEBUG(5, ("Sid %s is not a group.\n", 103 sid_string_dbg(&state->sid))); 104 /* 105 * We have to set the cache ourselves here, the child 106 * which is normally responsible was not queried yet. 107 */ 108 idmap_cache_set_sid2gid(&state->sid, -1); 109 tevent_req_nterror(req, NT_STATUS_INVALID_SID); 110 return; 111 } 112 113 domain = find_domain_from_sid_noinit(&state->sid); 114 115 /* 116 * TODO: Issue a gettrustinfo here in case we don't have "domain" yet? 117 */ 118 119 if ((domain != NULL) && domain->have_idmap_config) { 120 state->dom_name = domain->name; 121 } else { 122 state->dom_name = NULL; 123 } 124 125 child = idmap_child(); 126 127 subreq = rpccli_wbint_Sid2Gid_send(state, state->ev, child->rpccli, 128 state->dom_name, &state->sid, 129 &state->gid64); 130 if (tevent_req_nomem(subreq, req)) { 131 return; 132 } 133 tevent_req_set_callback(subreq, wb_sid2gid_done, req); 134} 135 136static void wb_sid2gid_done(struct tevent_req *subreq) 137{ 138 struct tevent_req *req = tevent_req_callback_data( 139 subreq, struct tevent_req); 140 struct wb_sid2gid_state *state = tevent_req_data( 141 req, struct wb_sid2gid_state); 142 NTSTATUS status, result; 143 144 status = rpccli_wbint_Sid2Gid_recv(subreq, state, &result); 145 TALLOC_FREE(subreq); 146 if (!NT_STATUS_IS_OK(status)) { 147 tevent_req_nterror(req, status); 148 return; 149 } 150 if (!NT_STATUS_IS_OK(result)) { 151 tevent_req_nterror(req, result); 152 return; 153 } 154 155 state->gid = state->gid64; 156 tevent_req_done(req); 157} 158 159NTSTATUS wb_sid2gid_recv(struct tevent_req *req, gid_t *gid) 160{ 161 struct wb_sid2gid_state *state = tevent_req_data( 162 req, struct wb_sid2gid_state); 163 NTSTATUS status; 164 165 if (tevent_req_is_nterror(req, &status)) { 166 return status; 167 } 168 *gid = state->gid; 169 return NT_STATUS_OK; 170} 171