r10504: - seperate implementation specific stuff, from the generic composite
[ira/wip.git] / source / winbind / wb_async_helpers.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Copyright (C) Volker Lendecke 2005
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 2 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, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20 /*
21   a composite API for finding a DC and its name
22 */
23
24 #include "includes.h"
25 #include "libcli/composite/composite.h"
26 #include "winbind/wb_async_helpers.h"
27
28 #include "librpc/gen_ndr/nbt.h"
29 #include "librpc/gen_ndr/samr.h"
30 #include "lib/messaging/irpc.h"
31 #include "librpc/gen_ndr/irpc.h"
32 #include "librpc/gen_ndr/ndr_irpc.h"
33
34 struct finddcs_state {
35         struct wb_finddcs *io;
36         struct composite_context *creq;
37
38         struct nbtd_getdcname *r;
39         struct irpc_request *ireq;
40 };
41
42 static void finddcs_getdc(struct irpc_request *ireq)
43 {
44         struct composite_context *c = talloc_get_type(ireq->async.private,
45                                                       struct composite_context);
46         struct finddcs_state *state = talloc_get_type(c->private_data,
47                                                       struct finddcs_state);
48
49         c->status = irpc_call_recv(ireq);
50         if (!NT_STATUS_IS_OK(c->status)) {
51                 goto done;
52         }
53
54         state->io->out.dcs[0].name = talloc_steal(state->io->out.dcs,
55                                                   state->r->out.dcname);
56
57         c->status = NT_STATUS_OK;
58         c->state = COMPOSITE_STATE_DONE;
59
60  done:
61         if (!NT_STATUS_IS_OK(c->status)) {
62                 c->state = COMPOSITE_STATE_ERROR;
63         }
64                 
65         if (c->state >= COMPOSITE_STATE_DONE &&
66             c->async.fn) {
67                 c->async.fn(c);
68         }
69 }
70
71 /*
72   called when name resolution is finished
73 */
74 static void finddcs_resolve(struct composite_context *res_ctx)
75 {
76         struct composite_context *c = talloc_get_type(res_ctx->async.private_data,
77                                                       struct composite_context);
78         struct finddcs_state *state = talloc_get_type(c->private_data,
79                                                       struct finddcs_state);
80         uint32_t *nbt_servers;
81
82         state->io->out.num_dcs = 1;
83         state->io->out.dcs = talloc_array(state, struct nbt_dc_name,
84                                           state->io->out.num_dcs);
85         if (state->io->out.dcs == NULL) {
86                 c->status = NT_STATUS_NO_MEMORY;
87                 goto done;
88         }
89
90         c->status = resolve_name_recv(res_ctx, state->io->out.dcs,
91                                       &state->io->out.dcs[0].address);
92         if (!NT_STATUS_IS_OK(c->status)) {
93                 goto done;
94         }
95
96         nbt_servers = irpc_servers_byname(state->io->in.msg_ctx, "nbt_server");
97         if ((nbt_servers == NULL) || (nbt_servers[0] == 0)) {
98                 c->status = NT_STATUS_NO_LOGON_SERVERS;
99                 goto done;
100         }
101
102         state->r = talloc(state, struct nbtd_getdcname);
103         if (state->r == NULL) {
104                 c->status = NT_STATUS_NO_MEMORY;
105                 goto done;
106         }
107
108         state->r->in.domainname = talloc_strdup(state->r, lp_workgroup());
109         state->r->in.ip_address = state->io->out.dcs[0].address;
110         state->r->in.my_computername = lp_netbios_name();
111         state->r->in.my_accountname = talloc_asprintf(state->r, "%s$",
112                                                       lp_netbios_name());
113         state->r->in.account_control = ACB_WSTRUST;
114         state->r->in.domain_sid = secrets_get_domain_sid(state->r,
115                                                          lp_workgroup());
116
117         if ((state->r->in.domainname == NULL) ||
118             (state->r->in.my_accountname == NULL)) {
119                 DEBUG(0, ("talloc failed\n"));
120                 c->status = NT_STATUS_NO_MEMORY;
121                 goto done;
122         }
123         if (state->r->in.domain_sid == NULL) {
124                 c->status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
125                 goto done;
126         }
127
128         state->ireq = irpc_call_send(state->io->in.msg_ctx, nbt_servers[0],
129                                      &dcerpc_table_irpc, DCERPC_NBTD_GETDCNAME,
130                                      state->r, state);
131         
132         if (state->ireq == NULL) {
133                 c->status = NT_STATUS_NO_MEMORY;
134                 goto done;
135         }
136
137         c->status = NT_STATUS_OK;
138         state->ireq->async.fn = finddcs_getdc;
139         state->ireq->async.private = c;
140
141  done:
142         if (!NT_STATUS_IS_OK(c->status)) {
143                 c->state = COMPOSITE_STATE_ERROR;
144         }
145                 
146         if (c->state >= COMPOSITE_STATE_DONE &&
147             c->async.fn) {
148                 c->async.fn(c);
149         }
150 }
151
152 struct composite_context *wb_finddcs_send(struct wb_finddcs *io,
153                                           struct event_context *event_ctx)
154 {
155         struct composite_context *c;
156         struct finddcs_state *state;
157         struct nbt_name name;
158
159         c = talloc_zero(NULL, struct composite_context);
160         if (c == NULL) goto failed;
161         c->state = COMPOSITE_STATE_IN_PROGRESS;
162         c->event_ctx = event_ctx;
163
164         state = talloc(c, struct finddcs_state);
165         if (state == NULL) goto failed;
166
167         state->io = io;
168
169         make_nbt_name(&name, io->in.domain, 0x1c);
170         state->creq = resolve_name_send(&name, c->event_ctx,
171                                         lp_name_resolve_order());
172
173         if (state->creq == NULL) goto failed;
174         state->creq->async.private_data = c;
175         state->creq->async.fn = finddcs_resolve;
176         c->private_data = state;
177
178         return c;
179 failed:
180         talloc_free(c);
181         return NULL;
182 }
183
184 NTSTATUS wb_finddcs_recv(struct composite_context *c, TALLOC_CTX *mem_ctx)
185 {
186         NTSTATUS status;
187
188         status = composite_wait(c);
189
190         if (NT_STATUS_IS_OK(status)) {
191                 struct finddcs_state *state = talloc_get_type(c->private_data,
192                                                               struct finddcs_state);
193                 talloc_steal(mem_ctx, state->io->out.dcs);
194         }
195
196         talloc_free(c);
197         return status;
198 }
199
200 NTSTATUS wb_finddcs(struct wb_finddcs *io, TALLOC_CTX *mem_ctx,
201                     struct event_context *ev)
202 {
203         struct composite_context *c = wb_finddcs_send(io, ev);
204         return wb_finddcs_recv(c, mem_ctx);
205 }