~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to librpc/rpc/binding.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
   dcerpc utility functions
 
5
 
 
6
   Copyright (C) Andrew Tridgell 2003
 
7
   Copyright (C) Jelmer Vernooij 2004
 
8
   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
 
9
   Copyright (C) Rafal Szczesniak 2006
 
10
 
 
11
   This program is free software; you can redistribute it and/or modify
 
12
   it under the terms of the GNU General Public License as published by
 
13
   the Free Software Foundation; either version 3 of the License, or
 
14
   (at your option) any later version.
 
15
 
 
16
   This program is distributed in the hope that it will be useful,
 
17
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
19
   GNU General Public License for more details.
 
20
 
 
21
   You should have received a copy of the GNU General Public License
 
22
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
23
*/
 
24
 
 
25
#include "includes.h"
 
26
#include "librpc/gen_ndr/ndr_epmapper.h"
 
27
#include "librpc/gen_ndr/ndr_misc.h"
 
28
#include "librpc/rpc/dcerpc.h"
 
29
#undef strcasecmp
 
30
 
 
31
#define MAX_PROTSEQ             10
 
32
 
 
33
static const struct {
 
34
        const char *name;
 
35
        enum dcerpc_transport_t transport;
 
36
        int num_protocols;
 
37
        enum epm_protocol protseq[MAX_PROTSEQ];
 
38
} transports[] = {
 
39
        { "ncacn_np",     NCACN_NP, 3, 
 
40
                { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_SMB, EPM_PROTOCOL_NETBIOS }},
 
41
        { "ncacn_ip_tcp", NCACN_IP_TCP, 3, 
 
42
                { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_TCP, EPM_PROTOCOL_IP } }, 
 
43
        { "ncacn_http", NCACN_HTTP, 3, 
 
44
                { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_HTTP, EPM_PROTOCOL_IP } }, 
 
45
        { "ncadg_ip_udp", NCACN_IP_UDP, 3, 
 
46
                { EPM_PROTOCOL_NCADG, EPM_PROTOCOL_UDP, EPM_PROTOCOL_IP } },
 
47
        { "ncalrpc", NCALRPC, 2, 
 
48
                { EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_PIPE } },
 
49
        { "ncacn_unix_stream", NCACN_UNIX_STREAM, 2, 
 
50
                { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_UNIX_DS } },
 
51
        { "ncadg_unix_dgram", NCADG_UNIX_DGRAM, 2, 
 
52
                { EPM_PROTOCOL_NCADG, EPM_PROTOCOL_UNIX_DS } },
 
53
        { "ncacn_at_dsp", NCACN_AT_DSP, 3, 
 
54
                { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_APPLETALK, EPM_PROTOCOL_DSP } },
 
55
        { "ncadg_at_ddp", NCADG_AT_DDP, 3, 
 
56
                { EPM_PROTOCOL_NCADG, EPM_PROTOCOL_APPLETALK, EPM_PROTOCOL_DDP } },
 
57
        { "ncacn_vns_ssp", NCACN_VNS_SPP, 3, 
 
58
                { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_STREETTALK, EPM_PROTOCOL_VINES_SPP } },
 
59
        { "ncacn_vns_ipc", NCACN_VNS_IPC, 3, 
 
60
                { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_STREETTALK, EPM_PROTOCOL_VINES_IPC }, },
 
61
        { "ncadg_ipx", NCADG_IPX, 2,
 
62
                { EPM_PROTOCOL_NCADG, EPM_PROTOCOL_IPX },
 
63
        },
 
64
        { "ncacn_spx", NCACN_SPX, 3,
 
65
                /* I guess some MS programmer confused the identifier for 
 
66
                 * EPM_PROTOCOL_UUID (0x0D or 13) with the one for 
 
67
                 * EPM_PROTOCOL_SPX (0x13) here. -- jelmer*/
 
68
                { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_UUID },
 
69
        },
 
70
};
 
