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