~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/libnet/libnet_lookup.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
   Unix SMB/CIFS implementation.
 
3
 
 
4
   Copyright (C) Rafal Szczesniak 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 3 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, see <http://www.gnu.org/licenses/>.
 
18
*/
 
19
 
 
20
/*
 
21
  a composite function for name resolving
 
22
*/
 
23
 
 
24
#include "includes.h"
 
25
#include "lib/events/events.h"
 
26
#include "libnet/libnet.h"
 
27
#include "libcli/composite/composite.h"
 
28
#include "auth/credentials/credentials.h"
 
29
#include "lib/messaging/messaging.h"
 
30
#include "lib/messaging/irpc.h"
 
31
#include "libcli/resolve/resolve.h"
 
32
#include "libcli/finddcs.h"
 
33
#include "libcli/security/security.h"
 
34
#include "librpc/gen_ndr/lsa.h"
 
35
#include "librpc/gen_ndr/ndr_lsa_c.h"
 
36
 
 
37
#include "param/param.h"
 
38
 
 
39
struct lookup_state {
 
40
        struct nbt_name hostname;
 
41
        const char *address;
 
42
};
 
43
 
 
44
 
 
45
static void continue_name_resolved(struct composite_context *ctx);
 
46
 
 
47
 
 
48
/**
 
49
 * Sends asynchronous Lookup request
 
50
 *
 
51
 * @param io arguments and result of the call
 
52
 */
 
53
 
 
54
struct composite_context *libnet_Lookup_send(struct libnet_context *ctx,
 
55
                                             struct libnet_Lookup *io)
 
56
{
 
57
        struct composite_context *c;
 
58
        struct lookup_state *s;
 
59
        struct composite_context *cresolve_req;
 
60
        struct resolve_context *resolve_ctx;
 
61
 
 
62
        /* allocate context and state structures */
 
63
        c = composite_create(ctx, ctx->event_ctx);
 
64
        if (c == NULL) return NULL;
 
65
 
 
66
        s = talloc_zero(c, struct lookup_state);
 
67
        if (composite_nomem(s, c)) return c;
 
68
 
 
69
        c->private_data = s;
 
70
 
 
71
        if (io == NULL || io->in.hostname == NULL) {
 
72
                composite_error(c, NT_STATUS_INVALID_PARAMETER);
 
73
                return c;
 
74
        }
 
75
 
 
76
        /* parameters */
 
77
        s->hostname.name   = talloc_strdup(s, io->in.hostname);
 
78
        if (composite_nomem(s->hostname.name, c)) return c;
 
79
 
 
80
        s->hostname.type   = io->in.type;
 
81
        s->hostname.scope  = NULL;
 
82
 
 
83
        /* name resolution methods */
 
84
        if (io->in.resolve_ctx) {
 
85
                resolve_ctx = io->in.resolve_ctx;
 
86
        } else {
 
87
                resolve_ctx = ctx->resolve_ctx;
 
88
        }
 
89
 
 
90
        /* send resolve request */
 
91
        cresolve_req = resolve_name_send(resolve_ctx, &s->hostname, c->event_ctx);
 
92
        if (composite_nomem(cresolve_req, c)) return c;
 
93
 
 
94
        composite_continue(c, cresolve_req, continue_name_resolved, c);
 
95
        return c;
 
96
}
 
97
 
 
98
 
 
99
static void continue_name_resolved(struct composite_context *ctx)
 
100
{
 
101
        struct composite_context *c;
 
102
        struct lookup_state *s;
 
103
 
 
104
        c = talloc_get_type(ctx->async.private_data, struct composite_context);
 
105
        s = talloc_get_type(c->private_data, struct lookup_state);
 
106
 
 
107
        c->status = resolve_name_recv(ctx, s, &s->address);
 
108
        
 
109
        composite_done(c);
 
110
}
 
111
 
 
112
 
 
113
/**
 
114
 * Waits for and receives results of asynchronous Lookup call
 
115
 *
 
116
 * @param c composite context returned by asynchronous Lookup call
 
117
 * @param mem_ctx memory context of the call
 
118
 * @param io pointer to results (and arguments) of the call
 
119
 * @return nt status code of execution
 
120
 */
 
121
 
 
122
NTSTATUS libnet_Lookup_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
 