71
 
 
72
static const struct {
 
73
        const char *name;
 
74
        uint32_t flag;
 
75
} ncacn_options[] = {
 
76
        {"sign", DCERPC_SIGN},
 
77
        {"seal", DCERPC_SEAL},
 
78
        {"connect", DCERPC_CONNECT},
 
79
        {"spnego", DCERPC_AUTH_SPNEGO},
 
80
        {"ntlm", DCERPC_AUTH_NTLM},
 
81
        {"krb5", DCERPC_AUTH_KRB5},
 
82
        {"validate", DCERPC_DEBUG_VALIDATE_BOTH},
 
83
        {"print", DCERPC_DEBUG_PRINT_BOTH},
 
84
        {"padcheck", DCERPC_DEBUG_PAD_CHECK},
 
85
        {"bigendian", DCERPC_PUSH_BIGENDIAN},
 
86
        {"smb2", DCERPC_SMB2},
 
87
        {"hdrsign", DCERPC_HEADER_SIGNING}
 
88
};
 
89
 
 
90
const char *epm_floor_string(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor)
 
91
{
 
92
        struct ndr_syntax_id syntax;
 
93
        NTSTATUS status;
 
94
 
 
95
        switch(epm_floor->lhs.protocol) {
 
96
                case EPM_PROTOCOL_UUID:
 
97
                        status = dcerpc_floor_get_lhs_data(epm_floor, &syntax);
 
98
                        if (NT_STATUS_IS_OK(status)) {
 
99
                                /* lhs is used: UUID */
 
100
                                char *uuidstr;
 
101
 
 
102
                                if (GUID_equal(&syntax.uuid, &ndr_transfer_syntax.uuid)) {
 
103
                                        return "NDR";
 
104
                                } 
 
105
 
 
106
                                if (GUID_equal(&syntax.uuid, &ndr64_transfer_syntax.uuid)) {
 
107
                                        return "NDR64";
 
108
                                } 
 
109
 
 
110
                                uuidstr = GUID_string(mem_ctx, &syntax.uuid);
 
111
 
 
112
                                return talloc_asprintf(mem_ctx, " uuid %s/0x%02x", uuidstr, syntax.if_version);
 
113
                        } else { /* IPX */
 
114
                                return talloc_asprintf(mem_ctx, "IPX:%s", 
 
115
                                                data_blob_hex_string(mem_ctx, &epm_floor->rhs.uuid.unknown));
 
116
                        }
 
117
 
 
118
                case EPM_PROTOCOL_NCACN:
 
119
                        return "RPC-C";
 
120
 
 
121
                case EPM_PROTOCOL_NCADG:
 
122
                        return "RPC";
 
123
 
 
124
                case EPM_PROTOCOL_NCALRPC:
 
125
                        return "NCALRPC";
 
126
 
 
127
                case EPM_PROTOCOL_DNET_NSP:
 
128
                        return "DNET/NSP";
 
129
 
 
130
                case EPM_PROTOCOL_IP:
 
131
                        return talloc_asprintf(mem_ctx, "IP:%s", epm_floor->rhs.ip.ipaddr);
 
132
 
 
133
                case EPM_PROTOCOL_PIPE:
 
134
                        return talloc_asprintf(mem_ctx, "PIPE:%s", epm_floor->rhs.pipe.path);
 
135
 
 
136
                case EPM_PROTOCOL_SMB:
 
137
                        return talloc_asprintf(mem_ctx, "SMB:%s", epm_floor->rhs.smb.unc);
 
138
 
 
139
                case EPM_PROTOCOL_UNIX_DS:
 
140
                        return talloc_asprintf(mem_ctx, "Unix:%s", epm_floor->rhs.unix_ds.path);
 
141
 
 
142
                case EPM_PROTOCOL_NETBIOS:
 
143
                        return talloc_asprintf(mem_ctx, "NetBIOS:%s", epm_floor->rhs.netbios.name);
 
144
 
 
145
                case EPM_PROTOCOL_NETBEUI:
 
146
                        return "NETBeui";
 
147
 
 
148
                case EPM_PROTOCOL_SPX:
 
149
                        return "SPX";
 
150
 
 
151
                case EPM_PROTOCOL_NB_IPX:
 
152
                        return "NB_IPX";
 
153
 
 
154
                case EPM_PROTOCOL_HTTP:
 
155
                        return talloc_asprintf(mem_ctx, "HTTP:%d", epm_floor->rhs.http.port);
 
156
 
 
157
                case EPM_PROTOCOL_TCP:
 
158
                        return talloc_asprintf(mem_ctx, "TCP:%d", epm_floor->rhs.tcp.port);
 
159
 
 
160
                case EPM_PROTOCOL_UDP:
 
161
                        return talloc_asprintf(mem_ctx, "UDP:%d", epm_floor->rhs.udp.port);
 
162
 
 
163
                default:
 
164
                        return talloc_asprintf(mem_ctx, "UNK(%02x):", epm_floor->lhs.protocol);
 
165
        }
 
166
}
 
