~ubuntu-branches/ubuntu/vivid/samba/vivid

« back to all changes in this revision

Viewing changes to source3/rpc_server/epmapper/srv_epmapper.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2011-12-21 13:18:04 UTC
  • mfrom: (0.39.21 sid)
  • Revision ID: package-import@ubuntu.com-20111221131804-xtlr39wx6njehxxr
Tags: 2:3.6.1-3ubuntu1
* Merge from Debian testing.  Remaining changes:
  + debian/patches/VERSION.patch:
    - set SAMBA_VERSION_SUFFIX to Ubuntu.
  + debian/patches/error-trans.fix-276472:
    - Add the translation of Unix Error code -ENOTSUP to NT Error Code
    - NT_STATUS_NOT_SUPPORTED to prevent the Permission denied error.
  + debian/smb.conf:
    - add "(Samba, Ubuntu)" to server string.
    - comment out the default [homes] share, and add a comment about
      "valid users = %S" to show users how to restrict access to
      \\server\username to only username.
    - Set 'usershare allow guests', so that usershare admins are 
      allowed to create public shares in addition to authenticated
      ones.
    - add map to guest = Bad user, maps bad username to guest access.
  + debian/samba-common.config:
    - Do not change priority to high if dhclient3 is installed.
    - Use priority medium instead of high for the workgroup question.
  + debian/control:
    - Don't build against or suggest ctdb.
    - Add dependency on samba-common-bin to samba.
  + Add ufw integration:
    - Created debian/samba.ufw.profile
    - debian/rules, debian/samba.dirs, debian/samba.files: install
      profile
    - debian/control: have samba suggest ufw
  + Add apport hook:
    - Created debian/source_samba.py.
    - debian/rules, debian/samba.dirs, debian/samba-common-bin.files: install
  + Switch to upstart:
    - Add debian/samba.{nmbd,smbd}.upstart.
  + debian/samba.logrotate, debian/samba-common.dhcp, debian/samba.if-up:
    - Make them upstart compatible
  + debian/samba.postinst: 
    - Avoid scary pdbedit warnings on first import.
  + debian/samba-common.postinst: Add more informative error message for
    the case where smb.conf was manually deleted
  + debian/patches/fix-debuglevel-name-conflict.patch: don't use 'debug_level'
    as a global variable name in an NSS module 
  + Dropped:
    - debian/patches/error-trans.fix-276472
    - debian/patches/fix-debuglevel-name-conflict.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   Unix SMB/CIFS implementation.
 
3
 
 
4
   Endpoint server for the epmapper pipe
 
5
 
 
6
   Copyright (C) 2010-2011 Andreas Schneider <asn@samba.org>
 
7
 
 
8
   This program is free software; you can redistribute it and/or modify
 
9
   it under the terms of the GNU General Public License as published by
 
10
   the Free Software Foundation; either version 3 of the License, or
 
11
   (at your option) any later version.
 
12
 
 
13
   This program is distributed in the hope that it will be useful,
 
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
   GNU General Public License for more details.
 
17
 
 
18
   You should have received a copy of the GNU General Public License
 
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
20
*/
 
21
 
 
22
#include "includes.h"
 
23
#include "ntdomain.h"
 
24
#include "../libcli/security/security.h"
 
25
#include "librpc/gen_ndr/srv_epmapper.h"
 
26
#include "srv_epmapper.h"
 
27
#include "auth.h"
 
28
 
 
29
typedef uint32_t error_status_t;
 
30
 
 
31
/* An endpoint combined with an interface description */
 
32
struct dcesrv_ep_iface {
 
33
        const char *name;
 
34
        struct ndr_syntax_id syntax_id;
 
35
        struct epm_tower ep;
 
36
};
 
37
 
 
38
/* A rpc service interface like samr, lsarpc or netlogon */
 
39
struct dcesrv_iface {
 
40
        const char *name;
 
41
        struct ndr_syntax_id syntax_id;
 
42
};
 
43
 
 
44
struct dcesrv_iface_list {
 
45
        struct dcesrv_iface_list *next, *prev;
 
46
        struct dcesrv_iface *iface;
 
47
};
 
48
 
 
49
/*
 
50
 * An endpoint can serve multiple rpc services interfaces.
 
51
 * For example \\pipe\netlogon can be used by lsarpc and netlogon.
 
52
 */
 
53
struct dcesrv_endpoint {
 
54
        struct dcesrv_endpoint *next, *prev;
 
55
 
 
56
        /* The type and the location of the endpoint */
 
57
        struct dcerpc_binding *ep_description;
 
58
 
 
59
        /* A list of rpc services able to connect to the endpoint */
 
60
        struct dcesrv_iface_list *iface_list;
 
61
};
 
62
 
 
63
struct dcesrv_ep_entry_list {
 
64
        struct dcesrv_ep_entry_list *next, *prev;
 
65
 
 
66
        uint32_t num_ents;
 
67
        struct epm_entry_t *entries;
 
68
};
 
69
 
 
70
struct rpc_eps {
 
71
        struct dcesrv_ep_iface *e;
 
72
        uint32_t count;
 
73
};
 
74
 
 
75
static struct dcesrv_endpoint *endpoint_table;
 
76
 
 
77
/*
 
78
 * Check if the UUID and if_version match to an interface.
 
79
 */
 
80
static bool interface_match(const struct dcesrv_iface *if1,
 
81
                            const struct dcesrv_iface *if2)
 
82
{
 
83
        return GUID_equal(&if1->syntax_id.uuid, &if2->syntax_id.uuid);
 
84
}
 
85
 
 
86
/*
 
87
 * Find the interface operations on an endpoint.
 
88
 */
 
89
static const struct dcesrv_iface *find_interface(const struct dcesrv_endpoint *endpoint,
 
90
                                                 const struct dcesrv_iface *iface)
 
91
{
 
92
        struct dcesrv_iface_list *iflist;
 
93
 
 
94
        for (iflist = endpoint->iface_list; iflist; iflist = iflist->next) {
 
95
                if (interface_match(iflist->iface, iface)) {
 
96
                        return iflist->iface;
 
97
                }
 
98
        }
 
99
 
 
100
        return NULL;
 
101
}
 