123
                            struct libnet_Lookup *io)
 
124
{
 
125
        NTSTATUS status;
 
126
        struct lookup_state *s;
 
127
 
 
128
        status = composite_wait(c);
 
129
        if (NT_STATUS_IS_OK(status)) {
 
130
                s = talloc_get_type(c->private_data, struct lookup_state);
 
131
 
 
132
                io->out.address = (const char **)str_list_make(mem_ctx, s->address, NULL);
 
133
                NT_STATUS_HAVE_NO_MEMORY(io->out.address);
 
134
        }
 
135
 
 
136
        talloc_free(c);
 
137
        return status;
 
138
}
 
139
 
 
140
 
 
141
/**
 
142
 * Synchronous version of Lookup call
 
143
 *
 
144
 * @param mem_ctx memory context for the call
 
145
 * @param io arguments and results of the call
 
146
 * @return nt status code of execution
 
147
 */
 
148
 
 
149
NTSTATUS libnet_Lookup(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
 
150
                       struct libnet_Lookup *io)
 
151
{
 
152
        struct composite_context *c = libnet_Lookup_send(ctx, io);
 
153
        return libnet_Lookup_recv(c, mem_ctx, io);
 
154
}
 
155
 
 
156
 
 
157
/*
 
158
 * Shortcut functions to find common types of name
 
159
 * (and skip nbt name type argument)
 
160
 */
 
161
 
 
162
 
 
163
/**
 
164
 * Sends asynchronous LookupHost request
 
165
 */
 
166
struct composite_context* libnet_LookupHost_send(struct libnet_context *ctx,
 
167
                                                 struct libnet_Lookup *io)
 
168
{
 
169
        io->in.type = NBT_NAME_SERVER;
 
170
        return libnet_Lookup_send(ctx, io);
 
171
}
 
172
 
 
173
 
 
174
 
 
175
/**
 
176
 * Synchronous version of LookupHost call
 
177
 */
 
178
NTSTATUS libnet_LookupHost(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
 
179
                           struct libnet_Lookup *io)
 
180
{
 
181
        struct composite_context *c = libnet_LookupHost_send(ctx, io);
 
182
        return libnet_Lookup_recv(c, mem_ctx, io);
 
183
}
 
184
 
 
185
 
 
186
/**
 
187
 * Sends asynchronous LookupDCs request
 
188
 */
 
189
struct composite_context* libnet_LookupDCs_send(struct libnet_context *ctx,
 
190
                                                TALLOC_CTX *mem_ctx,
 
191
                                                struct libnet_LookupDCs *io)
 
192
{
 
193
        struct composite_context *c;
 
194
        struct messaging_context *msg_ctx = 
 
195
                messaging_client_init(mem_ctx, lp_messaging_path(mem_ctx, ctx->lp_ctx), 
 
196
                                      lp_iconv_convenience(ctx->lp_ctx), ctx->event_ctx);
 
197
 
 
198
        c = finddcs_send(mem_ctx, lp_netbios_name(ctx->lp_ctx), lp_nbt_port(ctx->lp_ctx),
 
199
                         io->in.domain_name, io->in.name_type,
 
200
                         NULL, lp_iconv_convenience(ctx->lp_ctx), 
 
201
                         ctx->resolve_ctx, ctx->event_ctx, msg_ctx);
 
202
        return c;
 
203
}
 
204
 
 
205
/**
 
206
 * Waits for and receives results of asynchronous Lookup call
 
207
 *
 
208
 * @param c composite context returned by asynchronous Lookup call
 
209
 * @param mem_ctx memory context of the call
 
210
 * @param io pointer to results (and arguments) of the call
 
211
 * @return nt status code of execution
 
212
 */
 
213
 
 
214
NTSTATUS libnet_LookupDCs_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
 
215
                               struct libnet_LookupDCs *io)
 
216
{
 
217
        NTSTATUS status;
 
218
        status = finddcs_recv(c, mem_ctx, &io->out.num_dcs, &io->out.dcs);
 
219
        if (!NT_STATUS_IS_OK(status)) {
 
220
                return status;
 
221
        }
 
222
        return status;
 
223
}
 
224
 
 
225
 
 
226
/**
 
227
 * Synchronous version of LookupDCs
 
228
 */
 