167
 
 
168
 
 
169
/*
 
170
  form a binding string from a binding structure
 
171
*/
 
172
_PUBLIC_ char *dcerpc_binding_string(TALLOC_CTX *mem_ctx, const struct dcerpc_binding *b)
 
173
{
 
174
        char *s = talloc_strdup(mem_ctx, "");
 
175
        int i;
 
176
        const char *t_name = NULL;
 
177
 
 
178
        if (b->transport != NCA_UNKNOWN) {
 
179
                t_name = derpc_transport_string_by_transport(b->transport);
 
180
                if (!t_name) {
 
181
                        return NULL;
 
182
                }
 
183
        }
 
184
 
 
185
        if (!GUID_all_zero(&b->object.uuid)) { 
 
186
                s = talloc_asprintf(s, "%s@",
 
187
                                    GUID_string(mem_ctx, &b->object.uuid));
 
188
        }
 
189
 
 
190
        if (t_name != NULL) {
 
191
                s = talloc_asprintf_append_buffer(s, "%s:", t_name);
 
192
                if (s == NULL) {
 
193
                        return NULL;
 
194
                }
 
195
        }
 
196
 
 
197
        if (b->host) {
 
198
                s = talloc_asprintf_append_buffer(s, "%s", b->host);
 
199
        }
 
200
 
 
201
        if (!b->endpoint && !b->options && !b->flags) {
 
202
                return s;
 
203
        }
 
204
 
 
205
        s = talloc_asprintf_append_buffer(s, "[");
 
206
 
 
207
        if (b->endpoint) {
 
208
                s = talloc_asprintf_append_buffer(s, "%s", b->endpoint);
 
209
        }
 
210
 
 
211
        /* this is a *really* inefficent way of dealing with strings,
 
212
           but this is rarely called and the strings are always short,
 
213
           so I don't care */
 
214
        for (i=0;b->options && b->options[i];i++) {
 
215
                s = talloc_asprintf_append_buffer(s, ",%s", b->options[i]);
 
216
                if (!s) return NULL;
 
217
        }
 
218
 
 
219
        for (i=0;i<ARRAY_SIZE(ncacn_options);i++) {
 
220
                if (b->flags & ncacn_options[i].flag) {
 
221
                        s = talloc_asprintf_append_buffer(s, ",%s", ncacn_options[i].name);
 
222
                        if (!s) return NULL;
 
223
                }
 
224
        }
 
225
 
 
226
        s = talloc_asprintf_append_buffer(s, "]");
 
227
 
 
228
        return s;
 
229
}
 
230
 
 
231
/*
 
232
  parse a binding string into a dcerpc_binding structure
 
233
*/
 
234
_PUBLIC_ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struct dcerpc_binding **b_out)
 