102
 
 
103
/*
 
104
 * See if a uuid and if_version match to an interface
 
105
 */
 
106
static bool interface_match_by_uuid(const struct dcesrv_iface *iface,
 
107
                                    const struct GUID *uuid)
 
108
{
 
109
        return GUID_equal(&iface->syntax_id.uuid, uuid);
 
110
}
 
111
 
 
112
static struct dcesrv_iface_list *find_interface_list(const struct dcesrv_endpoint *endpoint,
 
113
                                                     const struct dcesrv_iface *iface)
 
114
{
 
115
        struct dcesrv_iface_list *iflist;
 
116
 
 
117
        for (iflist = endpoint->iface_list; iflist; iflist = iflist->next) {
 
118
                if (interface_match(iflist->iface, iface)) {
 
119
                        return iflist;
 
120
                }
 
121
        }
 
122
 
 
123
        return NULL;
 
124
}
 
125
 
 
126
/*
 
127
 * Check if two endpoints match.
 
128
 */
 
129
static bool endpoints_match(const struct dcerpc_binding *ep1,
 
130
                            const struct dcerpc_binding *ep2)
 
131
{
 
132
        if (ep1->transport != ep2->transport) {
 
133
                return false;
 
134
        }
 
135
 
 
136
        if (!ep1->endpoint || !ep2->endpoint) {
 
137
                return ep1->endpoint == ep2->endpoint;
 
138
        }
 
139
 
 
140
        if (!strequal(ep1->endpoint, ep2->endpoint)) {
 
141
                return false;
 
142
        }
 
143
 
 
144
        return true;
 
145
}
 
146
 
 
147
static struct dcesrv_endpoint *find_endpoint(struct dcesrv_endpoint *endpoint_list,
 
148
                                             struct dcerpc_binding *ep_description) {
 
149
        struct dcesrv_endpoint *ep;
 
150
 
 
151
        for (ep = endpoint_list; ep != NULL; ep = ep->next) {
 
152
                if (endpoints_match(ep->ep_description, ep_description)) {
 
153
                        return ep;
 
154
                }
 
155
        }
 
156
 
 
157
        return NULL;
 
158
}
 
159
 
 
160
/*
 
161
 * Build a list of all interfaces handled by all endpoint servers.
 
162
 */
 
163
static uint32_t build_ep_list(TALLOC_CTX *mem_ctx,
 
164
                              struct dcesrv_endpoint *endpoint_list,
 
165
                              const struct GUID *uuid,
 
166
                              const char *srv_addr,
 
167
                              struct dcesrv_ep_iface **peps)
 
168
{
 
169
        struct dcesrv_ep_iface *eps = NULL;
 
170
        struct dcesrv_endpoint *d;
 
171
        uint32_t total = 0;
 
172
        NTSTATUS status;
 
173
 
 
174
        *peps = NULL;
 
175
 
 
176
        for (d = endpoint_list; d != NULL; d = d->next) {
 
177
                struct dcesrv_iface_list *iface;
 
178
                struct dcerpc_binding *description;
 
179
 
 
180
                for (iface = d->iface_list; iface != NULL; iface = iface->next) {
 
181
                        if (uuid && !interface_match_by_uuid(iface->iface, uuid)) {
 
182
                                continue;
 
183
                        }
 
184
 
 
185
                        eps = talloc_realloc(mem_ctx,
 
186
                                             eps,
 
187
                                             struct dcesrv_ep_iface,
 
188
                                             total + 1);
 
189
                        if (eps == NULL) {
 
190
                                return 0;
 
191
                        }
 
192
                        eps[total].name = talloc_strdup(eps,
 
193
                                                        iface->iface->name);
 
194
                        eps[total].syntax_id = iface->iface->syntax_id;
 
195
 
 
196
                        description = dcerpc_binding_dup(mem_ctx, d->ep_description);
 
197
                        if (description == NULL) {
 
198
                                return 0;
 
199
                        }
 
200
                        description->object = iface->iface->syntax_id;
 
201
                        if (description->transport == NCACN_IP_TCP &&
 
202
                            srv_addr != NULL &&
 
203
                            (strcmp(description->host, "0.0.0.0") == 0 ||
 
204
                             strcmp(description->host, "::") == 0)) {
 
205
                                description->host = srv_addr;
 
206
                        }
 
207
 
 
208
                        status = dcerpc_binding_build_tower(eps,
 
209
                                                            description,
 
210
                                                            &eps[total].ep);
 
211
                        TALLOC_FREE(description);
 
212
                        if (NT_STATUS_IS_ERR(status)) {
 
213
                                DEBUG(1, ("Unable to build tower for %s\n",
 
214
                                          iface->iface->name));
 
215
                                continue;
 
216
                        }
 
217
                        total++;
 
218
                }
 
219
        }
 
220
 
 
221
        *peps = eps;
 
222
 
 
223
        return total;
 
224
}
 
225
 
 
226
static bool is_priviledged_pipe(struct auth_serversupplied_info *info) {
 
227
        /* If the user is not root, or has the system token, fail */
 
228
        if ((info->utok.uid != sec_initial_uid()) &&
 
229
            !security_token_is_system(info->security_token)) {
 
230
                return false;
 
231
        }
 
232
 
 
233
        return true;
 
234
}
 
235
 
 
236
bool srv_epmapper_delete_endpoints(struct pipes_struct *p)
 
237
{
 
238
        struct epm_Delete r;
 
239
        struct dcesrv_ep_entry_list *el = p->ep_entries;
 
240
        error_status_t result;
 
241
 
 
242
        while (el) {
 
243
                struct dcesrv_ep_entry_list *next = el->next;
 
244
 
 
245
                r.in.num_ents = el->num_ents;
 
246
                r.in.entries = el->entries;
 
247
 
 
248
                DEBUG(10, ("Delete_endpoints for: %s\n",
 
249
                           el->entries[0].annotation));
 
250
 
 
251
                result = _epm_Delete(p, &r);
 
252
                if (result != EPMAPPER_STATUS_OK) {
 
253
                        return false;
 
254
                }
 
255
 
 
256
                DLIST_REMOVE(p->ep_entries, el);
 
257
                TALLOC_FREE(el);
 
258
 
 
259
                el = next;
 
260
        }
 
261
 
 
262
        return true;
 
263
}
 