229
NTSTATUS libnet_LookupDCs(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
 
230
                          struct libnet_LookupDCs *io)
 
231
{
 
232
        struct composite_context *c = libnet_LookupDCs_send(ctx, mem_ctx, io);
 
233
        return libnet_LookupDCs_recv(c, mem_ctx, io);
 
234
}
 
235
 
 
236
 
 
237
struct lookup_name_state {
 
238
        struct libnet_context *ctx;
 
239
        const char *name;
 
240
        uint32_t count;
 
241
        struct libnet_DomainOpen domopen;
 
242
        struct lsa_LookupNames lookup;
 
243
        struct lsa_TransSidArray sids;
 
244
        struct lsa_String *names;
 
245
 
 
246
        /* information about the progress */
 
247
        void (*monitor_fn)(struct monitor_msg *);
 
248
};
 
249
 
 
250
 
 
251
static bool prepare_lookup_params(struct libnet_context *ctx,
 
252
                                  struct composite_context *c,
 
253
                                  struct lookup_name_state *s);
 
254
static void continue_lookup_name(struct composite_context *ctx);
 
255
static void continue_name_found(struct rpc_request *req);
 
256
 
 
257
 
 
258
struct composite_context* libnet_LookupName_send(struct libnet_context *ctx,
 
259
                                                 TALLOC_CTX *mem_ctx,
 
260
                                                 struct libnet_LookupName *io,
 
261
                                                 void (*monitor)(struct monitor_msg*))
 
262
{
 
263
        struct composite_context *c;
 
264
        struct lookup_name_state *s;
 
265
        struct rpc_request *lookup_req;
 
266
        bool prereq_met = false;
 
267
 
 
268
        c = composite_create(mem_ctx, ctx->event_ctx);
 
269
        if (c == NULL) return NULL;
 
270
 
 
271
        s = talloc_zero(c, struct lookup_name_state);
 
272
        if (composite_nomem(s, c)) return c;
 
273
 
 
274
        c->private_data = s;
 
275
        
 
276
        s->name = talloc_strdup(c, io->in.name);
 
277
        s->monitor_fn = monitor;
 
278
        s->ctx = ctx;
 
279
 
 
280
        prereq_met = lsa_domain_opened(ctx, io->in.domain_name, &c, &s->domopen,
 
281
                                       continue_lookup_name, monitor);
 
282
        if (!prereq_met) return c;
 
283
 
 
284
        if (!prepare_lookup_params(ctx, c, s)) return c;
 
285
 
 
286
        lookup_req = dcerpc_lsa_LookupNames_send(ctx->lsa.pipe, c, &s->lookup);
 
287
        if (composite_nomem(lookup_req, c)) return c;
 
288
 
 
289
        composite_continue_rpc(c, lookup_req, continue_name_found, c);
 
290
        return c;
 
291
}
 
292
 
 
293
 
 
294
static bool prepare_lookup_params(struct libnet_context *ctx,
 
295
                                  struct composite_context *c,
 
296
                                  struct lookup_name_state *s)
 
297
{
 
298
        const int single_name = 1;
 
299
 
 
300
        s->sids.count = 0;
 
301
        s->sids.sids  = NULL;
 
302
        
 
303
        s->names = talloc_array(ctx, struct lsa_String, single_name);
 
304
        if (composite_nomem(s->names, c)) return false;
 
305
        s->names[0].string = s->name;
 
306
        
 
307
        s->lookup.in.handle    = &ctx->lsa.handle;
 
308
        s->lookup.in.num_names = single_name;
 
309
        s->lookup.in.names     = s->names;
 
310
        s->lookup.in.sids      = &s->sids;
 
311
        s->lookup.in.level     = 1;
 
312
        s->lookup.in.count     = &s->count;
 
313
        s->lookup.out.count    = &s->count;
 
314
        s->lookup.out.sids     = &s->sids;
 
315
        s->lookup.out.domains  = talloc_zero(ctx, struct lsa_RefDomainList *);
 
316
        if (composite_nomem(s->lookup.out.domains, c)) return false;
 
317
        
 
318
        return true;
 
319
}
 
320
 
 
321
 
 
322
static void continue_lookup_name(struct composite_context *ctx)
 