235
{
 
236
        struct dcerpc_binding *b;
 
237
        char *options;
 
238
        char *p;
 
239
        int i, j, comma_count;
 
240
 
 
241
        b = talloc(mem_ctx, struct dcerpc_binding);
 
242
        if (!b) {
 
243
                return NT_STATUS_NO_MEMORY;
 
244
        }
 
245
 
 
246
        p = strchr(s, '@');
 
247
 
 
248
        if (p && PTR_DIFF(p, s) == 36) { /* 36 is the length of a UUID */
 
249
                NTSTATUS status;
 
250
                DATA_BLOB blob = data_blob(s, 36);
 
251
                status = GUID_from_data_blob(&blob, &b->object.uuid);
 
252
 
 
253
                if (NT_STATUS_IS_ERR(status)) {
 
254
                        DEBUG(0, ("Failed parsing UUID\n"));
 
255
                        return status;
 
256
                }
 
257
 
 
258
                s = p + 1;
 
259
        } else {
 
260
                ZERO_STRUCT(b->object);
 
261
        }
 
262
 
 
263
        b->object.if_version = 0;
 
264
 
 
265
        p = strchr(s, ':');
 
266
 
 
267
        if (p == NULL) {
 
268
                b->transport = NCA_UNKNOWN;
 
269
        } else {
 
270
                char *type = talloc_strndup(mem_ctx, s, PTR_DIFF(p, s));
 
271
                if (!type) {
 
272
                        return NT_STATUS_NO_MEMORY;
 
273
                }
 
274
 
 
275
                for (i=0;i<ARRAY_SIZE(transports);i++) {
 
276
                        if (strcasecmp(type, transports[i].name) == 0) {
 
277
                                b->transport = transports[i].transport;
 
278
                                break;
 
279
                        }
 
280
                }
 
281
 
 
282
                if (i==ARRAY_SIZE(transports)) {
 
283
                        DEBUG(0,("Unknown dcerpc transport '%s'\n", type));
 
284
                        return NT_STATUS_INVALID_PARAMETER;
 
285
                }
 
286
 
 
287
                talloc_free(type);
 
288
 
 
289
                s = p+1;
 
290
        }
 
291
 
 
292
        p = strchr(s, '[');
 
293
        if (p) {
 
294
                b->host = talloc_strndup(b, s, PTR_DIFF(p, s));
 
295
                options = talloc_strdup(mem_ctx, p+1);
 
296
                if (options[strlen(options)-1] != ']') {
 
297
                        return NT_STATUS_INVALID_PARAMETER;
 
298
                }
 
299
                options[strlen(options)-1] = 0;
 
300
        } else {
 
301
                b->host = talloc_strdup(b, s);
 
302
                options = NULL;
 
303
        }
 
304
        if (!b->host) {
 
305
                return NT_STATUS_NO_MEMORY;
 
306
        }
 
307
 
 
308
        b->target_hostname = b->host;
 
309
 
 
310
        b->options = NULL;
 
311
        b->flags = 0;
 
312
        b->assoc_group_id = 0;
 
313
        b->endpoint = NULL;
 
314
 
 
315
        if (!options) {
 
316
                *b_out = b;
 
317
                return NT_STATUS_OK;
 
318
        }
 
319
 
 
320
        comma_count = count_chars(options, ',');
 
321
 
 
322
        b->options = talloc_array(b, const char *, comma_count+2);
 
323
        if (!b->options) {
 
324
                return NT_STATUS_NO_MEMORY;
 
325
        }
 
326
 
 
327
        for (i=0; (p = strchr(options, ',')); i++) {
 
328
                b->options[i] = talloc_strndup(b, options, PTR_DIFF(p, options));
 
329
                if (!b->options[i]) {
 
330
                        return NT_STATUS_NO_MEMORY;
 
331
                }
 
332
                options = p+1;
 
333
        }
 
334
        b->options[i] = options;
 
335
        b->options[i+1] = NULL;
 
336
 
 
337
        /* some options are pre-parsed for convenience */
 
338
        for (i=0;b->options[i];i++) {
 
339
                for (j=0;j<ARRAY_SIZE(ncacn_options);j++) {
 
340
                        if (strcasecmp(ncacn_options[j].name, b->options[i]) == 0) {
 
341
                                int k;
 
342
                                b->flags |= ncacn_options[j].flag;
 
343
                                for (k=i;b->options[k];k++) {
 
344
                                        b->options[k] = b->options[k+1];
 
345
                                }
 
346
                                i--;
 
347
                                break;
 
348
                        }
 
349
                }
 
350
        }
 
351
 
 
352
        if (b->options[0]) {
 
353
                /* Endpoint is first option */
 
354
                b->endpoint = b->options[0];
 
355
                if (strlen(b->endpoint) == 0) b->endpoint = NULL;
 
356
 
 
357
                for (i=0;b->options[i];i++) {
 
358
                        b->options[i] = b->options[i+1];
 
359
                }
 
360
        }
 
361
 
 
362
        if (b->options[0] == NULL)
 
363
                b->options = NULL;
 
364
 
 
365
        *b_out = b;
 
366
        return NT_STATUS_OK;
 
367
}
 
368
 
 
369
_PUBLIC_ NTSTATUS dcerpc_floor_get_lhs_data(const struct epm_floor *epm_floor,
 
370
                                            struct ndr_syntax_id *syntax)
 
