1/* 2 Unix SMB/CIFS implementation. 3 async gettoken 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_gettoken_state { 25 struct tevent_context *ev; 26 struct dom_sid usersid; 27 int num_sids; 28 struct dom_sid *sids; 29}; 30 31static bool wb_add_rids_to_sids(TALLOC_CTX *mem_ctx, 32 int *pnum_sids, struct dom_sid **psids, 33 const struct dom_sid *domain_sid, 34 int num_rids, uint32_t *rids); 35 36static void wb_gettoken_gotgroups(struct tevent_req *subreq); 37static void wb_gettoken_gotlocalgroups(struct tevent_req *subreq); 38static void wb_gettoken_gotbuiltins(struct tevent_req *subreq); 39 40struct tevent_req *wb_gettoken_send(TALLOC_CTX *mem_ctx, 41 struct tevent_context *ev, 42 const struct dom_sid *sid) 43{ 44 struct tevent_req *req, *subreq; 45 struct wb_gettoken_state *state; 46 struct winbindd_domain *domain; 47 48 req = tevent_req_create(mem_ctx, &state, struct wb_gettoken_state); 49 if (req == NULL) { 50 return NULL; 51 } 52 sid_copy(&state->usersid, sid); 53 state->ev = ev; 54 55 domain = find_domain_from_sid_noinit(sid); 56 if (domain == NULL) { 57 DEBUG(5, ("Could not find domain from SID %s\n", 58 sid_string_dbg(sid))); 59 tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER); 60 return tevent_req_post(req, ev); 61 } 62 63 if (lp_winbind_trusted_domains_only() && domain->primary) { 64 DEBUG(7, ("wb_gettoken: My domain -- rejecting getgroups() " 65 "for %s.\n", sid_string_tos(sid))); 66 tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER); 67 return tevent_req_post(req, ev); 68 } 69 70 subreq = wb_lookupusergroups_send(state, ev, domain, &state->usersid); 71 if (tevent_req_nomem(subreq, req)) { 72 return tevent_req_post(req, ev); 73 } 74 tevent_req_set_callback(subreq, wb_gettoken_gotgroups, req); 75 return req; 76} 77 78static void wb_gettoken_gotgroups(struct tevent_req *subreq) 79{ 80 struct tevent_req *req = tevent_req_callback_data( 81 subreq, struct tevent_req); 82 struct wb_gettoken_state *state = tevent_req_data( 83 req, struct wb_gettoken_state); 84 struct dom_sid *sids; 85 struct winbindd_domain *domain; 86 NTSTATUS status; 87 88 status = wb_lookupusergroups_recv(subreq, state, &state->num_sids, 89 &state->sids); 90 TALLOC_FREE(subreq); 91 if (!NT_STATUS_IS_OK(status)) { 92 tevent_req_nterror(req, status); 93 return; 94 } 95 96 sids = talloc_realloc(state, state->sids, struct dom_sid, 97 state->num_sids + 1); 98 if (tevent_req_nomem(sids, req)) { 99 return; 100 } 101 memmove(&sids[1], &sids[0], state->num_sids * sizeof(sids[0])); 102 sid_copy(&sids[0], &state->usersid); 103 state->num_sids += 1; 104 state->sids = sids; 105 106 /* 107 * Expand our domain's aliases 108 */ 109 domain = find_domain_from_sid_noinit(get_global_sam_sid()); 110 if (domain == NULL) { 111 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); 112 return; 113 } 114 115 subreq = wb_lookupuseraliases_send(state, state->ev, domain, 116 state->num_sids, state->sids); 117 if (tevent_req_nomem(subreq, req)) { 118 return; 119 } 120 tevent_req_set_callback(subreq, wb_gettoken_gotlocalgroups, req); 121} 122 123static void wb_gettoken_gotlocalgroups(struct tevent_req *subreq) 124{ 125 struct tevent_req *req = tevent_req_callback_data( 126 subreq, struct tevent_req); 127 struct wb_gettoken_state *state = tevent_req_data( 128 req, struct wb_gettoken_state); 129 uint32_t num_rids; 130 uint32_t *rids; 131 struct winbindd_domain *domain; 132 NTSTATUS status; 133 134 status = wb_lookupuseraliases_recv(subreq, state, &num_rids, &rids); 135 TALLOC_FREE(subreq); 136 if (!NT_STATUS_IS_OK(status)) { 137 tevent_req_nterror(req, status); 138 return; 139 } 140 domain = find_domain_from_sid_noinit(get_global_sam_sid()); 141 if (!wb_add_rids_to_sids(state, &state->num_sids, &state->sids, 142 &domain->sid, num_rids, rids)) { 143 tevent_req_nterror(req, NT_STATUS_NO_MEMORY); 144 return; 145 } 146 TALLOC_FREE(rids); 147 148 /* 149 * Now expand the builtin groups 150 */ 151 152 domain = find_builtin_domain(); 153 if (domain == NULL) { 154 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); 155 return; 156 } 157 158 subreq = wb_lookupuseraliases_send(state, state->ev, domain, 159 state->num_sids, state->sids); 160 if (tevent_req_nomem(subreq, req)) { 161 return; 162 } 163 tevent_req_set_callback(subreq, wb_gettoken_gotbuiltins, req); 164} 165 166static void wb_gettoken_gotbuiltins(struct tevent_req *subreq) 167{ 168 struct tevent_req *req = tevent_req_callback_data( 169 subreq, struct tevent_req); 170 struct wb_gettoken_state *state = tevent_req_data( 171 req, struct wb_gettoken_state); 172 uint32_t num_rids; 173 uint32_t *rids; 174 NTSTATUS status; 175 176 status = wb_lookupuseraliases_recv(subreq, state, &num_rids, &rids); 177 TALLOC_FREE(subreq); 178 if (!NT_STATUS_IS_OK(status)) { 179 tevent_req_nterror(req, status); 180 return; 181 } 182 if (!wb_add_rids_to_sids(state, &state->num_sids, &state->sids, 183 &global_sid_Builtin, num_rids, rids)) { 184 tevent_req_nterror(req, NT_STATUS_NO_MEMORY); 185 return; 186 } 187 tevent_req_done(req); 188} 189 190NTSTATUS wb_gettoken_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, 191 int *num_sids, struct dom_sid **sids) 192{ 193 struct wb_gettoken_state *state = tevent_req_data( 194 req, struct wb_gettoken_state); 195 NTSTATUS status; 196 197 if (tevent_req_is_nterror(req, &status)) { 198 return status; 199 } 200 *num_sids = state->num_sids; 201 *sids = talloc_move(mem_ctx, &state->sids); 202 return NT_STATUS_OK; 203} 204 205static bool wb_add_rids_to_sids(TALLOC_CTX *mem_ctx, 206 int *pnum_sids, struct dom_sid **psids, 207 const struct dom_sid *domain_sid, 208 int num_rids, uint32_t *rids) 209{ 210 struct dom_sid *sids; 211 int i; 212 213 sids = talloc_realloc(mem_ctx, *psids, struct dom_sid, 214 *pnum_sids + num_rids); 215 if (sids == NULL) { 216 return false; 217 } 218 for (i=0; i<num_rids; i++) { 219 sid_compose(&sids[i+*pnum_sids], domain_sid, rids[i]); 220 } 221 222 *pnum_sids += num_rids; 223 *psids = sids; 224 return true; 225} 226