264
 
 
265
void srv_epmapper_cleanup(void)
 
266
{
 
267
        struct dcesrv_endpoint *ep = endpoint_table;
 
268
 
 
269
        while (ep) {
 
270
                struct dcesrv_endpoint *next = ep->next;
 
271
 
 
272
                DLIST_REMOVE(endpoint_table, ep);
 
273
                TALLOC_FREE(ep);
 
274
 
 
275
                ep = next;
 
276
        }
 
277
}
 
278
 
 
279
/*
 
280
 * epm_Insert
 
281
 *
 
282
 * Add the specified entries to an endpoint map.
 
283
 */
 
284
error_status_t _epm_Insert(struct pipes_struct *p,
 
285
                           struct epm_Insert *r)
 
286
{
 
287
        TALLOC_CTX *tmp_ctx;
 
288
        error_status_t rc;
 
289
        NTSTATUS status;
 
290
        uint32_t i;
 
291
        struct dcerpc_binding *b;
 
292
        struct dcesrv_endpoint *ep;
 
293
        struct dcesrv_iface_list *iflist;
 
294
        struct dcesrv_iface *iface;
 
295
        bool add_ep;
 
296
 
 
297
        /* If this is not a priviledged users, return */
 
298
        if (p->transport != NCALRPC ||
 
299
            !is_priviledged_pipe(p->session_info)) {
 
300
                return EPMAPPER_STATUS_CANT_PERFORM_OP;
 
301
        }
 
302
 
 
303
        tmp_ctx = talloc_stackframe();
 
304
        if (tmp_ctx == NULL) {
 
305
                return EPMAPPER_STATUS_NO_MEMORY;
 
306
        }
 
307
 
 
308
        DEBUG(3, ("_epm_Insert: Trying to add %u new entries.\n",
 
309
                  r->in.num_ents));
 
310
 
 
311
        for (i = 0; i < r->in.num_ents; i++) {
 
312
                add_ep = false;
 
313
                b = NULL;
 
314
 
 
315
                status = dcerpc_binding_from_tower(tmp_ctx,
 
316
                                                   &r->in.entries[i].tower->tower,
 
317
                                                   &b);
 
318
                if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
 
319
                        rc = EPMAPPER_STATUS_NO_MEMORY;
 
320
                        goto done;
 
321
                }
 
322
                if (!NT_STATUS_IS_OK(status)) {
 
323
                        rc = EPMAPPER_STATUS_CANT_PERFORM_OP;
 
324
                        goto done;
 
325
                }
 
326
 
 
327
                DEBUG(3, ("_epm_Insert: Adding transport %s for %s\n",
 
328
                          derpc_transport_string_by_transport(b->transport),
 
329
                          r->in.entries[i].annotation));
 
330
 
 
331
                /* Check if the entry already exits */
 
332
                ep = find_endpoint(endpoint_table, b);
 
333
                if (ep == NULL) {
 
334
                        /* No entry found, create it */
 
335
                        ep = talloc_zero(NULL, struct dcesrv_endpoint);
 
336
                        if (ep == NULL) {
 
337
                                rc = EPMAPPER_STATUS_NO_MEMORY;
 
338
                                goto done;
 
339
                        }
 
340
                        add_ep = true;
 
341
 
 
342
                        ep->ep_description = talloc_steal(ep, b);
 
343
                }
 
344
 
 
345
                /* TODO Replace the entry if the replace flag is set */
 
346
 
 
347
                /* Create an interface */
 
348
                iface = talloc(tmp_ctx, struct dcesrv_iface);
 
349
                if (iface == NULL) {
 
350
                        rc = EPMAPPER_STATUS_NO_MEMORY;
 
351
                        goto done;
 
352
                }
 
353
 
 
354
                iface->name = talloc_strdup(iface, r->in.entries[i].annotation);
 
355
                if (iface->name == NULL) {
 
356
                        rc = EPMAPPER_STATUS_NO_MEMORY;
 
357
                        goto done;
 
358
                }
 
359
                iface->syntax_id = b->object;
 
360
 
 
361
                /*
 
362
                 * Check if the rpc service is alrady registered on the
 
363
                 * endpoint.
 
364
                 */
 
365
                if (find_interface(ep, iface) != NULL) {
 
366
                        DEBUG(0, ("dcesrv_interface_register: interface '%s' "
 
367
                                  "already registered on endpoint\n",
 
368
                                  iface->name));
 
369
                        /* FIXME wrong error code? */
 
370
                        rc = EPMAPPER_STATUS_OK;
 
371
                        goto done;
 
372
                }
 
373
 
 
374
                /* Create an entry for the interface */
 
375
                iflist = talloc(ep, struct dcesrv_iface_list);
 
376
                if (iflist == NULL) {
 
377
                        rc = EPMAPPER_STATUS_NO_MEMORY;
 
378
                        goto done;
 
379
                }
 
380
                iflist->iface = talloc_move(iflist, &iface);
 
381
 
 
382
                /* Finally add the interface on the endpoint */
 
383
                DLIST_ADD(ep->iface_list, iflist);
 
384
 
 
385
                /* If it's a new endpoint add it to the endpoint_table */
 
386
                if (add_ep) {
 
387
                        DLIST_ADD(endpoint_table, ep);
 
388
                }
 
389
        }
 
390
 
 
391
        if (r->in.num_ents > 0) {
 
392
                struct dcesrv_ep_entry_list *el;
 
393
 
 
394
                el = talloc_zero(p, struct dcesrv_ep_entry_list);
 
395
                if (el == NULL) {
 
396
                        rc = EPMAPPER_STATUS_NO_MEMORY;
 
397
                        goto done;
 
398
                }
 
399
                el->num_ents = r->in.num_ents;
 
400
                el->entries = talloc_move(el, &r->in.entries);
 
401
 
 
402
                DLIST_ADD(p->ep_entries, el);
 
403
        }
 
404
 
 
405
        rc = EPMAPPER_STATUS_OK;
 
406
done:
 
407
        talloc_free(tmp_ctx);
 
408
 
 
409
        return rc;
 
410
}
 