323
{
 
324
        struct composite_context *c;
 
325
        struct lookup_name_state *s;
 
326
        struct rpc_request *lookup_req;
 
327
 
 
328
        c = talloc_get_type(ctx->async.private_data, struct composite_context);
 
329
        s = talloc_get_type(c->private_data, struct lookup_name_state);
 
330
 
 
331
        c->status = libnet_DomainOpen_recv(ctx, s->ctx, c, &s->domopen);
 
332
        if (!composite_is_ok(c)) return;
 
333
        
 
334
        if (!prepare_lookup_params(s->ctx, c, s)) return;
 
335
 
 
336
        lookup_req = dcerpc_lsa_LookupNames_send(s->ctx->lsa.pipe, c, &s->lookup);
 
337
        if (composite_nomem(lookup_req, c)) return;
 
338
        
 
339
        composite_continue_rpc(c, lookup_req, continue_name_found, c);
 
340
}
 
341
 
 
342
 
 
343
static void continue_name_found(struct rpc_request *req)
 
344
{
 
345
        struct composite_context *c;
 
346
        struct lookup_name_state *s;
 
347
 
 
348
        c = talloc_get_type(req->async.private_data, struct composite_context);
 
349
        s = talloc_get_type(c->private_data, struct lookup_name_state);
 
350
 
 
351
        c->status = dcerpc_ndr_request_recv(req);
 
352
        if (!composite_is_ok(c)) return;
 
353
 
 
354
        c->status = s->lookup.out.result;
 
355
        if (!composite_is_ok(c)) return;
 
356
 
 
357
        composite_done(c);
 
358
}
 
359
 
 
360
 
 
361
NTSTATUS libnet_LookupName_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
 
362
                                struct libnet_LookupName *io)
 
363
{
 
364
        NTSTATUS status;
 
365
        struct lookup_name_state *s;
 
366
 
 
367
        status = composite_wait(c);
 
368
 
 
369
        if (NT_STATUS_IS_OK(status)) {
 
370
                s = talloc_get_type(c->private_data, struct lookup_name_state);
 
371
 
 
372
                io->out.rid = 0;
 
373
                io->out.sid = NULL;
 
374
                io->out.sidstr = NULL;
 
375
 
 
376
                if (*s->lookup.out.count > 0) {
 
377
                        struct lsa_RefDomainList *domains = *s->lookup.out.domains;
 
378
                        struct lsa_TransSidArray *sids = s->lookup.out.sids;
 
379
 
 
380
                        if (domains == NULL || sids == NULL) {
 
381
                                status = NT_STATUS_UNSUCCESSFUL;
 
382
                                io->out.error_string = talloc_asprintf(mem_ctx, "Error: %s", nt_errstr(status));
 
383
                                goto done;
 
384
                        }
 
385
 
 
386
                        if (sids->count > 0) {
 
387
                                io->out.rid        = sids->sids[0].rid;
 
388
                                io->out.sid_type   = sids->sids[0].sid_type;
 
389
                                if (domains->count > 0) {
 
390
                                        io->out.sid = dom_sid_add_rid(mem_ctx, domains->domains[0].sid, io->out.rid);
 
391
                                        NT_STATUS_HAVE_NO_MEMORY(io->out.sid);
 
392
                                        io->out.sidstr = dom_sid_string(mem_ctx, io->out.sid);
 
393
                                        NT_STATUS_HAVE_NO_MEMORY(io->out.sidstr);
 
394
                                }
 
395
                        }
 
396
                }
 
397
 
 
398
                io->out.error_string = talloc_strdup(mem_ctx, "Success");
 
399
 
 
400
        } else if (!NT_STATUS_IS_OK(status)) {
 
401
                io->out.error_string = talloc_asprintf(mem_ctx, "Error: %s", nt_errstr(status));
 
402
        }
 
403
 
 
404
done:
 
405
        talloc_free(c);
 
406
        return status;
 
407
}
 
408
 
 
409
 
 
410
NTSTATUS libnet_LookupName(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
 
411
                           struct libnet_LookupName *io)
 
412
{
 
413
        struct composite_context *c;
 
414
        
 
415
        c = libnet_LookupName_send(ctx, mem_ctx, io, NULL);
 
416
        return libnet_LookupName_recv(c, mem_ctx, io);
 
417
}