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;
84 static void sid2domain_recv_name(struct composite_context *ctx);
85 static void sid2domain_recv_dcname(struct composite_context *ctx);
86 static void sid2domain_recv_init(struct composite_context *ctx);
88 struct composite_context *wb_sid2domain_send(struct wbsrv_service *service,
89 const struct dom_sid *sid)
91 struct composite_context *result, *ctx;
92 struct sid2domain_state *state;
94 result = talloc_zero(NULL, struct composite_context);
95 if (result == NULL) goto failed;
96 result->state = COMPOSITE_STATE_IN_PROGRESS;
97 result->async.fn = NULL;
98 result->event_ctx = service->task->event_ctx;
100 state = talloc(result, struct sid2domain_state);
101 if (state == NULL) goto failed;
103 result->private_data = state;
105 state->service = service;
106 state->sid = dom_sid_dup(state, sid);
107 if (state->sid == NULL) goto failed;
109 state->result = find_domain_from_sid(service, sid);
110 if (state->result != NULL) {
111 result->status = NT_STATUS_OK;
112 if (!state->result->initialized) {
113 ctx = wb_init_domain_send(state->result,
114 service->task->event_ctx,
115 service->task->msg_ctx);
116 if (ctx == NULL) goto failed;
117 ctx->async.fn = sid2domain_recv_init;
118 ctx->async.private_data = state;
121 composite_trigger_done(result);
125 state->my_domain = find_primary_domain(service);
126 if (state->my_domain == NULL) {
127 result->status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
128 composite_trigger_error(result);
132 ctx = wb_cmd_lookupsid_send(service, state->my_domain, state->sid);
133 if (ctx == NULL) goto failed;
134 ctx->async.fn = sid2domain_recv_name;
135 ctx->async.private_data = state;
143 static void sid2domain_recv_name(struct composite_context *ctx)
145 struct sid2domain_state *state =
146 talloc_get_type(ctx->async.private_data,
147 struct sid2domain_state);
148 struct wb_sid_object *name;
150 state->ctx->status = wb_cmd_lookupsid_recv(ctx, state, &name);
151 if (!composite_is_ok(state->ctx)) return;
153 if (name->type == SID_NAME_UNKNOWN) {
154 composite_error(state->ctx, NT_STATUS_NO_SUCH_DOMAIN);
158 state->domain_name = name->domain;
159 state->domain_sid = dom_sid_dup(state, state->sid);
160 if (name->type != SID_NAME_DOMAIN) {
161 state->domain_sid->num_auths -= 1;
164 ctx = wb_cmd_getdcname_send(state->service, state->my_domain,
166 composite_continue(state->ctx, ctx, sid2domain_recv_dcname, state);
169 static void sid2domain_recv_dcname(struct composite_context *ctx)
171 struct sid2domain_state *state =
172 talloc_get_type(ctx->async.private_data,
173 struct sid2domain_state);
175 state->ctx->status = wb_cmd_getdcname_recv(ctx, state,
177 if (!composite_is_ok(state->ctx)) return;
179 state->result = talloc_zero(state, struct wbsrv_domain);
180 if (composite_nomem(state->result, state->ctx)) return;
182 state->result->name = talloc_steal(state->result, state->domain_name);
183 state->result->sid = talloc_steal(state->result, state->domain_sid);
184 state->result->dcname = talloc_steal(state->result, state->dc_name);
186 state->result->schannel_creds = cli_credentials_init(state->result);
187 if (composite_nomem(state->result->schannel_creds, state->ctx)) return;
188 cli_credentials_set_conf(state->result->schannel_creds);
189 cli_credentials_set_anonymous(state->result->schannel_creds);
191 talloc_steal(state->service, state->result);
192 DLIST_ADD(state->service->domains, state->result);
194 ctx = wb_init_domain_send(state->result,
195 state->service->task->event_ctx,
196 state->service->task->msg_ctx);
197 composite_continue(state->ctx, ctx, sid2domain_recv_init, state);
200 static void sid2domain_recv_init(struct composite_context *ctx)
202 struct sid2domain_state *state =
203 talloc_get_type(ctx->async.private_data,
204 struct sid2domain_state);
206 state->ctx->status = wb_init_domain_recv(ctx);
207 if (!composite_is_ok(state->ctx)) return;
209 composite_done(state->ctx);
212 NTSTATUS wb_sid2domain_recv(struct composite_context *ctx,
213 struct wbsrv_domain **result)
215 NTSTATUS status = composite_wait(ctx);
216 if (NT_STATUS_IS_OK(status)) {
217 struct sid2domain_state *state =
218 talloc_get_type(ctx->private_data,
219 struct sid2domain_state);
220 *result = state->result;
226 NTSTATUS wb_sid2domain(struct wbsrv_service *service,
227 const struct dom_sid *sid,
228 struct wbsrv_domain **result)
230 struct composite_context *c = wb_sid2domain_send(service, sid);
231 return wb_sid2domain_recv(c, result);