371
{
 
372
        TALLOC_CTX *mem_ctx = talloc_init("floor_get_lhs_data");
 
373
        struct ndr_pull *ndr;
 
374
        enum ndr_err_code ndr_err;
 
375
        uint16_t if_version=0;
 
376
 
 
377
        ndr = ndr_pull_init_blob(&epm_floor->lhs.lhs_data, mem_ctx, NULL);
 
378
        if (ndr == NULL) {
 
379
                talloc_free(mem_ctx);
 
380
                return NT_STATUS_NO_MEMORY;
 
381
        }
 
382
        ndr->flags |= LIBNDR_FLAG_NOALIGN;
 
383
 
 
384
        ndr_err = ndr_pull_GUID(ndr, NDR_SCALARS | NDR_BUFFERS, &syntax->uuid);
 
385
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
386
                talloc_free(mem_ctx);
 
387
                return ndr_map_error2ntstatus(ndr_err);
 
388
        }
 
389
 
 
390
        ndr_err = ndr_pull_uint16(ndr, NDR_SCALARS, &if_version);
 
391
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
392
                talloc_free(mem_ctx);
 
393
                return ndr_map_error2ntstatus(ndr_err);
 
394
        }
 
395
 
 
396
        syntax->if_version = if_version;
 
397
 
 
398
        talloc_free(mem_ctx);
 
399
 
 
400
        return NT_STATUS_OK;
 
401
}
 
402
 
 
403
static DATA_BLOB dcerpc_floor_pack_lhs_data(TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *syntax)
 
404
{
 
405
        struct ndr_push *ndr = ndr_push_init_ctx(mem_ctx, NULL);
 
406
 
 
407
        ndr->flags |= LIBNDR_FLAG_NOALIGN;
 
408
 
 
409
        ndr_push_GUID(ndr, NDR_SCALARS | NDR_BUFFERS, &syntax->uuid);
 
410
        ndr_push_uint16(ndr, NDR_SCALARS, syntax->if_version);
 
411
 
 
412
        return ndr_push_blob(ndr);
 
413
}
 
414
 
 
415
const char *dcerpc_floor_get_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor)
 
416
{
 
417
        switch (epm_floor->lhs.protocol) {
 
418
        case EPM_PROTOCOL_TCP:
 
419
                if (epm_floor->rhs.tcp.port == 0) return NULL;
 
420
                return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.tcp.port);
 
421
 
 
422
        case EPM_PROTOCOL_UDP:
 
423
                if (epm_floor->rhs.udp.port == 0) return NULL;
 
424
                return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.udp.port);
 
425
 
 
426
        case EPM_PROTOCOL_HTTP:
 
427
                if (epm_floor->rhs.http.port == 0) return NULL;
 
428
                return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.http.port);
 
429
 
 
430
        case EPM_PROTOCOL_IP:
 
431
                return talloc_strdup(mem_ctx, epm_floor->rhs.ip.ipaddr);
 
432
 
 
433
        case EPM_PROTOCOL_NCACN:
 
434
                return NULL;
 
435
 
 
436
        case EPM_PROTOCOL_NCADG:
 
437
                return NULL;
 
438
 
 
439
        case EPM_PROTOCOL_SMB:
 
440
                if (strlen(epm_floor->rhs.smb.unc) == 0) return NULL;
 
441
                return talloc_strdup(mem_ctx, epm_floor->rhs.smb.unc);
 
442
 
 
443
        case EPM_PROTOCOL_PIPE:
 
444
                if (strlen(epm_floor->rhs.pipe.path) == 0) return NULL;
 
445
                return talloc_strdup(mem_ctx, epm_floor->rhs.pipe.path);
 
446
 
 
447
        case EPM_PROTOCOL_NETBIOS:
 
448
                if (strlen(epm_floor->rhs.netbios.name) == 0) return NULL;
 
449
                return talloc_strdup(mem_ctx, epm_floor->rhs.netbios.name);
 
450
 
 
451
        case EPM_PROTOCOL_NCALRPC:
 
452
                return NULL;
 
453
 
 
454
        case EPM_PROTOCOL_VINES_SPP:
 
455
                return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.vines_spp.port);
 
456
 
 
457
        case EPM_PROTOCOL_VINES_IPC:
 
458
                return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.vines_ipc.port);
 
459
 
 
460
        case EPM_PROTOCOL_STREETTALK:
 
461
                return talloc_strdup(mem_ctx, epm_floor->rhs.streettalk.streettalk);
 
