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

« back to all changes in this revision

Viewing changes to source4/dsdb/samdb/ldb_modules/extended_dn_store.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:
2
2
   ldb database library
3
3
 
4
4
   Copyright (C) Simo Sorce 2005-2008
5
 
   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2007-2008
 
5
   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2007-2009
6
6
 
7
7
   This program is free software; you can redistribute it and/or modify
8
8
   it under the terms of the GNU General Public License as published by
36
36
 */
37
37
 
38
38
#include "includes.h"
39
 
#include "ldb/include/ldb.h"
40
 
#include "ldb/include/ldb_errors.h"
41
 
#include "ldb/include/ldb_module.h"
 
39
#include <ldb.h>
 
40
#include <ldb_errors.h>
 
41
#include <ldb_module.h>
42
42
#include "librpc/gen_ndr/ndr_misc.h"
43
43
#include "dsdb/samdb/samdb.h"
44
44
#include "libcli/security/security.h"
45
 
 
 
45
#include "dsdb/samdb/ldb_modules/util.h"
46
46
#include <time.h>
47
47
 
48
48
struct extended_dn_replace_list {
49
49
        struct extended_dn_replace_list *next;
50
 
        struct ldb_dn *dn;
 
50
        struct dsdb_dn *dsdb_dn;
51
51
        TALLOC_CTX *mem_ctx;
52
52
        struct ldb_val *replace_dn;
53
53
        struct extended_dn_context *ac;
58
58
struct extended_dn_context {
59
59
        const struct dsdb_schema *schema;
60
60
        struct ldb_module *module;
 
61
        struct ldb_context *ldb;
61
62
        struct ldb_request *req;
62
63
        struct ldb_request *new_req;
63
64
 
70
71
                                                            struct ldb_request *req)
71
72
{
72
73
        struct extended_dn_context *ac;
73
 
 
 
74
        struct ldb_context *ldb = ldb_module_get_ctx(module);
74
75
        ac = talloc_zero(req, struct extended_dn_context);
75
76
        if (ac == NULL) {
76
 
                ldb_oom(ldb_module_get_ctx(module));
 
77
                ldb_oom(ldb);
77
78
                return NULL;
78
79
        }
79
80
 
80
 
        ac->schema = dsdb_get_schema(ldb_module_get_ctx(module));
 
81
        ac->schema = dsdb_get_schema(ldb_module_get_ctx(module), ac);
81
82
        ac->module = module;
 
83
        ac->ldb = ldb;
82
84
        ac->req = req;
83
85
 
84
86
        return ac;
127
129
        if (ares->error == LDB_ERR_NO_SUCH_OBJECT) {
128
130
                /* Don't worry too much about dangling references */
129
131
 
130
 
                ldb_reset_err_string(ldb_module_get_ctx(os->ac->module));
 
132
                ldb_reset_err_string(os->ac->ldb);
131
133
                if (os->next) {
132
134
                        struct extended_dn_replace_list *next;
133
135
 
157
159
                 * search.  We can't check, as it could be an extended
158
160
                 * DN, so a module below will resolve it */
159
161
                struct ldb_dn *dn = ares->message->dn;
160
 
 
161
 
                /* Replace the DN with the extended version of the DN
162
 
                 * (ie, add SID and GUID) */
163
 
                *os->replace_dn = data_blob_string_const(
164
 
                        ldb_dn_get_extended_linearized(os->mem_ctx, 
165
 
                                                       dn, 1));
 
162
                
 
163
                /* Rebuild with the string or binary 'extra part' the
 
164
                 * DN may have had as a prefix */
 
165
                struct dsdb_dn *dsdb_dn = dsdb_dn_construct(ares, dn, 
 
166
                                                            os->dsdb_dn->extra_part,
 
167
                                                            os->dsdb_dn->oid);
 
168
                if (dsdb_dn) {
 
169
                        /* Replace the DN with the extended version of the DN
 
170
                         * (ie, add SID and GUID) */
 
171
                        *os->replace_dn = data_blob_string_const(
 
172
                                dsdb_dn_get_extended_linearized(os->mem_ctx, 
 
173
                                                                dsdb_dn, 1));
 
174
                        talloc_free(dsdb_dn);
 
175
                }
166
176
                if (os->replace_dn->data == NULL) {
167
177
                        return ldb_module_done(os->ac->req, NULL, NULL,
168
178
                                                LDB_ERR_OPERATIONS_ERROR);
209
219
 
210
220
static int extended_store_replace(struct extended_dn_context *ac,
211
221
                                  TALLOC_CTX *callback_mem_ctx,
212
 
                                  struct ldb_val *plain_dn)
 
222
                                  struct ldb_val *plain_dn,
 
223
                                  bool is_delete, 
 
224
                                  const char *oid)
213
225
{
214
226
        int ret;
215
227
        struct extended_dn_replace_list *os;
221
233
 
222
234
        os = talloc_zero(ac, struct extended_dn_replace_list);
223
235
        if (!os) {
224
 
                return LDB_ERR_OPERATIONS_ERROR;
 
236
                return ldb_oom(ac->ldb);
225
237
        }
226
238
 
227
239
        os->ac = ac;
228
240
        
229
241
        os->mem_ctx = callback_mem_ctx;
230
242
 
231
 
        os->dn = ldb_dn_from_ldb_val(os, ldb_module_get_ctx(ac->module), plain_dn);
232
 
        if (!os->dn || !ldb_dn_validate(os->dn)) {
 
243
        os->dsdb_dn = dsdb_dn_parse(os, ac->ldb, plain_dn, oid);
 
244
        if (!os->dsdb_dn || !ldb_dn_validate(os->dsdb_dn->dn)) {
233
245
                talloc_free(os);
234
 
                ldb_asprintf_errstring(ldb_module_get_ctx(ac->module), 
235
 
                                       "could not parse %.*s as a DN", (int)plain_dn->length, plain_dn->data);
 
246
                ldb_asprintf_errstring(ac->ldb,
 
247
                                       "could not parse %.*s as a %s DN", (int)plain_dn->length, plain_dn->data,
 
248
                                       oid);
236
249
                return LDB_ERR_INVALID_DN_SYNTAX;
237
250
        }
238
251
 
 
252
        if (is_delete && !ldb_dn_has_extended(os->dsdb_dn->dn)) {
 
253
                /* NO need to figure this DN out, this element is
 
254
                 * going to be deleted anyway, and becuase it's not
 
255
                 * extended, we have enough information to do the
 
256
                 * delete */
 
257
                talloc_free(os);
 
258
                return LDB_SUCCESS;
 
259
        }
 
260
        
 
261
                
239
262
        os->replace_dn = plain_dn;
240
263
 
241
264
        /* The search request here might happen to be for an
243
266
         * module in the stack will convert this into a normal DN for
244
267
         * processing */
245
268
        ret = ldb_build_search_req(&os->search_req,
246
 
                                   ldb_module_get_ctx(ac->module), os, os->dn, LDB_SCOPE_BASE, NULL, 
 
269
                                   ac->ldb, os, os->dsdb_dn->dn, LDB_SCOPE_BASE, NULL, 
247
270
                                   attrs, NULL, os, extended_replace_dn,
248
271
                                   ac->req);
249
 
 
 
272
        LDB_REQ_SET_LOCATION(os->search_req);
250
273
        if (ret != LDB_SUCCESS) {
251
274
                talloc_free(os);
252
275
                return ret;
253
276
        }
254
277
 
255
 
        ret = ldb_request_add_control(os->search_req,
256
 
                                      DSDB_CONTROL_DN_STORAGE_FORMAT_OID,
257
 
                                      true, NULL);
 
278
        ret = dsdb_request_add_controls(os->search_req,
 
279
                                        DSDB_SEARCH_SHOW_RECYCLED|DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT);
258
280
        if (ret != LDB_SUCCESS) {
259
281
                talloc_free(os);
260
282
                return ret;
276
298
{
277
299
        struct extended_dn_context *ac;
278
300
        int ret;
279
 
        int i, j;
 
301
        unsigned int i, j;
280
302
 
281
303
        if (ldb_dn_is_special(req->op.add.message->dn)) {
282
304
                /* do not manipulate our control entries */
285
307
 
286
308
        ac = extended_dn_context_init(module, req);
287
309
        if (!ac) {
288
 
                return LDB_ERR_OPERATIONS_ERROR;
 
310
                return ldb_operr(ldb_module_get_ctx(module));
289
311
        }
290
312
 
291
313
        if (!ac->schema) {
302
324
                        continue;
303
325
                }
304
326
 
305
 
                /* We only setup an extended DN GUID on these particular DN objects */
306
 
                if (strcmp(schema_attr->attributeSyntax_oid, "2.5.5.1") != 0) {
 
327
                /* We only setup an extended DN GUID on DN elements */
 
328
                if (dsdb_dn_oid_to_format(schema_attr->syntax->ldap_oid) == DSDB_INVALID_DN) {
307
329
                        continue;
308
330
                }
309
331
 
311
333
                if (!ac->new_req) {
312
334
                        struct ldb_message *msg = ldb_msg_copy(ac, req->op.add.message);
313
335
                        if (!msg) {
314
 
                                ldb_oom(ldb_module_get_ctx(module));
315
 
                                return LDB_ERR_OPERATIONS_ERROR;
 
336
                                return ldb_oom(ldb_module_get_ctx(module));
316
337
                        }
317
338
                   
318
 
                        ret = ldb_build_add_req(&ac->new_req, ldb_module_get_ctx(module), ac, msg, req->controls, ac, extended_final_callback, req);
 
339
                        ret = ldb_build_add_req(&ac->new_req, ac->ldb, ac, msg, req->controls, ac, extended_final_callback, req);
 
340
                        LDB_REQ_SET_LOCATION(ac->new_req);
319
341
                        if (ret != LDB_SUCCESS) {
320
342
                                return ret;
321
343
                        }
323
345
                /* Re-calculate el */
324
346
                el = &ac->new_req->op.add.message->elements[i];
325
347
                for (j = 0; j < el->num_values; j++) {
326
 
                        ret = extended_store_replace(ac, ac->new_req->op.add.message->elements, &el->values[j]);
 
348
                        ret = extended_store_replace(ac, ac->new_req, &el->values[j],
 
349
                                                     false, schema_attr->syntax->ldap_oid);
327
350
                        if (ret != LDB_SUCCESS) {
328
351
                                return ret;
329
352
                        }
330
353
                }
331
354
        }
332
355
 
333
 
        /* if DNs were set continue */
 
356
        /* if no DNs were set continue */
334
357
        if (ac->ops == NULL) {
335
358
                talloc_free(ac);
336
359
                return ldb_next_request(module, req);
348
371
        /* Determine the effect of the modification */
349
372
        /* Apply the modify to the linked entry */
350
373
 
351
 
        int i, j;
 
374
        unsigned int i, j;
352
375
        struct extended_dn_context *ac;
353
376
        int ret;
354
377
 
359
382
 
360
383
        ac = extended_dn_context_init(module, req);
361
384
        if (!ac) {
362
 
                return LDB_ERR_OPERATIONS_ERROR;
 
385
                return ldb_operr(ldb_module_get_ctx(module));
363
386
        }
364
387
 
365
388
        if (!ac->schema) {
 
389
                talloc_free(ac);
366
390
                /* without schema, this doesn't make any sense */
367
391
                return ldb_next_request(module, req);
368
392
        }
376
400
                }
377
401
 
378
402
                /* We only setup an extended DN GUID on these particular DN objects */
379
 
                if (strcmp(schema_attr->attributeSyntax_oid, "2.5.5.1") != 0) {
 
403
                if (dsdb_dn_oid_to_format(schema_attr->syntax->ldap_oid) == DSDB_INVALID_DN) {
380
404
                        continue;
381
405
                }
382
 
                
 
406
 
383
407
                /* Before we setup a procedure to modify the incoming message, we must copy it */
384
408
                if (!ac->new_req) {
385
409
                        struct ldb_message *msg = ldb_msg_copy(ac, req->op.mod.message);
386
410
                        if (!msg) {
387
 
                                ldb_oom(ldb_module_get_ctx(module));
388
 
                                return LDB_ERR_OPERATIONS_ERROR;
 
411
                                talloc_free(ac);
 
412
                                return ldb_oom(ac->ldb);
389
413
                        }
390
414
                   
391
 
                        ret = ldb_build_mod_req(&ac->new_req, ldb_module_get_ctx(module), ac, msg, req->controls, ac, extended_final_callback, req);
 
415
                        ret = ldb_build_mod_req(&ac->new_req, ac->ldb, ac, msg, req->controls, ac, extended_final_callback, req);
 
416
                        LDB_REQ_SET_LOCATION(ac->new_req);
392
417
                        if (ret != LDB_SUCCESS) {
 
418
                                talloc_free(ac);
393
419
                                return ret;
394
420
                        }
395
421
                }
397
423
                el = &ac->new_req->op.mod.message->elements[i];
398
424
                /* For each value being added, we need to setup the lookups to fill in the extended DN */
399
425
                for (j = 0; j < el->num_values; j++) {
400
 
                        struct ldb_dn *dn = ldb_dn_from_ldb_val(ac, ldb_module_get_ctx(module), &el->values[j]);
401
 
                        if (!dn || !ldb_dn_validate(dn)) {
402
 
                                ldb_asprintf_errstring(ldb_module_get_ctx(module), 
403
 
                                                       "could not parse attribute %s as a DN", el->name);
404
 
                                return LDB_ERR_INVALID_DN_SYNTAX;
405
 
                        }
406
 
                        if (((el->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_DELETE) && !ldb_dn_has_extended(dn)) {
407
 
                                /* NO need to figure this DN out, it's going to be deleted anyway */
408
 
                                continue;
409
 
                        }
410
 
                        ret = extended_store_replace(ac, req->op.mod.message->elements, &el->values[j]);
 
426
                        /* If we are just going to delete this
 
427
                         * element, only do a lookup if
 
428
                         * extended_store_replace determines it's an
 
429
                         * input of an extended DN */
 
430
                        bool is_delete = (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE);
 
431
 
 
432
                        ret = extended_store_replace(ac, ac->new_req, &el->values[j],
 
433
                                                     is_delete, schema_attr->syntax->ldap_oid);
411
434
                        if (ret != LDB_SUCCESS) {
 
435
                                talloc_free(ac);
412
436
                                return ret;
413
437
                        }
414
438
                }
424
448
        return ldb_next_request(module, ac->ops->search_req);
425
449
}
426
450
 
427
 
_PUBLIC_ const struct ldb_module_ops ldb_extended_dn_store_module_ops = {
 
451
static const struct ldb_module_ops ldb_extended_dn_store_module_ops = {
428
452
        .name              = "extended_dn_store",
429
453
        .add               = extended_dn_add,
430
454
        .modify            = extended_dn_modify,
431
455
};
 
456
 
 
457
int ldb_extended_dn_store_module_init(const char *version)
 
458
{
 
459
        LDB_MODULE_CHECK_VERSION(version);
 
460
        return ldb_register_module(&ldb_extended_dn_store_module_ops);
 
461
}