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 3 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, see <http://www.gnu.org/licenses/>.
21 a composite function for name resolving
25 #include "libnet/libnet.h"
26 #include "libcli/composite/composite.h"
27 #include "auth/credentials/credentials.h"
28 #include "libcli/resolve/resolve.h"
29 #include "libcli/finddc.h"
30 #include "libcli/security/security.h"
31 #include "librpc/gen_ndr/ndr_lsa_c.h"
32 #include "param/param.h"
35 struct nbt_name hostname
;
40 static void continue_name_resolved(struct composite_context
*ctx
);
44 * Sends asynchronous Lookup request
46 * @param io arguments and result of the call
49 struct composite_context
*libnet_Lookup_send(struct libnet_context
*ctx
,
51 struct libnet_Lookup
*io
)
53 struct composite_context
*c
;
54 struct lookup_state
*s
;
55 struct composite_context
*cresolve_req
;
56 struct resolve_context
*resolve_ctx
;
58 /* allocate context and state structures */
59 c
= composite_create(mem_ctx
, ctx
->event_ctx
);
60 if (c
== NULL
) return NULL
;
62 s
= talloc_zero(c
, struct lookup_state
);
63 if (composite_nomem(s
, c
)) return c
;
67 if (io
== NULL
|| io
->in
.hostname
== NULL
) {
68 composite_error(c
, NT_STATUS_INVALID_PARAMETER
);
73 s
->hostname
.name
= talloc_strdup(s
, io
->in
.hostname
);
74 if (composite_nomem(s
->hostname
.name
, c
)) return c
;
76 s
->hostname
.type
= io
->in
.type
;
77 s
->hostname
.scope
= NULL
;
79 /* name resolution methods */
80 if (io
->in
.resolve_ctx
) {
81 resolve_ctx
= io
->in
.resolve_ctx
;
83 resolve_ctx
= ctx
->resolve_ctx
;
86 /* send resolve request */
87 cresolve_req
= resolve_name_send(resolve_ctx
, s
, &s
->hostname
, c
->event_ctx
);
88 if (composite_nomem(cresolve_req
, c
)) return c
;
90 composite_continue(c
, cresolve_req
, continue_name_resolved
, c
);
95 static void continue_name_resolved(struct composite_context
*ctx
)
97 struct composite_context
*c
;
98 struct lookup_state
*s
;
100 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
101 s
= talloc_get_type(c
->private_data
, struct lookup_state
);
103 c
->status
= resolve_name_recv(ctx
, s
, &s
->address
);
110 * Waits for and receives results of asynchronous Lookup call
112 * @param c composite context returned by asynchronous Lookup call
113 * @param mem_ctx memory context of the call
114 * @param io pointer to results (and arguments) of the call
115 * @return nt status code of execution
118 NTSTATUS
libnet_Lookup_recv(struct composite_context
*c
, TALLOC_CTX
*mem_ctx
,
119 struct libnet_Lookup
*io
)
122 struct lookup_state
*s
;
124 status
= composite_wait(c
);
125 if (NT_STATUS_IS_OK(status
)) {
128 s
= talloc_get_type(c
->private_data
, struct lookup_state
);
130 address
= str_list_make_single(mem_ctx
, s
->address
);
131 NT_STATUS_HAVE_NO_MEMORY(address
);
132 io
->out
.address
= discard_const_p(const char *, 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
, mem_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
,
167 struct libnet_Lookup
*io
)
169 io
->in
.type
= NBT_NAME_SERVER
;
170 return libnet_Lookup_send(ctx
, mem_ctx
, io
);
176 * Synchronous version of LookupHost call
178 NTSTATUS
libnet_LookupHost(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
,
179 struct libnet_Lookup
*io
)
181 struct composite_context
*c
= libnet_LookupHost_send(ctx
, mem_ctx
, io
);
182 return libnet_Lookup_recv(c
, mem_ctx
, io
);
187 * Sends asynchronous LookupDCs request
189 struct tevent_req
*libnet_LookupDCs_send(struct libnet_context
*ctx
,
191 struct libnet_LookupDCs
*io
)
193 struct tevent_req
*req
;
194 struct finddcs finddcs_io
;
196 ZERO_STRUCT(finddcs_io
);
198 if (strcasecmp_m(io
->in
.domain_name
, lpcfg_workgroup(ctx
->lp_ctx
)) == 0) {
199 finddcs_io
.in
.domain_name
= lpcfg_dnsdomain(ctx
->lp_ctx
);
201 finddcs_io
.in
.domain_name
= io
->in
.domain_name
;
203 finddcs_io
.in
.minimum_dc_flags
= NBT_SERVER_LDAP
| NBT_SERVER_DS
| NBT_SERVER_WRITABLE
;
204 finddcs_io
.in
.server_address
= ctx
->server_address
;
206 req
= finddcs_cldap_send(mem_ctx
, &finddcs_io
, ctx
->resolve_ctx
, ctx
->event_ctx
);
211 * Waits for and receives results of asynchronous Lookup call
213 * @param c composite context returned by asynchronous Lookup call
214 * @param mem_ctx memory context of the call
215 * @param io pointer to results (and arguments) of the call
216 * @return nt status code of execution
219 NTSTATUS
libnet_LookupDCs_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
220 struct libnet_LookupDCs
*io
)
223 struct finddcs finddcs_io
;
224 status
= finddcs_cldap_recv(req
, mem_ctx
, &finddcs_io
);
227 io
->out
.dcs
= talloc(mem_ctx
, struct nbt_dc_name
);
228 NT_STATUS_HAVE_NO_MEMORY(io
->out
.dcs
);
229 io
->out
.dcs
[0].address
= finddcs_io
.out
.address
;
230 io
->out
.dcs
[0].name
= finddcs_io
.out
.netlogon
.data
.nt5_ex
.pdc_dns_name
;
236 * Synchronous version of LookupDCs
238 NTSTATUS
libnet_LookupDCs(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
,
239 struct libnet_LookupDCs
*io
)
241 struct tevent_req
*req
= libnet_LookupDCs_send(ctx
, mem_ctx
, io
);
242 return libnet_LookupDCs_recv(req
, mem_ctx
, io
);
246 struct lookup_name_state
{
247 struct libnet_context
*ctx
;
250 struct libnet_DomainOpen domopen
;
251 struct lsa_LookupNames lookup
;
252 struct lsa_TransSidArray sids
;
253 struct lsa_String
*names
;
255 /* information about the progress */
256 void (*monitor_fn
)(struct monitor_msg
*);
260 static bool prepare_lookup_params(struct libnet_context
*ctx
,
261 struct composite_context
*c
,
262 struct lookup_name_state
*s
);
263 static void continue_lookup_name(struct composite_context
*ctx
);
264 static void continue_name_found(struct tevent_req
*subreq
);
267 struct composite_context
* libnet_LookupName_send(struct libnet_context
*ctx
,
269 struct libnet_LookupName
*io
,
270 void (*monitor
)(struct monitor_msg
*))
272 struct composite_context
*c
;
273 struct lookup_name_state
*s
;
274 struct tevent_req
*subreq
;
275 bool prereq_met
= false;
277 c
= composite_create(mem_ctx
, ctx
->event_ctx
);
278 if (c
== NULL
) return NULL
;
280 s
= talloc_zero(c
, struct lookup_name_state
);
281 if (composite_nomem(s
, c
)) return c
;
285 s
->name
= talloc_strdup(c
, io
->in
.name
);
286 s
->monitor_fn
= monitor
;
289 prereq_met
= lsa_domain_opened(ctx
, c
, io
->in
.domain_name
, &c
, &s
->domopen
,
290 continue_lookup_name
, monitor
);
291 if (!prereq_met
) return c
;
293 if (!prepare_lookup_params(ctx
, c
, s
)) return c
;
295 subreq
= dcerpc_lsa_LookupNames_r_send(s
, c
->event_ctx
,
296 ctx
->lsa
.pipe
->binding_handle
,
298 if (composite_nomem(subreq
, c
)) return c
;
300 tevent_req_set_callback(subreq
, continue_name_found
, c
);
305 static bool prepare_lookup_params(struct libnet_context
*ctx
,
306 struct composite_context
*c
,
307 struct lookup_name_state
*s
)
309 const int single_name
= 1;
314 s
->names
= talloc_array(s
, struct lsa_String
, single_name
);
315 if (composite_nomem(s
->names
, c
)) return false;
316 s
->names
[0].string
= s
->name
;
318 s
->lookup
.in
.handle
= &ctx
->lsa
.handle
;
319 s
->lookup
.in
.num_names
= single_name
;
320 s
->lookup
.in
.names
= s
->names
;
321 s
->lookup
.in
.sids
= &s
->sids
;
322 s
->lookup
.in
.level
= 1;
323 s
->lookup
.in
.count
= &s
->count
;
324 s
->lookup
.out
.count
= &s
->count
;
325 s
->lookup
.out
.sids
= &s
->sids
;
326 s
->lookup
.out
.domains
= talloc_zero(s
, struct lsa_RefDomainList
*);
327 if (composite_nomem(s
->lookup
.out
.domains
, c
)) return false;
333 static void continue_lookup_name(struct composite_context
*ctx
)
335 struct composite_context
*c
;
336 struct lookup_name_state
*s
;
337 struct tevent_req
*subreq
;
339 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
340 s
= talloc_get_type(c
->private_data
, struct lookup_name_state
);
342 c
->status
= libnet_DomainOpen_recv(ctx
, s
->ctx
, c
, &s
->domopen
);
343 if (!composite_is_ok(c
)) return;
345 if (!prepare_lookup_params(s
->ctx
, c
, s
)) return;
347 subreq
= dcerpc_lsa_LookupNames_r_send(s
, c
->event_ctx
,
348 s
->ctx
->lsa
.pipe
->binding_handle
,
350 if (composite_nomem(subreq
, c
)) return;
352 tevent_req_set_callback(subreq
, continue_name_found
, c
);
356 static void continue_name_found(struct tevent_req
*subreq
)
358 struct composite_context
*c
;
359 struct lookup_name_state
*s
;
361 c
= tevent_req_callback_data(subreq
, struct composite_context
);
362 s
= talloc_get_type(c
->private_data
, struct lookup_name_state
);
364 c
->status
= dcerpc_lsa_LookupNames_r_recv(subreq
, s
);
366 if (!composite_is_ok(c
)) return;
368 c
->status
= s
->lookup
.out
.result
;
369 if (!composite_is_ok(c
)) return;
371 if (s
->lookup
.out
.sids
->count
!= s
->lookup
.in
.num_names
) {
372 composite_error(c
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
380 NTSTATUS
libnet_LookupName_recv(struct composite_context
*c
, TALLOC_CTX
*mem_ctx
,
381 struct libnet_LookupName
*io
)
384 struct lookup_name_state
*s
;
386 status
= composite_wait(c
);
388 if (NT_STATUS_IS_OK(status
)) {
389 s
= talloc_get_type(c
->private_data
, struct lookup_name_state
);
393 io
->out
.sidstr
= NULL
;
395 if (*s
->lookup
.out
.count
> 0) {
396 struct lsa_RefDomainList
*domains
= *s
->lookup
.out
.domains
;
397 struct lsa_TransSidArray
*sids
= s
->lookup
.out
.sids
;
399 if (domains
== NULL
|| sids
== NULL
) {
400 status
= NT_STATUS_UNSUCCESSFUL
;
401 io
->out
.error_string
= talloc_asprintf(mem_ctx
, "Error: %s", nt_errstr(status
));
405 if (sids
->count
> 0) {
406 io
->out
.rid
= sids
->sids
[0].rid
;
407 io
->out
.sid_type
= sids
->sids
[0].sid_type
;
408 if (domains
->count
> 0) {
409 io
->out
.sid
= dom_sid_add_rid(mem_ctx
, domains
->domains
[0].sid
, io
->out
.rid
);
410 NT_STATUS_HAVE_NO_MEMORY(io
->out
.sid
);
411 io
->out
.sidstr
= dom_sid_string(mem_ctx
, io
->out
.sid
);
412 NT_STATUS_HAVE_NO_MEMORY(io
->out
.sidstr
);
417 io
->out
.error_string
= talloc_strdup(mem_ctx
, "Success");
419 } else if (!NT_STATUS_IS_OK(status
)) {
420 io
->out
.error_string
= talloc_asprintf(mem_ctx
, "Error: %s", nt_errstr(status
));
429 NTSTATUS
libnet_LookupName(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
,
430 struct libnet_LookupName
*io
)
432 struct composite_context
*c
;
434 c
= libnet_LookupName_send(ctx
, mem_ctx
, io
, NULL
);
435 return libnet_LookupName_recv(c
, mem_ctx
, io
);