2 Unix SMB/CIFS implementation.
4 Find and init a domain struct for a SID
6 Copyright (C) Volker Lendecke 2005
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 2 of the License, or
11 (at your option) any later version.
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.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "libcli/composite/composite.h"
25 #include "winbind/wb_server.h"
26 #include "smbd/service_stream.h"
27 #include "smbd/service_task.h"
28 #include "lib/events/events.h"
29 #include "librpc/gen_ndr/nbt.h"
30 #include "librpc/gen_ndr/ndr_netlogon.h"
31 #include "winbind/wb_async_helpers.h"
32 #include "include/dlinklist.h"
34 static const char *sam_name(void)
36 if (lp_server_role() == ROLE_STANDALONE) {
37 return lp_netbios_name();
39 return lp_workgroup();
42 static struct wbsrv_domain *find_primary_domain(struct wbsrv_service *service)
44 const char *my_domain_name = sam_name();
45 struct wbsrv_domain *domain;
47 for (domain = service->domains; domain!=NULL; domain = domain->next) {
48 if (strcasecmp(domain->name, my_domain_name) == 0) {
55 static struct wbsrv_domain *find_domain_from_sid(struct wbsrv_service *service,
56 const struct dom_sid *sid)
58 struct wbsrv_domain *domain;
60 for (domain = service->domains; domain!=NULL; domain = domain->next) {
61 if (dom_sid_equal(domain->sid, sid)) {
64 if (dom_sid_in_domain(domain->sid, sid)) {
71 struct sid2domain_state {
72 struct composite_context *ctx;
73 struct wbsrv_service *service;
74 const struct dom_sid *sid;
76 const char *domain_name;
78 struct dom_sid *domain_sid;
80 struct wbsrv_domain *my_domain;
81 struct wbsrv_domain *result;
83 struct netr_DsRGetDCName dsr_getdcname;
84 struct netr_GetAnyDCName getdcname;
87 static void sid2domain_recv_name(struct composite_context *ctx);
88 static void sid2domain_recv_dsr_dcname(struct rpc_request *req);
89 static void sid2domain_recv_dcname(struct composite_context *ctx);
90 static void sid2domain_recv_init(struct composite_context *ctx);
92 struct composite_context *wb_sid2domain_send(TALLOC_CTX *mem_ctx,
93 struct wbsrv_service *service,
94 const struct dom_sid *sid)
96 struct composite_context *result, *ctx;
97 struct sid2domain_state *state;
99 result = talloc_zero(mem_ctx, struct composite_context);
100 if (result == NULL) goto failed;
101 result->state = COMPOSITE_STATE_IN_PROGRESS;
102 result->async.fn = NULL;
103 result->event_ctx = service->task->event_ctx;
105 state = talloc(result, struct sid2domain_state);
106 if (state == NULL) goto failed;
108 result->private_data = state;
110 state->service = service;
111 state->sid = dom_sid_dup(state, sid);
112 if (state->sid == NULL) goto failed;
114 state->result = find_domain_from_sid(service, sid);
115 if (state->result != NULL) {
116 result->status = NT_STATUS_OK;
117 if (!state->result->initialized) {
118 ctx = wb_init_domain_send(service, state->result);
119 if (ctx == NULL) goto failed;
120 ctx->async.fn = sid2domain_recv_init;
121 ctx->async.private_data = state;
124 composite_trigger_done(result);
128 state->my_domain = find_primary_domain(service);
129 if (state->my_domain == NULL) {
130 result->status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
131 composite_trigger_error(result);
135 ctx = wb_cmd_lookupsid_send(state, service, state->sid);
136 if (ctx == NULL) goto failed;
137 ctx->async.fn = sid2domain_recv_name;
138 ctx->async.private_data = state;
146 static void sid2domain_recv_name(struct composite_context *ctx)
148 struct sid2domain_state *state =
149 talloc_get_type(ctx->async.private_data,
150 struct sid2domain_state);
151 struct rpc_request *req;
152 struct wb_sid_object *name;
154 state->ctx->status = wb_cmd_lookupsid_recv(ctx, state, &name);
155 if (!composite_is_ok(state->ctx)) return;
157 if (name->type == SID_NAME_UNKNOWN) {
158 composite_error(state->ctx, NT_STATUS_NO_SUCH_DOMAIN);
162 state->domain_name = name->domain;
163 state->domain_sid = dom_sid_dup(state, state->sid);
164 if (composite_nomem(state->domain_sid, state->ctx)) return;
166 if (name->type != SID_NAME_DOMAIN) {
167 state->domain_sid->num_auths -= 1;
170 state->dsr_getdcname.in.server_unc =
171 talloc_asprintf(state, "\\\\%s", state->my_domain->dcname);
172 if (composite_nomem(state->dsr_getdcname.in.server_unc,
175 state->dsr_getdcname.in.domain_name = state->domain_name;
176 state->dsr_getdcname.in.domain_guid = NULL;
177 state->dsr_getdcname.in.site_guid = NULL;
178 state->dsr_getdcname.in.flags = 0x40000000;
180 req = dcerpc_netr_DsRGetDCName_send(state->my_domain->netlogon_pipe,
181 state, &state->dsr_getdcname);
182 composite_continue_rpc(state->ctx, req, sid2domain_recv_dsr_dcname,
186 static void sid2domain_recv_dsr_dcname(struct rpc_request *req)
188 struct sid2domain_state *state =
189 talloc_get_type(req->async.private,
190 struct sid2domain_state);
191 struct composite_context *ctx;
193 state->ctx->status = dcerpc_ndr_request_recv(req);
194 if (!NT_STATUS_IS_OK(state->ctx->status)) {
195 DEBUG(9, ("dcerpc_ndr_request_recv returned %s\n",
196 nt_errstr(state->ctx->status)));
201 werror_to_ntstatus(state->dsr_getdcname.out.result);
202 if (!NT_STATUS_IS_OK(state->ctx->status)) {
203 DEBUG(9, ("dsrgetdcname returned %s\n",
204 nt_errstr(state->ctx->status)));
208 DEBUG(0, ("unc: %s, addr: %s, addr_type: %d, domain_name: %s, "
210 state->dsr_getdcname.out.info->dc_unc,
211 state->dsr_getdcname.out.info->dc_address,
212 state->dsr_getdcname.out.info->dc_address_type,
213 state->dsr_getdcname.out.info->domain_name,
214 state->dsr_getdcname.out.info->forest_name));
218 ctx = wb_cmd_getdcname_send(state, state->service, state->domain_name);
219 composite_continue(state->ctx, ctx, sid2domain_recv_dcname, state);
222 static void sid2domain_recv_dcname(struct composite_context *ctx)
224 struct sid2domain_state *state =
225 talloc_get_type(ctx->async.private_data,
226 struct sid2domain_state);
228 state->ctx->status = wb_cmd_getdcname_recv(ctx, state,
230 if (!composite_is_ok(state->ctx)) return;
232 state->result = talloc_zero(state, struct wbsrv_domain);
233 if (composite_nomem(state->result, state->ctx)) return;
235 state->result->name = talloc_steal(state->result, state->domain_name);
236 state->result->sid = talloc_steal(state->result, state->domain_sid);
237 state->result->dcname = talloc_steal(state->result, state->dc_name);
239 state->result->schannel_creds = cli_credentials_init(state->result);
240 if (composite_nomem(state->result->schannel_creds, state->ctx)) return;
241 cli_credentials_set_conf(state->result->schannel_creds);
242 cli_credentials_set_machine_account(state->result->schannel_creds);
244 talloc_steal(state->service, state->result);
245 DLIST_ADD(state->service->domains, state->result);
247 ctx = wb_init_domain_send(state->service, state->result);
248 composite_continue(state->ctx, ctx, sid2domain_recv_init, state);
251 static void sid2domain_recv_init(struct composite_context *ctx)
253 struct sid2domain_state *state =
254 talloc_get_type(ctx->async.private_data,
255 struct sid2domain_state);
257 state->ctx->status = wb_init_domain_recv(ctx);
258 if (!composite_is_ok(state->ctx)) {
259 DEBUG(10, ("Could not init domain\n"));
263 composite_done(state->ctx);
266 NTSTATUS wb_sid2domain_recv(struct composite_context *ctx,
267 struct wbsrv_domain **result)
269 NTSTATUS status = composite_wait(ctx);
270 if (NT_STATUS_IS_OK(status)) {
271 struct sid2domain_state *state =
272 talloc_get_type(ctx->private_data,
273 struct sid2domain_state);
274 *result = state->result;
280 NTSTATUS wb_sid2domain(TALLOC_CTX *mem_ctx, struct wbsrv_service *service,
281 const struct dom_sid *sid,
282 struct wbsrv_domain **result)
284 struct composite_context *c = wb_sid2domain_send(mem_ctx, service,
286 return wb_sid2domain_recv(c, result);