462
 
 
463
        case EPM_PROTOCOL_UNIX_DS:
 
464
                if (strlen(epm_floor->rhs.unix_ds.path) == 0) return NULL;
 
465
                return talloc_strdup(mem_ctx, epm_floor->rhs.unix_ds.path);
 
466
 
 
467
        case EPM_PROTOCOL_NULL:
 
468
                return NULL;
 
469
 
 
470
        default:
 
471
                DEBUG(0,("Unsupported lhs protocol %d\n", epm_floor->lhs.protocol));
 
472
                break;
 
473
        }
 
474
 
 
475
        return NULL;
 
476
}
 
477
 
 
478
static NTSTATUS dcerpc_floor_set_rhs_data(TALLOC_CTX *mem_ctx, 
 
479
                                          struct epm_floor *epm_floor,  
 
480
                                          const char *data)
 
481
{
 
482
        switch (epm_floor->lhs.protocol) {
 
483
        case EPM_PROTOCOL_TCP:
 
484
                epm_floor->rhs.tcp.port = atoi(data);
 
485
                return NT_STATUS_OK;
 
486
 
 
487
        case EPM_PROTOCOL_UDP:
 
488
                epm_floor->rhs.udp.port = atoi(data);
 
489
                return NT_STATUS_OK;
 
490
 
 
491
        case EPM_PROTOCOL_HTTP:
 
492
                epm_floor->rhs.http.port = atoi(data);
 
493
                return NT_STATUS_OK;
 
494
 
 
495
        case EPM_PROTOCOL_IP:
 
496
                epm_floor->rhs.ip.ipaddr = talloc_strdup(mem_ctx, data);
 
497
                NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.ip.ipaddr);
 
498
                return NT_STATUS_OK;
 
499
 
 
500
        case EPM_PROTOCOL_NCACN:
 
501
                epm_floor->rhs.ncacn.minor_version = 0;
 
502
                return NT_STATUS_OK;
 
503
 
 
504
        case EPM_PROTOCOL_NCADG:
 
505
                epm_floor->rhs.ncadg.minor_version = 0;
 
506
                return NT_STATUS_OK;
 
507
 
 
508
        case EPM_PROTOCOL_SMB:
 
509
                epm_floor->rhs.smb.unc = talloc_strdup(mem_ctx, data);
 
510
                NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.smb.unc);
 
511
                return NT_STATUS_OK;
 
512
 
 
513
        case EPM_PROTOCOL_PIPE:
 
514
                epm_floor->rhs.pipe.path = talloc_strdup(mem_ctx, data);
 
515
                NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.pipe.path);
 
516
                return NT_STATUS_OK;
 
517
 
 
518
        case EPM_PROTOCOL_NETBIOS:
 
519
                epm_floor->rhs.netbios.name = talloc_strdup(mem_ctx, data);
 
520
                NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.netbios.name);
 
521
                return NT_STATUS_OK;
 
522
 
 
523
        case EPM_PROTOCOL_NCALRPC:
 
524
                return NT_STATUS_OK;
 
525
 
 
526
        case EPM_PROTOCOL_VINES_SPP:
 
527
                epm_floor->rhs.vines_spp.port = atoi(data);
 
528
                return NT_STATUS_OK;
 
529
 
 
530
        case EPM_PROTOCOL_VINES_IPC:
 
531
                epm_floor->rhs.vines_ipc.port = atoi(data);
 
532
                return NT_STATUS_OK;
 
533
 
 
534
        case EPM_PROTOCOL_STREETTALK:
 
535
                epm_floor->rhs.streettalk.streettalk = talloc_strdup(mem_ctx, data);
 
536
                NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.streettalk.streettalk);
 
537
                return NT_STATUS_OK;
 
538
 
 
539
        case EPM_PROTOCOL_UNIX_DS:
 
540
                epm_floor->rhs.unix_ds.path = talloc_strdup(mem_ctx, data);
 
541
                NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.unix_ds.path);
 
542
                return NT_STATUS_OK;
 
543
 
 
544
        case EPM_PROTOCOL_NULL:
 
545
                return NT_STATUS_OK;
 
546
 
 
547
        default:
 
548
                DEBUG(0,("Unsupported lhs protocol %d\n", epm_floor->lhs.protocol));
 
549
                break;
 
550
        }
 