411
 
 
412
 
 
413
/*
 
414
 * epm_Delete
 
415
 *
 
416
 * Delete the specified entries from an endpoint map.
 
417
 */
 
418
error_status_t _epm_Delete(struct pipes_struct *p,
 
419
                           struct epm_Delete *r)
 
420
{
 
421
        TALLOC_CTX *tmp_ctx;
 
422
        error_status_t rc;
 
423
        NTSTATUS status;
 
424
        uint32_t i;
 
425
        struct dcerpc_binding *b;
 
426
        struct dcesrv_endpoint *ep;
 
427
        struct dcesrv_iface iface;
 
428
        struct dcesrv_iface_list *iflist;
 
429
 
 
430
        DEBUG(3, ("_epm_Delete: Trying to delete %u entries.\n",
 
431
                  r->in.num_ents));
 
432
 
 
433
        /* If this is not a priviledged users, return */
 
434
        if (p->transport != NCALRPC ||
 
435
            !is_priviledged_pipe(p->session_info)) {
 
436
                return EPMAPPER_STATUS_CANT_PERFORM_OP;
 
437
        }
 
438
 
 
439
        tmp_ctx = talloc_stackframe();
 
440
        if (tmp_ctx == NULL) {
 
441
                return EPMAPPER_STATUS_NO_MEMORY;
 
442
        }
 
443
 
 
444
        for (i = 0; i < r->in.num_ents; i++) {
 
445
                b = NULL;
 
446
 
 
447
                status = dcerpc_binding_from_tower(tmp_ctx,
 
448
                                                   &r->in.entries[i].tower->tower,
 
449
                                                   &b);
 
450
                if (!NT_STATUS_IS_OK(status)) {
 
451
                        rc = EPMAPPER_STATUS_NO_MEMORY;
 
452
                        goto done;
 
453
                }
 
454
 
 
455
                DEBUG(3, ("_epm_Delete: Deleting transport '%s' for '%s'\n",
 
456
                          derpc_transport_string_by_transport(b->transport),
 
457
                          r->in.entries[i].annotation));
 
458
 
 
459
                ep = find_endpoint(endpoint_table, b);
 
460
                if (ep == NULL) {
 
461
                        rc = EPMAPPER_STATUS_OK;
 
462
                        goto done;
 
463
                }
 
464
 
 
465
                iface.name = r->in.entries[i].annotation;
 
466
                iface.syntax_id = b->object;
 
467
 
 
468
                iflist = find_interface_list(ep, &iface);
 
469
                if (iflist == NULL) {
 
470
                        DEBUG(0, ("_epm_Delete: No interfaces left, delete endpoint\n"));
 
471
                        DLIST_REMOVE(endpoint_table, ep);
 
472
                        talloc_free(ep);
 
473
 
 
474
                        rc = EPMAPPER_STATUS_OK;
 
475
                        goto done;
 
476
                }
 
477
 
 
478
                DLIST_REMOVE(ep->iface_list, iflist);
 
479
 
 
480
                if (ep->iface_list == NULL) {
 
481
                        DEBUG(0, ("_epm_Delete: No interfaces left, delete endpoint\n"));
 
482
                        DLIST_REMOVE(endpoint_table, ep);
 
483
                        talloc_free(ep);
 
484
 
 
485
                        rc = EPMAPPER_STATUS_OK;
 
486
                        goto done;
 
487
                }
 
488
 
 
489
        }
 
490
 
 
491
        rc = EPMAPPER_STATUS_OK;
 
492
done:
 
493
        talloc_free(tmp_ctx);
 
494
 
 
495
        return rc;
 
496
}
 
497
 
 
498
 
 
499
/*
 
500
 * epm_Lookup
 
501
 *
 
502
 * Lookup entries in an endpoint map.
 
503
 */
 
504
error_status_t _epm_Lookup(struct pipes_struct *p,
 
505
                           struct epm_Lookup *r)
 
