1/* 2 Unix SMB/CIFS implementation. 3 4 Find and init a domain struct for a SID 5 6 Copyright (C) Volker Lendecke 2005 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20*/ 21 22#include "includes.h" 23#include "libcli/composite/composite.h" 24#include "winbind/wb_server.h" 25#include "smbd/service_task.h" 26#include "winbind/wb_async_helpers.h" 27#include "libcli/security/security.h" 28#include "../lib/util/dlinklist.h" 29#include "param/param.h" 30 31static struct wbsrv_domain *find_domain_from_sid(struct wbsrv_service *service, 32 const struct dom_sid *sid) 33{ 34 struct wbsrv_domain *domain; 35 36 for (domain = service->domains; domain!=NULL; domain = domain->next) { 37 if (dom_sid_equal(domain->info->sid, sid)) { 38 break; 39 } 40 if (dom_sid_in_domain(domain->info->sid, sid)) { 41 break; 42 } 43 } 44 return domain; 45} 46 47struct sid2domain_state { 48 struct composite_context *ctx; 49 struct wbsrv_service *service; 50 struct dom_sid *sid; 51 52 struct wbsrv_domain *domain; 53}; 54 55static void sid2domain_recv_dom_info(struct composite_context *ctx); 56static void sid2domain_recv_name(struct composite_context *ctx); 57static void sid2domain_recv_trusted_dom_info(struct composite_context *ctx); 58static void sid2domain_recv_init(struct composite_context *ctx); 59 60struct composite_context *wb_sid2domain_send(TALLOC_CTX *mem_ctx, 61 struct wbsrv_service *service, 62 const struct dom_sid *sid) 63{ 64 struct composite_context *result, *ctx; 65 struct sid2domain_state *state; 66 67 result = composite_create(mem_ctx, service->task->event_ctx); 68 if (result == NULL) goto failed; 69 70 state = talloc(result, struct sid2domain_state); 71 if (state == NULL) goto failed; 72 state->ctx = result; 73 result->private_data = state; 74 75 state->service = service; 76 state->sid = dom_sid_dup(state, sid); 77 if (state->sid == NULL) goto failed; 78 79 state->domain = find_domain_from_sid(service, sid); 80 if (state->domain != NULL) { 81 result->status = NT_STATUS_OK; 82 composite_done(result); 83 return result; 84 } 85 86 if (dom_sid_equal(service->primary_sid, sid) || 87 dom_sid_in_domain(service->primary_sid, sid)) { 88 ctx = wb_get_dom_info_send(state, service, lp_workgroup(service->task->lp_ctx), 89 service->primary_sid); 90 if (ctx == NULL) goto failed; 91 ctx->async.fn = sid2domain_recv_dom_info; 92 ctx->async.private_data = state; 93 return result; 94 } 95 96 ctx = wb_cmd_lookupsid_send(state, service, state->sid); 97 if (ctx == NULL) goto failed; 98 composite_continue(result, ctx, sid2domain_recv_name, state); 99 100 return result; 101 102 failed: 103 talloc_free(result); 104 return NULL; 105 106} 107 108static void sid2domain_recv_dom_info(struct composite_context *ctx) 109{ 110 struct sid2domain_state *state = 111 talloc_get_type(ctx->async.private_data, 112 struct sid2domain_state); 113 struct wb_dom_info *info; 114 115 state->ctx->status = wb_get_dom_info_recv(ctx, state, &info); 116 if (!composite_is_ok(state->ctx)) return; 117 118 ctx = wb_init_domain_send(state, state->service, info); 119 120 composite_continue(state->ctx, ctx, sid2domain_recv_init, state); 121} 122 123static void sid2domain_recv_name(struct composite_context *ctx) 124{ 125 struct sid2domain_state *state = 126 talloc_get_type(ctx->async.private_data, 127 struct sid2domain_state); 128 struct wb_sid_object *name; 129 130 state->ctx->status = wb_cmd_lookupsid_recv(ctx, state, &name); 131 if (!composite_is_ok(state->ctx)) return; 132 133 if (name->type == SID_NAME_UNKNOWN) { 134 composite_error(state->ctx, NT_STATUS_NO_SUCH_DOMAIN); 135 return; 136 } 137 138 if (name->type != SID_NAME_DOMAIN) { 139 state->sid->num_auths -= 1; 140 } 141 142 ctx = wb_trusted_dom_info_send(state, state->service, name->domain, 143 state->sid); 144 145 composite_continue(state->ctx, ctx, sid2domain_recv_trusted_dom_info, 146 state); 147} 148 149static void sid2domain_recv_trusted_dom_info(struct composite_context *ctx) 150{ 151 struct sid2domain_state *state = 152 talloc_get_type(ctx->async.private_data, 153 struct sid2domain_state); 154 struct wb_dom_info *info; 155 156 state->ctx->status = wb_trusted_dom_info_recv(ctx, state, &info); 157 if (!composite_is_ok(state->ctx)) return; 158 159 ctx = wb_init_domain_send(state, state->service, info); 160 161 composite_continue(state->ctx, ctx, sid2domain_recv_init, state); 162} 163 164static void sid2domain_recv_init(struct composite_context *ctx) 165{ 166 struct sid2domain_state *state = 167 talloc_get_type(ctx->async.private_data, 168 struct sid2domain_state); 169 struct wbsrv_domain *existing; 170 171 state->ctx->status = wb_init_domain_recv(ctx, state, 172 &state->domain); 173 if (!composite_is_ok(state->ctx)) { 174 DEBUG(10, ("Could not init domain\n")); 175 return; 176 } 177 178 existing = find_domain_from_sid(state->service, state->sid); 179 if (existing != NULL) { 180 DEBUG(5, ("Initialized domain twice, dropping second one\n")); 181 talloc_free(state->domain); 182 state->domain = existing; 183 } 184 185 talloc_steal(state->service, state->domain); 186 DLIST_ADD(state->service->domains, state->domain); 187 188 composite_done(state->ctx); 189} 190 191NTSTATUS wb_sid2domain_recv(struct composite_context *ctx, 192 struct wbsrv_domain **result) 193{ 194 NTSTATUS status = composite_wait(ctx); 195 if (NT_STATUS_IS_OK(status)) { 196 struct sid2domain_state *state = 197 talloc_get_type(ctx->private_data, 198 struct sid2domain_state); 199 *result = state->domain; 200 } 201 talloc_free(ctx); 202 return status; 203} 204 205NTSTATUS wb_sid2domain(TALLOC_CTX *mem_ctx, struct wbsrv_service *service, 206 const struct dom_sid *sid, 207 struct wbsrv_domain **result) 208{ 209 struct composite_context *c = wb_sid2domain_send(mem_ctx, service, 210 sid); 211 return wb_sid2domain_recv(c, result); 212} 213