551
 
 
552
        return NT_STATUS_NOT_SUPPORTED;
 
553
}
 
554
 
 
555
enum dcerpc_transport_t dcerpc_transport_by_endpoint_protocol(int prot)
 
556
{
 
557
        int i;
 
558
 
 
559
        /* Find a transport that has 'prot' as 4th protocol */
 
560
        for (i=0;i<ARRAY_SIZE(transports);i++) {
 
561
                if (transports[i].num_protocols >= 2 && 
 
562
                        transports[i].protseq[1] == prot) {
 
563
                        return transports[i].transport;
 
564
                }
 
565
        }
 
566
 
 
567
        /* Unknown transport */
 
568
        return (unsigned int)-1;
 
569
}
 
570
 
 
571
_PUBLIC_ enum dcerpc_transport_t dcerpc_transport_by_tower(const struct epm_tower *tower)
 
572
{
 
573
        int i;
 
574
 
 
575
        /* Find a transport that matches this tower */
 
576
        for (i=0;i<ARRAY_SIZE(transports);i++) {
 
577
                int j;
 
578
                if (transports[i].num_protocols != tower->num_floors - 2) {
 
579
                        continue; 
 
580
                }
 
581
 
 
582
                for (j = 0; j < transports[i].num_protocols; j++) {
 
583
                        if (transports[i].protseq[j] != tower->floors[j+2].lhs.protocol) {
 
584
                                break;
 
585
                        }
 
586
                }
 
587
 
 
588
                if (j == transports[i].num_protocols) {
 
589
                        return transports[i].transport;
 
590
                }
 
591
        }
 
592
 
 
593
        /* Unknown transport */
 
594
        return (unsigned int)-1;
 
595
}
 
596
 
 
597
_PUBLIC_ const char *derpc_transport_string_by_transport(enum dcerpc_transport_t t)
 
598
{
 
599
        int i;
 
600
 
 
601
        for (i=0; i<ARRAY_SIZE(transports); i++) {
 
602
                if (t == transports[i].transport) {
 
603
                        return transports[i].name;
 
604
                }
 
605
        }
 
606
        return NULL;
 
607
}
 
608
 
 
609
_PUBLIC_ NTSTATUS dcerpc_binding_from_tower(TALLOC_CTX *mem_ctx, 
 
610
                                   struct epm_tower *tower, 
 
611
                                   struct dcerpc_binding **b_out)
 
612
{
 
613
        NTSTATUS status;
 
614
        struct dcerpc_binding *binding;
 
615
 
 
616
        binding = talloc(mem_ctx, struct dcerpc_binding);
 
617
        NT_STATUS_HAVE_NO_MEMORY(binding);
 
618
 
 
619
        ZERO_STRUCT(binding->object);
 
620
        binding->options = NULL;
 
621
        binding->host = NULL;
 
622
        binding->target_hostname = NULL;
 
623
        binding->flags = 0;
 
624
        binding->assoc_group_id = 0;
 
625
 
 
626
        binding->transport = dcerpc_transport_by_tower(tower);
 
627
 
 
628
        if (binding->transport == (unsigned int)-1) {
 
629
                return NT_STATUS_NOT_SUPPORTED;
 
630
        }
 
631
 
 
632
        if (tower->num_floors < 1) {
 
633
                return NT_STATUS_OK;
 
634
        }
 
635
 
 
636
        /* Set object uuid */
 
637
        status = dcerpc_floor_get_lhs_data(&tower->floors[0], &binding->object);
 
638
 
 
639
        if (!NT_STATUS_IS_OK(status)) {
 
640
                DEBUG(1, ("Error pulling object uuid and version: %s", nt_errstr(status)));     
 
641
                return status;
 
642
        }
 
643
 
 
644
        /* Ignore floor 1, it contains the NDR version info */
 
645
 
 
646
        binding->options = NULL;
 
647
 
 
648
        /* Set endpoint */
 
649
        if (tower->num_floors >= 4) {
 
650
                binding->endpoint = dcerpc_floor_get_rhs_data(mem_ctx, &tower->floors[3]);
 
651
        } else {
 
652
                binding->endpoint = NULL;
 
653
        }
 
654
 
 
655
        /* Set network address */
 
656
        if (tower->num_floors >= 5) {
 
657
                binding->host = dcerpc_floor_get_rhs_data(mem_ctx, &tower->floors[4]);
 
658
                NT_STATUS_HAVE_NO_MEMORY(binding->host);
 
659
                binding->target_hostname = binding->host;
 
660
        }
 
661
        *b_out = binding;
 
662
        return NT_STATUS_OK;
 
663
}
 