506
{
 
507
        struct policy_handle *entry_handle;
 
508
        struct rpc_eps *eps;
 
509
        TALLOC_CTX *tmp_ctx;
 
510
        error_status_t rc;
 
511
        uint32_t count = 0;
 
512
        uint32_t num_ents = 0;
 
513
        uint32_t i;
 
514
        bool match = false;
 
515
        bool ok;
 
516
 
 
517
        *r->out.num_ents = 0;
 
518
        r->out.entries = NULL;
 
519
 
 
520
        tmp_ctx = talloc_stackframe();
 
521
        if (tmp_ctx == NULL) {
 
522
                return EPMAPPER_STATUS_NO_MEMORY;
 
523
        }
 
524
 
 
525
        DEBUG(3, ("_epm_Lookup: Trying to lookup max. %u entries.\n",
 
526
                  r->in.max_ents));
 
527
 
 
528
        if (r->in.entry_handle == NULL ||
 
529
            policy_handle_empty(r->in.entry_handle)) {
 
530
                struct GUID *obj;
 
531
 
 
532
                DEBUG(5, ("_epm_Lookup: No entry_handle found, creating it.\n"));
 
533
 
 
534
                eps = talloc_zero(tmp_ctx, struct rpc_eps);
 
535
                if (eps == NULL) {
 
536
                        rc = EPMAPPER_STATUS_NO_MEMORY;
 
537
                        goto done;
 
538
                }
 
539
 
 
540
                if (r->in.object == NULL || GUID_all_zero(r->in.object)) {
 
541
                        obj = NULL;
 
542
                } else {
 
543
                        obj = r->in.object;
 
544
                }
 
545
 
 
546
                switch (r->in.inquiry_type) {
 
547
                case RPC_C_EP_ALL_ELTS:
 
548
                        /*
 
549
                         * Return all elements from the endpoint map. The
 
550
                         * interface_id, vers_option, and object parameters MUST
 
551
                         * be ignored.
 
552
                         */
 
553
                        eps->count = build_ep_list(eps,
 
554
                                                   endpoint_table,
 
555
                                                   NULL,
 
556
                                                   p->server_id == NULL ? NULL : p->server_id->addr,
 
557
                                                   &eps->e);
 
558
                        break;
 
559
                case RPC_C_EP_MATCH_BY_IF:
 
560
                        /*
 
561
                         * Return endpoint map elements that contain the
 
562
                         * interface identifier specified by the interface_id
 
563
                         * and vers_option values.
 
564
                         *
 
565
                         * RPC_C_EP_MATCH_BY_IF and RPC_C_EP_MATCH_BY_BOTH
 
566
                         * need both the same endpoint list. There is a second
 
567
                         * check for the inquiry_type below which differentiates
 
568
                         * between them.
 
569
                         */
 
570
                case RPC_C_EP_MATCH_BY_BOTH:
 
571
                        /*
 
572
                         * Return endpoint map elements that contain the
 
573
                         * interface identifier and object UUID specified by
 
574
                         * interface_id, vers_option, and object.
 
575
                         */
 
576
                        eps->count = build_ep_list(eps,
 
577
                                                   endpoint_table,
 
578
                                                   &r->in.interface_id->uuid,
 
579
                                                   p->server_id == NULL ? NULL : p->server_id->addr,
 
580
                                                   &eps->e);
 
581
                        break;
 
582
                case RPC_C_EP_MATCH_BY_OBJ:
 
583
                        /*
 
584
                         * Return endpoint map elements that contain the object
 
585
                         * UUID specified by object.
 
586
                         */
 
587
                        eps->count = build_ep_list(eps,
 
588
                                                   endpoint_table,
 
589
                                                   r->in.object,
 
590
                                                   p->server_id == NULL ? NULL : p->server_id->addr,
 
591
                                                   &eps->e);
 
592
                        break;
 
593
                default:
 
594
                        rc = EPMAPPER_STATUS_CANT_PERFORM_OP;
 
595
                        goto done;
 
596
                }
 
597
 
 
598
                if (eps->count == 0) {
 
599
                        rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
 
600
                        goto done;
 
601
                }
 
602
 
 
603
                ok = create_policy_hnd(p, r->out.entry_handle, eps);
 
604
                if (!ok) {
 
605
                        rc = EPMAPPER_STATUS_NO_MEMORY;
 
606
                        goto done;
 
607
                }
 
608
 
 
609
                ok = find_policy_by_hnd(p, r->out.entry_handle, (void **)(void*) &eps);
 
610
                if (!ok) {
 
611
                        rc = EPMAPPER_STATUS_NO_MEMORY;
 
612
                        goto done;
 
613
                }
 
614
                entry_handle = r->out.entry_handle;
 
615
        } else {
 
616
                DEBUG(5, ("_epm_Lookup: Trying to find entry_handle.\n"));
 
617
 
 
618
                ok = find_policy_by_hnd(p, r->in.entry_handle, (void **)(void*) &eps);
 
619
                if (!ok) {
 
620
                        rc = EPMAPPER_STATUS_NO_MEMORY;
 
621
                        goto done;
 
622
                }
 
623
                entry_handle = r->in.entry_handle;
 
624
        }
 
625
 
 
626
        if (eps == NULL || eps->e == NULL) {
 
627
                rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
 
628
                goto done;
 
629
        }
 
630
 
 
631
        /* return the next N elements */
 
632
        count = r->in.max_ents;
 
633
        if (count > eps->count) {
 
634
                count = eps->count;
 
635
        }
 
636
 
 
637
        DEBUG(3, ("_epm_Lookup: Find %u entries\n", count));
 
638
 
 
639
        if (count == 0) {
 
640
                close_policy_hnd(p, entry_handle);
 
641
                ZERO_STRUCTP(r->out.entry_handle);
 
642
 
 
643
                rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
 
644
                goto done;
 
645
        }
 
646
 
 
647
        r->out.entries = talloc_array(p->mem_ctx, struct epm_entry_t, count);
 
648
        if (r->out.entries == NULL) {
 
649
                rc = EPMAPPER_STATUS_NO_MEMORY;
 
650
                goto done;
 
651
        }
 
652
 
 
653
        for (i = 0; i < count; i++) {
 
654
                match = false;
 
655
 
 
656
                switch (r->in.inquiry_type) {
 
657
                case RPC_C_EP_ALL_ELTS:
 
658
                        /*
 
659
                         * Return all elements from the endpoint map. The
 
660
                         * interface_id, vers_option, and object parameters MUST
 
661
                         * be ignored.
 
662
                         */
 
663
                        match = true;
 
664
                        break;
 
665
                case RPC_C_EP_MATCH_BY_IF:
 
666
                        /*
 
667
                         * Return endpoint map elements that contain the
 
668
                         * interface identifier specified by the interface_id
 
669
                         * and vers_option values.
 
670
                         */
 
671
                        if (GUID_equal(&r->in.interface_id->uuid,
 
672
                                       &eps->e[i].syntax_id.uuid)) {
 
673
                                match = true;
 
674
                        }
 
675
                        break;
 
676
                case RPC_C_EP_MATCH_BY_OBJ:
 
677
                        /*
 
678
                         * Return endpoint map elements that contain the object
 
679
                         * UUID specified by object.
 
680
                         */
 
681
                        if (GUID_equal(r->in.object,
 
682
                                       &eps->e[i].syntax_id.uuid)) {
 
683
                                match = true;
 
684
                        }
 
685
                        break;
 
686
                case RPC_C_EP_MATCH_BY_BOTH:
 
687
                        /*
 
688
                         * Return endpoint map elements that contain the
 
689
                         * interface identifier and object UUID specified by
 
690
                         * interface_id, vers_option, and object.
 
691
                         */
 
692
                        if (GUID_equal(&r->in.interface_id->uuid,
 
693
                                       &eps->e[i].syntax_id.uuid) &&
 
694
                            GUID_equal(r->in.object, &eps->e[i].syntax_id.uuid)) {
 
695
                                match = true;
 
696
                        }
 
697
                        break;
 
698
                default:
 
699
                        return EPMAPPER_STATUS_CANT_PERFORM_OP;
 
700
                }
 
701
 
 
702
                if (match) {
 
703
                        if (r->in.inquiry_type == RPC_C_EP_MATCH_BY_IF ||
 
704
                            r->in.inquiry_type == RPC_C_EP_MATCH_BY_OBJ) {
 
705
                                /* Check inteface version */
 
706
 
 
707
                                match = false;
 
708
                                switch (r->in.vers_option) {
 
709
                                case RPC_C_VERS_ALL:
 
710
                                        /*
 
711
                                         * Return endpoint map elements that
 
712
                                         * contain the specified interface UUID,
 
713
                                         * regardless of the version numbers.
 
714
                                         */
 
715
                                        match = true;
 
716
                                        break;
 
717
                                case RPC_C_VERS_COMPATIBLE:
 
718
                                        /*
 
719
                                         * Return the endpoint map elements that
 
720
                                         * contain the same major versions of
 
721
                                         * the specified interface UUID and a
 
722
                                         * minor version greater than or equal
 
723
                                         * to the minor version of the specified
 
724
                                         * UUID.
 
725
                                         */
 
726
                                        if (r->in.interface_id->vers_major ==
 
727
                                            (eps->e[i].syntax_id.if_version >> 16) &&
 
728
                                            r->in.interface_id->vers_minor <=
 
729
                                            (eps->e[i].syntax_id.if_version && 0xFFFF)) {
 
730
                                                match = true;
 
731
                                        }
 
732
                                        break;
 
733
                                case RPC_C_VERS_EXACT:
 
734
                                        /*
 
735
                                         * Return endpoint map elements that
 
736
                                         * contain the specified version of the
 
737
                                         * specified interface UUID.
 
738
                                         */
 
739
                                        if (r->in.interface_id->vers_major ==
 
740
                                            (eps->e[i].syntax_id.if_version >> 16) &&
 
741
                                            r->in.interface_id->vers_minor ==
 
742
                                            (eps->e[i].syntax_id.if_version && 0xFFFF)) {
 
743
                                                match = true;
 
744
                                        }
 
745
                                        match = true;
 
746
                                        break;
 
747
                                case RPC_C_VERS_MAJOR_ONLY:
 
748
                                        /*
 
749
                                         * Return endpoint map elements that
 
750
                                         * contain the same version of the
 
751
                                         * specified interface UUID and ignore
 
752
                                         * the minor version.
 
753
                                         */
 
754
                                        if (r->in.interface_id->vers_major ==
 
755
                                            (eps->e[i].syntax_id.if_version >> 16)) {
 
756
                                                match = true;
 
757
                                        }
 
758
                                        match = true;
 
759
                                        break;
 
760
                                case RPC_C_VERS_UPTO:
 
761
                                        /*
 
762
                                         * Return endpoint map elements that
 
763
                                         * contain a version of the specified
 
764
                                         * interface UUID less than or equal to
 
765
                                         * the specified major and minor
 
766
                                         * version.
 
767
                                         */
 
768
                                        if (r->in.interface_id->vers_major >
 
769
                                            eps->e[i].syntax_id.if_version >> 16) {
 
770
                                                match = true;
 
771
                                        } else {
 
772
                                                if (r->in.interface_id->vers_major ==
 
773
                                                    (eps->e[i].syntax_id.if_version >> 16) &&
 
774
                                                    r->in.interface_id->vers_minor >=
 
775
                                                    (eps->e[i].syntax_id.if_version && 0xFFFF)) {
 
776
                                                        match = true;
 
777
                                                }
 
778
                                        }
 
779
                                        break;
 
780
                                default:
 
781
                                        return EPMAPPER_STATUS_CANT_PERFORM_OP;
 
782
                                }
 
783
                        }
 
784
                }
 
785
 
 
786
                if (match) {
 
787
                        ZERO_STRUCT(r->out.entries[num_ents].object);
 
788
 
 
789
                        DEBUG(10, ("_epm_Lookup: Adding tower for '%s'\n",
 
790
                                   eps->e[i].name));
 
791
                        r->out.entries[num_ents].annotation = talloc_strdup(r->out.entries,
 
792
                                                                            eps->e[i].name);
 
793
                        r->out.entries[num_ents].tower = talloc(r->out.entries,
 
794
                                                                struct epm_twr_t);
 
795
                        if (r->out.entries[num_ents].tower == NULL) {
 
796
                                rc = EPMAPPER_STATUS_NO_MEMORY;
 
797
                                goto done;
 
798
                        }
 
799
                        r->out.entries[num_ents].tower->tower.floors = talloc_move(r->out.entries[num_ents].tower, &eps->e[i].ep.floors);
 
800
                        r->out.entries[num_ents].tower->tower.num_floors = eps->e[i].ep.num_floors;
 
801
                        r->out.entries[num_ents].tower->tower_length = 0;
 
802
 
 
803
                        num_ents++;
 
804
                }
 
805
        } /* end for loop */
 
806
 
 
807
        *r->out.num_ents = num_ents;
 
808
 
 
809
        eps->count -= count;
 
810
        eps->e += count;
 
811
        if (eps->count == 0) {
 
812
                close_policy_hnd(p, entry_handle);
 
813
                ZERO_STRUCTP(r->out.entry_handle);
 
814
                rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
 
815
                goto done;
 
816
        }
 
817
 
 
818
        rc = EPMAPPER_STATUS_OK;
 
819
done:
 
820
        talloc_free(tmp_ctx);
 
821
 
 
822
        return rc;
 
823
}
 
