2 Unix SMB/CIFS implementation.
4 Copyright (C) Rafal Szczesniak 2005
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.
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.
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.
22 a composite function for name resolving
26 #include "lib/events/events.h"
27 #include "libnet/libnet.h"
28 #include "libcli/composite/composite.h"
29 #include "auth/credentials/credentials.h"
30 #include "lib/messaging/messaging.h"
31 #include "lib/messaging/irpc.h"
32 #include "libcli/resolve/resolve.h"
33 #include "libcli/finddcs.h"
34 #include "libcli/security/security.h"
35 #include "librpc/gen_ndr/lsa.h"
36 #include "librpc/gen_ndr/ndr_lsa_c.h"
39 struct nbt_name hostname
;
44 static void continue_name_resolved(struct composite_context
*ctx
);
48 * Sends asynchronous Lookup request
50 * @param io arguments and result of the call
53 struct composite_context
*libnet_Lookup_send(struct libnet_context
*ctx
,
54 struct libnet_Lookup
*io
)
56 struct composite_context
*c
;
57 struct lookup_state
*s
;
58 struct composite_context
*cresolve_req
;
61 /* allocate context and state structures */
62 c
= composite_create(ctx
, ctx
->event_ctx
);
63 if (c
== NULL
) return NULL
;
65 s
= talloc_zero(c
, struct lookup_state
);
66 if (composite_nomem(s
, c
)) return c
;
70 if (io
== NULL
|| io
->in
.hostname
== NULL
) {
71 composite_error(c
, NT_STATUS_INVALID_PARAMETER
);
76 s
->hostname
.name
= talloc_strdup(s
, io
->in
.hostname
);
77 if (composite_nomem(s
->hostname
.name
, c
)) return c
;
79 s
->hostname
.type
= io
->in
.type
;
80 s
->hostname
.scope
= NULL
;
82 /* name resolution methods */
84 methods
= io
->in
.methods
;
86 methods
= ctx
->name_res_methods
;
89 /* send resolve request */
90 cresolve_req
= resolve_name_send(&s
->hostname
, c
->event_ctx
, methods
);
91 if (composite_nomem(cresolve_req
, c
)) return c
;
93 composite_continue(c
, cresolve_req
, continue_name_resolved
, c
);
98 static void continue_name_resolved(struct composite_context
*ctx
)
100 struct composite_context
*c
;
101 struct lookup_state
*s
;
103 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
104 s
= talloc_get_type(c
->private_data
, struct lookup_state
);
106 c
->status
= resolve_name_recv(ctx
, s
, &s
->address
);
113 * Waits for and receives results of asynchronous Lookup call
115 * @param c composite context returned by asynchronous Lookup call
116 * @param mem_ctx memory context of the call
117 * @param io pointer to results (and arguments) of the call
118 * @return nt status code of execution
121 NTSTATUS
libnet_Lookup_recv(struct composite_context
*c
, TALLOC_CTX
*mem_ctx
,
122 struct libnet_Lookup
*io
)
125 struct lookup_state
*s
;
127 status
= composite_wait(c
);
128 if (NT_STATUS_IS_OK(status
)) {
129 s
= talloc_get_type(c
->private_data
, struct lookup_state
);
131 io
->out
.address
= str_list_make(mem_ctx
, s
->address
, NULL
);
132 NT_STATUS_HAVE_NO_MEMORY(io
->out
.address
);
141 * Synchronous version of Lookup call
143 * @param mem_ctx memory context for the call
144 * @param io arguments and results of the call
145 * @return nt status code of execution
148 NTSTATUS
libnet_Lookup(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
,
149 struct libnet_Lookup
*io
)
151 struct composite_context
*c
= libnet_Lookup_send(ctx
, io
);
152 return libnet_Lookup_recv(c
, mem_ctx
, io
);
157 * Shortcut functions to find common types of name
158 * (and skip nbt name type argument)
163 * Sends asynchronous LookupHost request
165 struct composite_context
* libnet_LookupHost_send(struct libnet_context
*ctx
,
166 struct libnet_Lookup
*io
)
168 io
->in
.type
= NBT_NAME_SERVER
;
169 return libnet_Lookup_send(ctx
, io
);
175 * Synchronous version of LookupHost call
177 NTSTATUS
libnet_LookupHost(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
,
178 struct libnet_Lookup
*io
)
180 struct composite_context
*c
= libnet_LookupHost_send(ctx
, io
);
181 return libnet_Lookup_recv(c
, mem_ctx
, io
);
186 * Sends asynchronous LookupDCs request
188 struct composite_context
* libnet_LookupDCs_send(struct libnet_context
*ctx
,
190 struct libnet_LookupDCs
*io
)
192 struct composite_context
*c
;
193 struct messaging_context
*msg_ctx
= messaging_client_init(mem_ctx
, ctx
->event_ctx
);
195 c
= finddcs_send(mem_ctx
, io
->in
.domain_name
, io
->in
.name_type
,
196 NULL
, ctx
->name_res_methods
, ctx
->event_ctx
, msg_ctx
);
201 * Waits for and receives results of asynchronous Lookup call
203 * @param c composite context returned by asynchronous Lookup call
204 * @param mem_ctx memory context of the call
205 * @param io pointer to results (and arguments) of the call
206 * @return nt status code of execution
209 NTSTATUS
libnet_LookupDCs_recv(struct composite_context
*c
, TALLOC_CTX
*mem_ctx
,
210 struct libnet_LookupDCs
*io
)
213 status
= finddcs_recv(c
, mem_ctx
, &io
->out
.num_dcs
, &io
->out
.dcs
);
214 if (!NT_STATUS_IS_OK(status
)) {
222 * Synchronous version of LookupDCs
224 NTSTATUS
libnet_LookupDCs(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
,
225 struct libnet_LookupDCs
*io
)
227 struct composite_context
*c
= libnet_LookupDCs_send(ctx
, mem_ctx
, io
);
228 return libnet_LookupDCs_recv(c
, mem_ctx
, io
);
232 struct lookup_name_state
{
233 struct libnet_context
*ctx
;
236 struct libnet_DomainOpen domopen
;
237 struct lsa_LookupNames lookup
;
238 struct lsa_TransSidArray sids
;
239 struct lsa_String
*names
;
241 /* information about the progress */
242 void (*monitor_fn
)(struct monitor_msg
*);
246 static bool prepare_lookup_params(struct libnet_context
*ctx
,
247 struct composite_context
*c
,
248 struct lookup_name_state
*s
);
249 static void continue_lookup_name(struct composite_context
*ctx
);
250 static void continue_name_found(struct rpc_request
*req
);
253 struct composite_context
* libnet_LookupName_send(struct libnet_context
*ctx
,
255 struct libnet_LookupName
*io
,
256 void (*monitor
)(struct monitor_msg
*))
258 struct composite_context
*c
;
259 struct lookup_name_state
*s
;
260 struct rpc_request
*lookup_req
;
261 BOOL prereq_met
= False
;
263 c
= composite_create(mem_ctx
, ctx
->event_ctx
);
264 if (c
== NULL
) return NULL
;
266 s
= talloc_zero(c
, struct lookup_name_state
);
267 if (composite_nomem(s
, c
)) return c
;
271 s
->name
= talloc_strdup(c
, io
->in
.name
);
272 s
->monitor_fn
= monitor
;
275 prereq_met
= lsa_domain_opened(ctx
, io
->in
.domain_name
, &c
, &s
->domopen
,
276 continue_lookup_name
, monitor
);
277 if (!prereq_met
) return c
;
279 if (!prepare_lookup_params(ctx
, c
, s
)) return c
;
281 lookup_req
= dcerpc_lsa_LookupNames_send(ctx
->lsa
.pipe
, c
, &s
->lookup
);
282 if (composite_nomem(lookup_req
, c
)) return c
;
284 composite_continue_rpc(c
, lookup_req
, continue_name_found
, c
);
289 static bool prepare_lookup_params(struct libnet_context
*ctx
,
290 struct composite_context
*c
,
291 struct lookup_name_state
*s
)
293 const int single_name
= 1;
298 s
->names
= talloc_array(ctx
, struct lsa_String
, single_name
);
299 if (composite_nomem(s
->names
, c
)) return false;
300 s
->names
[0].string
= s
->name
;
302 s
->lookup
.in
.handle
= &ctx
->lsa
.handle
;
303 s
->lookup
.in
.num_names
= single_name
;
304 s
->lookup
.in
.names
= s
->names
;
305 s
->lookup
.in
.sids
= &s
->sids
;
306 s
->lookup
.in
.level
= 1;
307 s
->lookup
.in
.count
= &s
->count
;
308 s
->lookup
.out
.count
= &s
->count
;
309 s
->lookup
.out
.sids
= &s
->sids
;
315 static void continue_lookup_name(struct composite_context
*ctx
)
317 struct composite_context
*c
;
318 struct lookup_name_state
*s
;
319 struct rpc_request
*lookup_req
;
321 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
322 s
= talloc_get_type(c
->private_data
, struct lookup_name_state
);
324 c
->status
= libnet_DomainOpen_recv(ctx
, s
->ctx
, c
, &s
->domopen
);
325 if (!composite_is_ok(c
)) return;
327 if (!prepare_lookup_params(s
->ctx
, c
, s
)) return;
329 lookup_req
= dcerpc_lsa_LookupNames_send(s
->ctx
->lsa
.pipe
, c
, &s
->lookup
);
330 if (composite_nomem(lookup_req
, c
)) return;
332 composite_continue_rpc(c
, lookup_req
, continue_name_found
, c
);
336 static void continue_name_found(struct rpc_request
*req
)
338 struct composite_context
*c
;
339 struct lookup_name_state
*s
;
341 c
= talloc_get_type(req
->async
.private_data
, struct composite_context
);
342 s
= talloc_get_type(c
->private_data
, struct lookup_name_state
);
344 c
->status
= dcerpc_ndr_request_recv(req
);
345 if (!composite_is_ok(c
)) return;
347 c
->status
= s
->lookup
.out
.result
;
348 if (!composite_is_ok(c
)) return;
354 NTSTATUS
libnet_LookupName_recv(struct composite_context
*c
, TALLOC_CTX
*mem_ctx
,
355 struct libnet_LookupName
*io
)
358 struct lookup_name_state
*s
;
360 status
= composite_wait(c
);
362 if (NT_STATUS_IS_OK(status
)) {
363 s
= talloc_get_type(c
->private_data
, struct lookup_name_state
);
367 io
->out
.sidstr
= NULL
;
369 if (*s
->lookup
.out
.count
> 0) {
370 struct lsa_RefDomainList
*domains
= s
->lookup
.out
.domains
;
371 struct lsa_TransSidArray
*sids
= s
->lookup
.out
.sids
;
373 if (domains
== NULL
|| sids
== NULL
) {
374 status
= NT_STATUS_UNSUCCESSFUL
;
375 io
->out
.error_string
= talloc_asprintf(mem_ctx
, "Error: %s", nt_errstr(status
));
379 if (sids
->count
> 0) {
380 io
->out
.rid
= sids
->sids
[0].rid
;
381 io
->out
.sid_type
= sids
->sids
[0].sid_type
;
382 if (domains
->count
> 0) {
383 io
->out
.sid
= dom_sid_add_rid(mem_ctx
, domains
->domains
[0].sid
, io
->out
.rid
);
384 NT_STATUS_HAVE_NO_MEMORY(io
->out
.sid
);
385 io
->out
.sidstr
= dom_sid_string(mem_ctx
, io
->out
.sid
);
386 NT_STATUS_HAVE_NO_MEMORY(io
->out
.sidstr
);
391 io
->out
.error_string
= talloc_strdup(mem_ctx
, "Success");
393 } else if (!NT_STATUS_IS_OK(status
)) {
394 io
->out
.error_string
= talloc_asprintf(mem_ctx
, "Error: %s", nt_errstr(status
));
403 NTSTATUS
libnet_LookupName(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
,
404 struct libnet_LookupName
*io
)
406 struct composite_context
*c
;
408 c
= libnet_LookupName_send(ctx
, mem_ctx
, io
, NULL
);
409 return libnet_LookupName_recv(c
, mem_ctx
, io
);