664
 
 
665
_PUBLIC_ NTSTATUS dcerpc_binding_build_tower(TALLOC_CTX *mem_ctx,
 
666
                                             const struct dcerpc_binding *binding,
 
667
                                             struct epm_tower *tower)
 
668
{
 
669
        const enum epm_protocol *protseq = NULL;
 
670
        int num_protocols = -1, i;
 
671
        NTSTATUS status;
 
672
 
 
673
        /* Find transport */
 
674
        for (i=0;i<ARRAY_SIZE(transports);i++) {
 
675
                if (transports[i].transport == binding->transport) {
 
676
                        protseq = transports[i].protseq;
 
677
                        num_protocols = transports[i].num_protocols;
 
678
                        break;
 
679
                }
 
680
        }
 
681
 
 
682
        if (num_protocols == -1) {
 
683
                DEBUG(0, ("Unable to find transport with id '%d'\n", binding->transport));
 
684
                return NT_STATUS_UNSUCCESSFUL;
 
685
        }
 
686
 
 
687
        tower->num_floors = 2 + num_protocols;
 
688
        tower->floors = talloc_array(mem_ctx, struct epm_floor, tower->num_floors);
 
689
 
 
690
        /* Floor 0 */
 
691
        tower->floors[0].lhs.protocol = EPM_PROTOCOL_UUID;
 
692
 
 
693
        tower->floors[0].lhs.lhs_data = dcerpc_floor_pack_lhs_data(mem_ctx, &binding->object);
 
694
 
 
695
        tower->floors[0].rhs.uuid.unknown = data_blob_talloc_zero(mem_ctx, 2);
 
696
 
 
697
        /* Floor 1 */
 
698
        tower->floors[1].lhs.protocol = EPM_PROTOCOL_UUID;
 
699
 
 
700
        tower->floors[1].lhs.lhs_data = dcerpc_floor_pack_lhs_data(mem_ctx, 
 
701
                                                                &ndr_transfer_syntax);
 
702
 
 
703
        tower->floors[1].rhs.uuid.unknown = data_blob_talloc_zero(mem_ctx, 2);
 
704
 
 
705
        /* Floor 2 to num_protocols */
 
706
        for (i = 0; i < num_protocols; i++) {
 
707
                tower->floors[2 + i].lhs.protocol = protseq[i];
 
708
                tower->floors[2 + i].lhs.lhs_data = data_blob_talloc(mem_ctx, NULL, 0);
 
709
                ZERO_STRUCT(tower->floors[2 + i].rhs);
 
710
                dcerpc_floor_set_rhs_data(mem_ctx, &tower->floors[2 + i], "");
 
711
        }
 
712
 
 
713
        /* The 4th floor contains the endpoint */
 
714
        if (num_protocols >= 2 && binding->endpoint) {
 
715
                status = dcerpc_floor_set_rhs_data(mem_ctx, &tower->floors[3], binding->endpoint);
 
716
                if (NT_STATUS_IS_ERR(status)) {
 
717
                        return status;
 
718
                }
 
719
        }
 
720
 
 
721
        /* The 5th contains the network address */
 
722
        if (num_protocols >= 3 && binding->host) {
 
723
                if (is_ipaddress(binding->host)) {
 
724
                        status = dcerpc_floor_set_rhs_data(mem_ctx, &tower->floors[4], 
 
725
                                                           binding->host);
 
726
                } else {
 
727
                        /* note that we don't attempt to resolve the
 
728
                           name here - when we get a hostname here we
 
729
                           are in the client code, and want to put in
 
730
                           a wildcard all-zeros IP for the server to
 
731
                           fill in */
 
732
                        status = dcerpc_floor_set_rhs_data(mem_ctx, &tower->floors[4], 
 
733
                                                           "0.0.0.0");
 
734
                }
 
735
                if (NT_STATUS_IS_ERR(status)) {
 
736
                        return status;
 
737
                }
 
738
        }
 
739
 
 
740
        return NT_STATUS_OK;
 
741
}