824
 
 
825
/*
 
826
 * epm_Map
 
827
 *
 
828
 * Apply some algorithm (using the fields in the map_tower) to an endpoint map
 
829
 * to produce a list of protocol towers.
 
830
 */
 
831
error_status_t _epm_Map(struct pipes_struct *p,
 
832
                        struct epm_Map *r)
 
833
{
 
834
        struct policy_handle *entry_handle;
 
835
        enum dcerpc_transport_t transport;
 
836
        struct ndr_syntax_id ifid;
 
837
        struct epm_floor *floors;
 
838
        struct rpc_eps *eps;
 
839
        TALLOC_CTX *tmp_ctx;
 
840
        error_status_t rc;
 
841
        uint32_t count = 0;
 
842
        uint32_t num_towers = 0;
 
843
        uint32_t num_floors = 0;
 
844
        uint32_t i;
 
845
        bool ok;
 
846
 
 
847
        *r->out.num_towers = 0;
 
848
        r->out.towers = NULL;
 
849
 
 
850
        if (r->in.map_tower == NULL || r->in.max_towers == 0 ||
 
851
            r->in.map_tower->tower.num_floors < 3) {
 
852
                return EPMAPPER_STATUS_NO_MORE_ENTRIES;
 
853
        }
 
854
 
 
855
        tmp_ctx = talloc_stackframe();
 
856
        if (tmp_ctx == NULL) {
 
857
                return EPMAPPER_STATUS_NO_MEMORY;
 
858
        }
 
859
 
 
860
        ZERO_STRUCTP(r->out.entry_handle);
 
861
 
 
862
        DEBUG(3, ("_epm_Map: Trying to map max. %u towers.\n",
 
863
                  r->in.max_towers));
 
864
 
 
865
        /*
 
866
         * A tower has normally up to 6 floors
 
867
         *
 
868
         * +-----------------------------------------------------------------+
 
869
         * | Floor 1 | Provides the RPC interface identifier. (e.g. UUID for |
 
870
         * |         | netlogon)                                             |
 
871
         * +---------+-------------------------------------------------------+
 
872
         * | Floor 2 | Transfer syntax (NDR endcoded)                        |
 
873
         * +---------+-------------------------------------------------------+
 
874
         * | Floor 3 | RPC protocol identifier (ncacn_tcp_ip, ncacn_np, ...) |
 
875
         * +---------+-------------------------------------------------------+
 
876
         * | Floor 4 | Port address (e.g. TCP Port: 49156)                   |
 
877
         * +---------+-------------------------------------------------------+
 
878
         * | Floor 5 | Transport (e.g. IP:192.168.51.10)                     |
 
879
         * +---------+-------------------------------------------------------+
 
880
         * | Floor 6 | Routing                                               |
 
881
         * +---------+-------------------------------------------------------+
 
882
         */
 
883
        num_floors = r->in.map_tower->tower.num_floors;
 
884
        floors = r->in.map_tower->tower.floors;
 
885
 
 
886
        /* We accept NDR as the transfer syntax */
 
887
        dcerpc_floor_get_lhs_data(&floors[1], &ifid);
 
888
 
 
889
        if (floors[1].lhs.protocol != EPM_PROTOCOL_UUID ||
 
890
            !GUID_equal(&ifid.uuid, &ndr_transfer_syntax.uuid) ||
 
891
            ifid.if_version != ndr_transfer_syntax.if_version) {
 
892
                rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
 
893
                goto done;
 
894
        }
 
895
 
 
896
        /* We only talk to sane transports */
 
897
        transport = dcerpc_transport_by_tower(&r->in.map_tower->tower);
 
898
        if (transport == NCA_UNKNOWN) {
 
899
                DEBUG(2, ("epm_Map: Client requested unknown transport with"
 
900
                          "levels: "));
 
901
                for (i = 2; i < r->in.map_tower->tower.num_floors; i++) {
 
902
                        DEBUG(2, ("%d, ", r->in.map_tower->tower.floors[i].lhs.protocol));
 
903
                }
 
904
                DEBUG(2, ("\n"));
 
905
                rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
 
906
                goto done;
 
907
        }
 
908
 
 
909
        if (r->in.entry_handle == NULL ||
 
910
            policy_handle_empty(r->in.entry_handle)) {
 
911
                struct GUID *obj;
 
912
 
 
913
                DEBUG(5, ("_epm_Map: No entry_handle found, creating it.\n"));
 
914
 
 
915
                eps = talloc_zero(tmp_ctx, struct rpc_eps);
 
916
                if (eps == NULL) {
 
917
                        rc = EPMAPPER_STATUS_NO_MEMORY;
 
918
                        goto done;
 
919
                }
 
920
 
 
921
                /*
 
922
                 * *** ATTENTION ***
 
923
                 * CDE 1.1 states:
 
924
                 *
 
925
                 * ept_map()
 
926
                 *     Apply some algorithm (using the fields in the map_tower)
 
927
                 *     to an endpoint map to produce a list of protocol towers.
 
928
                 *
 
929
                 * The following code is the mysterious "some algorithm"!
 
930
                 */
 
931
 
 
932
                /* Filter by object id if one was given. */
 
933
                if (r->in.object == NULL || GUID_all_zero(r->in.object)) {
 
934
                        obj = NULL;
 
935
                } else {
 
936
                        obj = r->in.object;
 
937
                }
 
938
 
 
939
                eps->count = build_ep_list(eps,
 
940
                                           endpoint_table,
 
941
                                           obj,
 
942
                                           p->server_id == NULL ? NULL : p->server_id->addr,
 
943
                                           &eps->e);
 
944
                if (eps->count == 0) {
 
945
                        rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
 
946
                        goto done;
 
947
                }
 
948
 
 
949
                /* Filter out endpoints which match the interface. */
 
950
                {
 
951
                        struct rpc_eps *teps;
 
952
                        uint32_t total = 0;
 
953
 
 
954
                        teps = talloc_zero(tmp_ctx, struct rpc_eps);
 
955
                        if (teps == NULL) {
 
956
                                rc = EPMAPPER_STATUS_NO_MEMORY;
 
957
                                goto done;
 
958
                        }
 
959
 
 
960
                        for (i = 0; i < eps->count; i++) {
 
961
                                if (data_blob_cmp(&r->in.map_tower->tower.floors[0].lhs.lhs_data,
 
962
                                                  &eps->e[i].ep.floors[0].lhs.lhs_data) != 0 ||
 
963
                                    transport != dcerpc_transport_by_tower(&eps->e[i].ep)) {
 
964
                                        continue;
 
965
                                }
 
966
 
 
967
                                teps->e = talloc_realloc(tmp_ctx,
 
968
                                                         teps->e,
 
969
                                                         struct dcesrv_ep_iface,
 
970
                                                         total + 1);
 
971
                                if (teps->e == NULL) {
 
972
                                        return 0;
 
973
                                }
 
974
 
 
975
                                teps->e[total].ep.floors = talloc_move(teps, &eps->e[i].ep.floors);
 
976
                                teps->e[total].ep.num_floors = eps->e[i].ep.num_floors;
 
977
                                teps->e[total].name = talloc_move(teps, &eps->e[i].name);
 
978
                                teps->e[total].syntax_id = eps->e[i].syntax_id;
 
979
 
 
980
                                total++;
 
981
                        }
 
982
 
 
983
                        teps->count = total;
 
984
                        talloc_free(eps);
 
985
                        eps = teps;
 
986
                }
 
987
                /* end of "some algorithm" */
 
988
 
 
989
                ok = create_policy_hnd(p, r->out.entry_handle, eps);
 
990
                if (!ok) {
 
991
                        rc = EPMAPPER_STATUS_NO_MEMORY;
 
992
                        goto done;
 
993
                }
 
994
 
 
995
                ok = find_policy_by_hnd(p, r->out.entry_handle, (void **)(void*) &eps);
 
996
                if (!ok) {
 
997
                        rc = EPMAPPER_STATUS_NO_MEMORY;
 
998
                        goto done;
 
999
                }
 
1000
                entry_handle = r->out.entry_handle;
 
1001
        } else {
 
1002
                DEBUG(5, ("_epm_Map: Trying to find entry_handle.\n"));
 
1003
 
 
1004
                ok = find_policy_by_hnd(p, r->in.entry_handle, (void **)(void*) &eps);
 
1005
                if (!ok) {
 
1006
                        rc = EPMAPPER_STATUS_NO_MEMORY;
 
1007
                        goto done;
 
1008
                }
 
1009
                entry_handle = r->in.entry_handle;
 
1010
        }
 
1011
 
 
1012
        if (eps == NULL || eps->e == NULL) {
 
1013
                rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
 
1014
                goto done;
 
1015
        }
 
1016
 
 
1017
        /* return the next N elements */
 
1018
        count = r->in.max_towers;
 
1019
        if (count > eps->count) {
 
1020
                count = eps->count;
 
1021
        }
 
1022
 
 
1023
        if (count == 0) {
 
1024
                close_policy_hnd(p, entry_handle);
 
1025
                ZERO_STRUCTP(r->out.entry_handle);
 
1026
 
 
1027
                rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
 
1028
                goto done;
 
1029
        }
 
1030
 
 
1031
        r->out.towers = talloc_array(p->mem_ctx, struct epm_twr_p_t, count);
 
1032
        if (r->out.towers == NULL) {
 
1033
                rc = EPMAPPER_STATUS_NO_MEMORY;
 
1034
                goto done;
 
1035
        }
 
1036
 
 
1037
        for (i = 0; i < count; i++) {
 
1038
                DEBUG(5, ("_epm_Map: Map tower for '%s'\n",
 
1039
                           eps->e[i].name));
 
1040
 
 
1041
                r->out.towers[num_towers].twr = talloc(r->out.towers,
 
1042
                                                       struct epm_twr_t);
 
1043
                if (r->out.towers[num_towers].twr == NULL) {
 
1044
                        rc = EPMAPPER_STATUS_NO_MEMORY;
 
1045
                        goto done;
 
1046
                }
 
1047
                r->out.towers[num_towers].twr->tower.floors = talloc_move(r->out.towers[num_towers].twr, &eps->e[i].ep.floors);
 
1048
                r->out.towers[num_towers].twr->tower.num_floors = eps->e[i].ep.num_floors;
 
1049
                r->out.towers[num_towers].twr->tower_length = 0;
 
1050
 
 
1051
                num_towers++;
 
1052
        }
 
1053
 
 
1054
        *r->out.num_towers = num_towers;
 
1055
 
 
1056
        eps->count -= count;
 
1057
        eps->e += count;
 
1058
        if (eps->count == 0) {
 
1059
                close_policy_hnd(p, entry_handle);
 
1060
                ZERO_STRUCTP(r->out.entry_handle);
 
1061
        }
 
1062
 
 
1063
        rc = EPMAPPER_STATUS_OK;
 
1064
done:
 
1065
        talloc_free(tmp_ctx);
 
1066
 
 
1067
        return rc;
 
1068
}
 
1069
 
 
1070
/*
 
1071
 * epm_LookupHandleFree
 
1072
 */
 
1073
error_status_t _epm_LookupHandleFree(struct pipes_struct *p,
 
1074
                                     struct epm_LookupHandleFree *r)
 
1075
{
 
1076
        if (r->in.entry_handle == NULL) {
 
1077
                return EPMAPPER_STATUS_OK;
 
1078
        }
 
1079
 
 
1080
        if (is_valid_policy_hnd(r->in.entry_handle)) {
 
1081
                close_policy_hnd(p, r->in.entry_handle);
 
1082
        }
 
1083
 
 
1084
        r->out.entry_handle = r->in.entry_handle;
 
1085
 
 
1086
        return EPMAPPER_STATUS_OK;
 
1087
}
 
1088
 
 
1089
 
 
1090
/*
 
1091
 * epm_InqObject
 
1092
 *
 
1093
 * A client implementation SHOULD NOT call this method. These extensions do not
 
1094
 * provide an alternative method.
 
1095
 */
 
1096
error_status_t _epm_InqObject(struct pipes_struct *p,
 
1097
                      struct epm_InqObject *r)
 
1098
{
 
1099
        p->rng_fault_state = true;
 
1100
        return EPMAPPER_STATUS_CANT_PERFORM_OP;
 
1101
}
 
1102
 
 
1103
 
 
1104
/*
 
1105
 * epm_MgmtDelete
 
1106
 *
 
1107
 * A client implementation SHOULD NOT call this method. These extensions do not
 
1108
 * provide an alternative method.
 
1109
*/
 
1110
error_status_t _epm_MgmtDelete(struct pipes_struct *p,
 
1111
                       struct epm_MgmtDelete *r)
 
1112
{
 
1113
        p->rng_fault_state = true;
 
1114
        return EPMAPPER_STATUS_CANT_PERFORM_OP;
 
1115
}
 
1116
 
 
1117
 
 
1118
/*
 
1119
  epm_MapAuth
 
1120
*/
 
1121
error_status_t _epm_MapAuth(struct pipes_struct *p,
 
1122
                    struct epm_MapAuth *r)
 
1123
{
 
1124
        p->rng_fault_state = true;
 
1125
        return EPMAPPER_STATUS_CANT_PERFORM_OP;
 
1126
}
 
1127
 
 
1128
/* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */