Coverage Report

Created: 2026-04-01 06:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/lib/ldb-samba/ldif_handlers.c
Line
Count
Source
1
/*
2
   ldb database library - ldif handlers for Samba
3
4
   Copyright (C) Andrew Tridgell 2005
5
   Copyright (C) Andrew Bartlett 2006-2009
6
   Copyright (C) Matthias Dieter Wallnöfer 2009
7
     ** NOTE! The following LGPL license applies to the ldb
8
     ** library. This does NOT imply that all of Samba is released
9
     ** under the LGPL
10
11
   This library is free software; you can redistribute it and/or
12
   modify it under the terms of the GNU Lesser General Public
13
   License as published by the Free Software Foundation; either
14
   version 3 of the License, or (at your option) any later version.
15
16
   This library 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 GNU
19
   Lesser General Public License for more details.
20
21
   You should have received a copy of the GNU Lesser General Public
22
   License along with this library; if not, see <http://www.gnu.org/licenses/>.
23
*/
24
25
#include "includes.h"
26
#include <ldb.h>
27
#include <ldb_module.h>
28
#include "ldb_handlers.h"
29
#include "dsdb/samdb/samdb.h"
30
#include "dsdb/common/util.h"
31
#include "librpc/gen_ndr/ndr_security.h"
32
#include "librpc/gen_ndr/ndr_misc.h"
33
#include "librpc/gen_ndr/ndr_drsblobs.h"
34
#include "librpc/gen_ndr/ndr_dnsp.h"
35
#include "librpc/ndr/libndr.h"
36
#include "libcli/security/security.h"
37
#include "param/param.h"
38
#include "../lib/util/asn1.h"
39
#include "lib/util/smb_strtox.h"
40
41
#undef DBGC_CLASS
42
0
#define DBGC_CLASS DBGC_LDB
43
44
/*
45
  use ndr_print_* to convert a NDR formatted blob to a ldif formatted blob
46
47
  If mask_errors is true, then function succeeds but out data
48
  is set to "<Unable to decode binary data>" message
49
50
  \return 0 on success; -1 on error
51
*/
52
static int ldif_write_NDR(struct ldb_context *ldb, void *mem_ctx,
53
        const struct ldb_val *in, struct ldb_val *out,
54
        size_t struct_size,
55
        ndr_pull_flags_fn_t pull_fn,
56
        ndr_print_fn_t print_fn,
57
        bool mask_errors)
58
0
{
59
0
  uint8_t *p;
60
0
  enum ndr_err_code err;
61
0
  if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
62
0
    return ldb_handler_copy(ldb, mem_ctx, in, out);
63
0
  }
64
0
  p = talloc_size(mem_ctx, struct_size);
65
0
  err = ndr_pull_struct_blob(in, mem_ctx,
66
0
           p, pull_fn);
67
0
  if (err != NDR_ERR_SUCCESS) {
68
    /* fail in not in mask_error mode */
69
0
    if (!mask_errors) {
70
0
      return -1;
71
0
    }
72
0
    talloc_free(p);
73
0
    out->data = (uint8_t *)talloc_strdup(mem_ctx, "<Unable to decode binary data>");
74
0
    out->length = strlen((const char *)out->data);
75
0
    return 0;
76
0
  }
77
0
  out->data = (uint8_t *)ndr_print_struct_string(mem_ctx, print_fn, "NDR", p);
78
0
  talloc_free(p);
79
0
  if (out->data == NULL) {
80
0
    return ldb_handler_copy(ldb, mem_ctx, in, out);
81
0
  }
82
0
  out->length = strlen((char *)out->data);
83
0
  return 0;
84
0
}
85
86
/*
87
  convert a ldif formatted objectSid to a NDR formatted blob
88
*/
89
static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
90
             const struct ldb_val *in, struct ldb_val *out)
91
0
{
92
0
  bool ret;
93
0
  enum ndr_err_code ndr_err;
94
0
  struct dom_sid sid;
95
0
  if (in->length > DOM_SID_STR_BUFLEN) {
96
0
    return -1;
97
0
  }
98
0
  if (in->length < 5) { /* "S-1-x" */
99
0
    return -1;
100
0
  }
101
0
  if (in->data[0] != 'S' && in->data[0] != 's') {
102
0
    return -1;
103
0
  } else {
104
0
    char p[DOM_SID_STR_BUFLEN + 1];
105
0
    memcpy(p, in->data, in->length);
106
0
    p[in->length] = '\0';
107
108
0
    ret = dom_sid_parse(p, &sid);
109
0
    if (ret == false) {
110
0
      return -1;
111
0
    }
112
113
0
    *out = data_blob_talloc(mem_ctx, NULL,
114
0
          ndr_size_dom_sid(&sid, 0));
115
0
    if (out->data == NULL) {
116
0
      return -1;
117
0
    }
118
119
0
    ndr_err = ndr_push_struct_into_fixed_blob(out, &sid,
120
0
        (ndr_push_flags_fn_t)ndr_push_dom_sid);
121
0
    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
122
0
      TALLOC_FREE(out->data);
123
0
      return -1;
124
0
    }
125
0
  }
126
0
  return 0;
127
0
}
128
129
/*
130
  convert a NDR formatted blob to a ldif formatted objectSid
131
*/
132
int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
133
        const struct ldb_val *in, struct ldb_val *out)
134
0
{
135
0
  struct dom_sid sid;
136
0
  enum ndr_err_code ndr_err;
137
138
0
  ndr_err = ndr_pull_struct_blob_all_noalloc(in, &sid,
139
0
             (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
140
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
141
0
    return -1;
142
0
  }
143
0
  *out = data_blob_string_const(dom_sid_string(mem_ctx, &sid));
144
0
  if (out->data == NULL) {
145
0
    return -1;
146
0
  }
147
0
  return 0;
148
0
}
149
150
/*
151
  compare two objectSids
152
153
  If the SIDs seem to be strings, they are converted to binary form.
154
*/
155
static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
156
            const struct ldb_val *v1, const struct ldb_val *v2)
157
0
{
158
0
  struct ldb_val parsed_1 = {.data = NULL};
159
0
  struct ldb_val parsed_2 = {.data = NULL};
160
0
  int ret;
161
  /*
162
   * If the ldb_vals look like SID strings (i.e. start with "S-"
163
   * or "s-"), we treat them as strings.
164
   *
165
   * It is not really possible for a blob to be both a SID string and a
166
   * SID struct -- the first two bytes of a struct dom_sid (including in
167
   * NDR form) are the version (1), and the number of sub-auths (<= 15),
168
   * neither of which are close to 'S' or '-'.
169
   */
170
0
  ret = ldif_read_objectSid(ldb, mem_ctx, v1, &parsed_1);
171
0
  if (ret == 0) {
172
0
    v1 = &parsed_1;
173
0
  }
174
0
  ret = ldif_read_objectSid(ldb, mem_ctx, v2, &parsed_2);
175
0
  if (ret == 0) {
176
0
    v2 = &parsed_2;
177
0
  }
178
179
0
  ret = ldb_comparison_binary(ldb, mem_ctx, v1, v2);
180
181
0
  TALLOC_FREE(parsed_1.data);
182
0
  TALLOC_FREE(parsed_2.data);
183
0
  return ret;
184
0
}
185
186
/*
187
  canonicalise a objectSid
188
*/
189
static int ldif_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
190
              const struct ldb_val *in, struct ldb_val *out)
191
0
{
192
  /* First try as a string SID */
193
0
  if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
194
0
    return 0;
195
0
  }
196
  /* not a string after all */
197
0
  return ldb_handler_copy(ldb, mem_ctx, in, out);
198
0
}
199
200
static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx,
201
            const struct ldb_val *in, struct ldb_val *out)
202
0
{
203
0
  struct dom_sid sid;
204
0
  enum ndr_err_code ndr_err;
205
206
0
  if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
207
0
    return 0;
208
0
  }
209
210
  /* Perhaps not a string after all */
211
0
  *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
212
213
0
  if (!out->data) {
214
0
    return -1;
215
0
  }
216
217
0
  (*out).length = strhex_to_str((char *)out->data, out->length,
218
0
             (const char *)in->data, in->length);
219
220
  /* Check it looks like a SID */
221
0
  ndr_err = ndr_pull_struct_blob_all_noalloc(out, &sid,
222
0
             (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
223
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
224
0
    TALLOC_FREE(out->data);
225
0
    return -1;
226
0
  }
227
0
  return 0;
228
0
}
229
230
/*
231
  convert a ldif formatted objectGUID to a NDR formatted blob
232
*/
233
static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
234
              const struct ldb_val *in, struct ldb_val *out)
235
0
{
236
0
  struct GUID guid;
237
0
  NTSTATUS status;
238
239
0
  status = GUID_from_data_blob(in, &guid);
240
0
  if (!NT_STATUS_IS_OK(status)) {
241
0
    return -1;
242
0
  }
243
244
0
  status = GUID_to_ndr_blob(&guid, mem_ctx, out);
245
0
  if (!NT_STATUS_IS_OK(status)) {
246
0
    return -1;
247
0
  }
248
0
  return 0;
249
0
}
250
251
/*
252
  convert a NDR formatted blob to a ldif formatted objectGUID
253
*/
254
static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
255
         const struct ldb_val *in, struct ldb_val *out)
256
0
{
257
0
  struct GUID guid;
258
0
  NTSTATUS status;
259
260
0
  status = GUID_from_ndr_blob(in, &guid);
261
0
  if (!NT_STATUS_IS_OK(status)) {
262
0
    return -1;
263
0
  }
264
0
  out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
265
0
  if (out->data == NULL) {
266
0
    return -1;
267
0
  }
268
0
  out->length = strlen((const char *)out->data);
269
0
  return 0;
270
0
}
271
272
static bool ldif_comparision_objectGUID_isString(const struct ldb_val *v)
273
0
{
274
0
  if (v->length != 36 && v->length != 38) return false;
275
276
  /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
277
0
  return true;
278
0
}
279
280
static int extended_dn_read_GUID(struct ldb_context *ldb, void *mem_ctx,
281
            const struct ldb_val *in, struct ldb_val *out)
282
0
{
283
284
0
  if (in->length == 36 && ldif_read_objectGUID(ldb, mem_ctx, in, out) == 0) {
285
0
    return 0;
286
0
  }
287
288
  /* Try as 'hex' form */
289
0
  if (in->length != 32) {
290
0
    return -1;
291
0
  }
292
293
0
  *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
294
295
0
  if (!out->data) {
296
0
    return -1;
297
0
  }
298
299
0
  (*out).length = strhex_to_str((char *)out->data, out->length,
300
0
              (const char *)in->data, in->length);
301
302
  /* Check it looks like a GUID */
303
0
  if ((*out).length != 16) {
304
0
    data_blob_free(out);
305
0
    return -1;
306
0
  }
307
308
0
  return 0;
309
0
}
310
311
/*
312
  compare two objectGUIDs
313
*/
314
static int ldif_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
315
             const struct ldb_val *v1, const struct ldb_val *v2)
316
0
{
317
0
  if (ldif_comparision_objectGUID_isString(v1) && ldif_comparision_objectGUID_isString(v2)) {
318
0
    return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
319
0
  } else if (ldif_comparision_objectGUID_isString(v1)
320
0
       && !ldif_comparision_objectGUID_isString(v2)) {
321
0
    struct ldb_val v;
322
0
    int ret;
323
0
    if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
324
      /* Perhaps it wasn't a valid string after all */
325
0
      return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
326
0
    }
327
0
    ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
328
0
    talloc_free(v.data);
329
0
    return ret;
330
0
  } else if (!ldif_comparision_objectGUID_isString(v1)
331
0
       && ldif_comparision_objectGUID_isString(v2)) {
332
0
    struct ldb_val v;
333
0
    int ret;
334
0
    if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
335
      /* Perhaps it wasn't a valid string after all */
336
0
      return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
337
0
    }
338
0
    ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
339
0
    talloc_free(v.data);
340
0
    return ret;
341
0
  }
342
0
  return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
343
0
}
344
345
/*
346
  canonicalise a objectGUID
347
*/
348
static int ldif_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
349
               const struct ldb_val *in, struct ldb_val *out)
350
0
{
351
0
  if (ldif_comparision_objectGUID_isString(in)) {
352
0
    if (ldif_read_objectGUID(ldb, mem_ctx, in, out) != 0) {
353
      /* Perhaps it wasn't a valid string after all */
354
0
      return ldb_handler_copy(ldb, mem_ctx, in, out);
355
0
    }
356
0
    return 0;
357
0
  }
358
0
  return ldb_handler_copy(ldb, mem_ctx, in, out);
359
0
}
360
361
362
/*
363
  convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
364
*/
365
static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
366
            const struct ldb_val *in, struct ldb_val *out)
367
0
{
368
0
  struct security_descriptor *sd;
369
0
  enum ndr_err_code ndr_err;
370
371
0
  if (in->length >= 2 && isupper(in->data[0]) && in->data[1] == ':') {
372
    /*
373
     * If it starts with an upper case character followed by ':',
374
     * we know it's not NDR, but most likely SDDL...
375
     */
376
0
    const struct dom_sid *sid = samdb_domain_sid(ldb);
377
378
0
    sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
379
0
    if (sd == NULL) {
380
0
      return -1;
381
0
    }
382
383
0
    goto decoded;
384
0
  }
385
386
0
  sd = talloc(mem_ctx, struct security_descriptor);
387
0
  if (sd == NULL) {
388
0
    return -1;
389
0
  }
390
391
0
  ndr_err = ndr_pull_struct_blob(in, sd, sd,
392
0
               (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
393
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
394
0
    talloc_free(sd);
395
0
    return -1;
396
0
  }
397
398
0
decoded:
399
0
  ndr_err = ndr_push_struct_blob(out, mem_ctx, sd,
400
0
               (ndr_push_flags_fn_t)ndr_push_security_descriptor);
401
0
  talloc_free(sd);
402
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
403
0
    return -1;
404
0
  }
405
406
0
  return 0;
407
0
}
408
409
/*
410
  convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
411
*/
412
static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
413
             const struct ldb_val *in, struct ldb_val *out)
414
0
{
415
0
  struct security_descriptor *sd;
416
0
  enum ndr_err_code ndr_err;
417
418
0
  if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
419
0
    return ldif_write_NDR(ldb, mem_ctx, in, out,
420
0
              sizeof(struct security_descriptor),
421
0
              (ndr_pull_flags_fn_t)ndr_pull_security_descriptor,
422
0
              (ndr_print_fn_t)ndr_print_security_descriptor,
423
0
              true);
424
425
0
  }
426
427
0
  sd = talloc(mem_ctx, struct security_descriptor);
428
0
  if (sd == NULL) {
429
0
    return -1;
430
0
  }
431
  /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
432
0
  ndr_err = ndr_pull_struct_blob(in, sd, sd,
433
0
             (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
434
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
435
0
    talloc_free(sd);
436
0
    return -1;
437
0
  }
438
0
  out->data = (uint8_t *)sddl_encode(mem_ctx, sd, samdb_domain_sid_cache_only(ldb));
439
0
  talloc_free(sd);
440
0
  if (out->data == NULL) {
441
0
    return -1;
442
0
  }
443
0
  out->length = strlen((const char *)out->data);
444
0
  return 0;
445
0
}
446
447
/*
448
  convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
449
*/
450
static int ldif_write_sddlSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
451
             const struct ldb_val *in, struct ldb_val *out)
452
0
{
453
0
  if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
454
0
    struct security_descriptor *sd;
455
0
    const struct dom_sid *sid = samdb_domain_sid(ldb);
456
457
0
    sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
458
0
    out->data = (uint8_t *)ndr_print_struct_string(mem_ctx,
459
0
          (ndr_print_fn_t)ndr_print_security_descriptor,
460
0
          "SDDL", sd);
461
0
    out->length = strlen((const char *)out->data);
462
0
    talloc_free(sd);
463
0
    return 0;
464
0
  }
465
466
0
  return ldb_handler_copy(ldb, mem_ctx, in, out);
467
0
}
468
469
/*
470
   canonicalise an objectCategory.  We use the long form as the canonical form:
471
   'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
472
473
   Also any short name of an objectClass that points to a different
474
   class (such as user) has the canonical form of the class it's
475
   defaultObjectCategory points to (eg
476
   cn=Person,cn=Schema,cn=Configuration,<basedn>)
477
*/
478
479
static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
480
              const struct ldb_val *in, struct ldb_val *out)
481
0
{
482
0
  struct ldb_dn *dn1 = NULL;
483
0
  const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
484
0
  const struct dsdb_class *sclass;
485
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
486
0
  if (!tmp_ctx) {
487
0
    return LDB_ERR_OPERATIONS_ERROR;
488
0
  }
489
490
0
  if (!schema) {
491
0
    talloc_free(tmp_ctx);
492
0
    *out = data_blob_talloc(mem_ctx, in->data, in->length);
493
0
    if (in->data && !out->data) {
494
0
      return LDB_ERR_OPERATIONS_ERROR;
495
0
    }
496
0
    return LDB_SUCCESS;
497
0
  }
498
0
  dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, in);
499
0
  if ( ! ldb_dn_validate(dn1)) {
500
0
    const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
501
0
    sclass = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
502
0
    if (sclass) {
503
0
      struct ldb_dn *dn = ldb_dn_new(tmp_ctx, ldb,
504
0
                   sclass->defaultObjectCategory);
505
0
      if (dn == NULL) {
506
0
        talloc_free(tmp_ctx);
507
0
        return LDB_ERR_OPERATIONS_ERROR;
508
0
      }
509
510
0
      *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn));
511
0
      talloc_free(tmp_ctx);
512
513
0
      if (!out->data) {
514
0
        return LDB_ERR_OPERATIONS_ERROR;
515
0
      }
516
0
      return LDB_SUCCESS;
517
0
    } else {
518
0
      *out = data_blob_talloc(mem_ctx, in->data, in->length);
519
0
      talloc_free(tmp_ctx);
520
521
0
      if (in->data && !out->data) {
522
0
        return LDB_ERR_OPERATIONS_ERROR;
523
0
      }
524
0
      return LDB_SUCCESS;
525
0
    }
526
0
  }
527
0
  *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn1));
528
0
  talloc_free(tmp_ctx);
529
530
0
  if (!out->data) {
531
0
    return LDB_ERR_OPERATIONS_ERROR;
532
0
  }
533
0
  return LDB_SUCCESS;
534
0
}
535
536
static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
537
            const struct ldb_val *v1,
538
            const struct ldb_val *v2)
539
0
{
540
0
  return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_objectCategory,
541
0
          v1, v2);
542
0
}
543
544
/*
545
  convert a NDR formatted blob to a ldif formatted schemaInfo
546
*/
547
static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx,
548
         const struct ldb_val *in, struct ldb_val *out)
549
0
{
550
0
  return ldif_write_NDR(ldb, mem_ctx, in, out,
551
0
            sizeof(struct schemaInfoBlob),
552
0
            (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob,
553
0
            (ndr_print_fn_t)ndr_print_schemaInfoBlob,
554
0
            true);
555
0
}
556
557
/*
558
  convert a ldif formatted prefixMap to a NDR formatted blob
559
*/
560
static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
561
             const struct ldb_val *in, struct ldb_val *out)
562
0
{
563
0
  struct prefixMapBlob *blob;
564
0
  enum ndr_err_code ndr_err;
565
0
  char *string, *line, *p, *oid;
566
0
  DATA_BLOB oid_blob;
567
568
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
569
570
0
  if (tmp_ctx == NULL) {
571
0
    return -1;
572
0
  }
573
574
0
  blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
575
0
  if (blob == NULL) {
576
0
    talloc_free(tmp_ctx);
577
0
    return -1;
578
0
  }
579
580
  /* use the switch value to detect if this is in the binary
581
   * format
582
   */
583
0
  if (in->length >= 4 && IVAL(in->data, 0) == PREFIX_MAP_VERSION_DSDB) {
584
0
    ndr_err = ndr_pull_struct_blob(in, tmp_ctx, blob,
585
0
                 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
586
0
    if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
587
0
      ndr_err = ndr_push_struct_blob(out, mem_ctx,
588
0
                   blob,
589
0
                   (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
590
0
      talloc_free(tmp_ctx);
591
0
      if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
592
0
        return -1;
593
0
      }
594
0
      return 0;
595
0
    }
596
0
  }
597
598
  /* If this does not parse, then it is probably the text version, and we should try it that way */
599
0
  blob->version = PREFIX_MAP_VERSION_DSDB;
600
601
0
  string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
602
0
  if (string == NULL) {
603
0
    talloc_free(blob);
604
0
    return -1;
605
0
  }
606
607
0
  line = string;
608
0
  while (line && line[0]) {
609
0
    int error = 0;
610
611
0
    p=strchr(line, ';');
612
0
    if (p) {
613
0
      p[0] = '\0';
614
0
    } else {
615
0
      p=strchr(line, '\n');
616
0
      if (p) {
617
0
        p[0] = '\0';
618
0
      }
619
0
    }
620
    /* allow a trailing separator */
621
0
    if (line == p) {
622
0
      break;
623
0
    }
624
625
0
    blob->ctr.dsdb.mappings = talloc_realloc(blob,
626
0
               blob->ctr.dsdb.mappings,
627
0
               struct drsuapi_DsReplicaOIDMapping,
628
0
               blob->ctr.dsdb.num_mappings+1);
629
0
    if (!blob->ctr.dsdb.mappings) {
630
0
      talloc_free(tmp_ctx);
631
0
      return -1;
632
0
    }
633
634
0
    blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix =
635
0
      smb_strtoul(line, &oid, 10, &error, SMB_STR_STANDARD);
636
637
0
    if (oid[0] != ':' || error != 0) {
638
0
      talloc_free(tmp_ctx);
639
0
      return -1;
640
0
    }
641
642
    /* we know there must be at least ":" */
643
0
    oid++;
644
645
0
    if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) {
646
0
      talloc_free(tmp_ctx);
647
0
      return -1;
648
0
    }
649
0
    blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.length = oid_blob.length;
650
0
    blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.binary_oid = oid_blob.data;
651
652
0
    blob->ctr.dsdb.num_mappings++;
653
654
    /* Now look past the terminator we added above */
655
0
    if (p) {
656
0
      line = p + 1;
657
0
    } else {
658
0
      line = NULL;
659
0
    }
660
0
  }
661
662
0
  ndr_err = ndr_push_struct_blob(out, mem_ctx,
663
0
               blob,
664
0
               (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
665
0
  talloc_free(tmp_ctx);
666
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
667
0
    return -1;
668
0
  }
669
0
  return 0;
670
0
}
671
672
/*
673
  convert a NDR formatted blob to a ldif formatted prefixMap
674
*/
675
static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
676
        const struct ldb_val *in, struct ldb_val *out)
677
0
{
678
0
  struct prefixMapBlob *blob;
679
0
  enum ndr_err_code ndr_err;
680
0
  char *string;
681
0
  uint32_t i;
682
683
0
  if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
684
0
    int err;
685
    /* try to decode the blob as S4 prefixMap */
686
0
    err = ldif_write_NDR(ldb, mem_ctx, in, out,
687
0
                         sizeof(struct prefixMapBlob),
688
0
                         (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
689
0
                         (ndr_print_fn_t)ndr_print_prefixMapBlob,
690
0
                         false);
691
0
    if (0 == err) {
692
0
      return err;
693
0
    }
694
    /* try parsing it as Windows PrefixMap value */
695
0
    return ldif_write_NDR(ldb, mem_ctx, in, out,
696
0
                          sizeof(struct drsuapi_MSPrefixMap_Ctr),
697
0
                          (ndr_pull_flags_fn_t)ndr_pull_drsuapi_MSPrefixMap_Ctr,
698
0
                          (ndr_print_fn_t)ndr_print_drsuapi_MSPrefixMap_Ctr,
699
0
                          true);
700
0
  }
701
702
0
  blob = talloc(mem_ctx, struct prefixMapBlob);
703
0
  if (blob == NULL) {
704
0
    return -1;
705
0
  }
706
0
  ndr_err = ndr_pull_struct_blob_all(in, blob,
707
0
             blob,
708
0
             (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
709
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
710
0
    goto failed;
711
0
  }
712
0
  if (blob->version != PREFIX_MAP_VERSION_DSDB) {
713
0
    goto failed;
714
0
  }
715
0
  string = talloc_strdup(mem_ctx, "");
716
0
  if (string == NULL) {
717
0
    goto failed;
718
0
  }
719
720
0
  for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
721
0
    DATA_BLOB oid_blob;
722
0
    char *partial_oid = NULL;
723
724
0
    if (i > 0) {
725
0
      talloc_asprintf_addbuf(&string, ";");
726
0
    }
727
728
0
    oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid,
729
0
             blob->ctr.dsdb.mappings[i].oid.length);
730
0
    if (!ber_read_partial_OID_String(blob, oid_blob, &partial_oid)) {
731
0
      DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X\n",
732
0
          blob->ctr.dsdb.mappings[i].id_prefix));
733
0
      goto failed;
734
0
    }
735
0
    talloc_asprintf_addbuf(&string, "%u:%s",
736
0
               blob->ctr.dsdb.mappings[i].id_prefix,
737
0
               partial_oid);
738
0
    talloc_free(discard_const(partial_oid));
739
0
  }
740
741
0
  talloc_free(blob);
742
0
  *out = data_blob_string_const(string);
743
0
  return 0;
744
745
0
failed:
746
0
  talloc_free(blob);
747
0
  return -1;
748
0
}
749
750
static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
751
0
{
752
0
  if (v->length < 4) {
753
0
    return true;
754
0
  }
755
756
0
  if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
757
0
    return false;
758
0
  }
759
760
0
  return true;
761
0
}
762
763
/*
764
  canonicalise a prefixMap
765
*/
766
static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
767
               const struct ldb_val *in, struct ldb_val *out)
768
0
{
769
0
  if (ldif_comparision_prefixMap_isString(in)) {
770
0
    return ldif_read_prefixMap(ldb, mem_ctx, in, out);
771
0
  }
772
0
  return ldb_handler_copy(ldb, mem_ctx, in, out);
773
0
}
774
775
static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
776
             const struct ldb_val *v1,
777
             const struct ldb_val *v2)
778
0
{
779
0
  return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_prefixMap,
780
0
          v1, v2);
781
0
}
782
783
/* length limited conversion of a ldb_val to a int32_t */
784
static int val_to_int32(const struct ldb_val *in, int32_t *v)
785
0
{
786
0
  char *end;
787
0
  char buf[64];
788
789
  /* make sure we don't read past the end of the data */
790
0
  if (in->length > sizeof(buf)-1) {
791
0
    return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
792
0
  }
793
0
  strncpy(buf, (char *)in->data, in->length);
794
0
  buf[in->length] = 0;
795
796
  /* We've to use "strtoll" here to have the intended overflows.
797
   * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
798
0
  *v = (int32_t) strtoll(buf, &end, 0);
799
0
  if (*end != 0) {
800
0
    return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
801
0
  }
802
0
  return LDB_SUCCESS;
803
0
}
804
805
/* length limited conversion of a ldb_val to a int64_t */
806
static int val_to_int64(const struct ldb_val *in, int64_t *v)
807
0
{
808
0
  char *end;
809
0
  char buf[64];
810
811
  /* make sure we don't read past the end of the data */
812
0
  if (in->length > sizeof(buf)-1) {
813
0
    return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
814
0
  }
815
0
  strncpy(buf, (char *)in->data, in->length);
816
0
  buf[in->length] = 0;
817
818
0
  *v = (int64_t) strtoll(buf, &end, 0);
819
0
  if (*end != 0) {
820
0
    return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
821
0
  }
822
0
  return LDB_SUCCESS;
823
0
}
824
825
/* Canonicalisation of two 32-bit integers */
826
static int ldif_canonicalise_int32(struct ldb_context *ldb, void *mem_ctx,
827
      const struct ldb_val *in, struct ldb_val *out)
828
0
{
829
0
  int32_t i;
830
0
  int ret;
831
832
0
  ret = val_to_int32(in, &i);
833
0
  if (ret != LDB_SUCCESS) {
834
0
    return ret;
835
0
  }
836
0
  out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%d", i);
837
0
  if (out->data == NULL) {
838
0
    ldb_oom(ldb);
839
0
    return LDB_ERR_OPERATIONS_ERROR;
840
0
  }
841
0
  out->length = strlen((char *)out->data);
842
0
  return 0;
843
0
}
844
845
/*
846
 * Lexicographically sorted representation for a 32-bit integer
847
 *
848
 * [ INT32_MIN ... -3, -2, -1 | 0 | +1, +2, +3 ... INT32_MAX ]
849
 *             n                o              p
850
 *
851
 * Refer to the comment in lib/ldb/common/attrib_handlers.c for the
852
 * corresponding documentation for 64-bit integers.
853
 *
854
 * The same rules apply but use INT32_MIN and INT32_MAX.
855
 *
856
 * String representation padding is done to 10 characters.
857
 *
858
 * INT32_MAX = 2^31 - 1 = 2147483647 (10 characters long)
859
 *
860
 */
861
static int ldif_index_format_int32(struct ldb_context *ldb,
862
            void *mem_ctx,
863
            const struct ldb_val *in,
864
            struct ldb_val *out)
865
0
{
866
0
  int32_t i;
867
0
  int ret;
868
0
  char prefix;
869
0
  size_t len;
870
871
0
  ret = val_to_int32(in, &i);
872
0
  if (ret != LDB_SUCCESS) {
873
0
    return ret;
874
0
  }
875
876
0
  if (i < 0) {
877
    /*
878
     * i is negative, so this is subtraction rather than
879
     * wrap-around.
880
     */
881
0
    prefix = 'n';
882
0
    i = INT32_MAX + i + 1;
883
0
  } else if (i > 0) {
884
0
    prefix = 'p';
885
0
  } else {
886
0
    prefix = 'o';
887
0
  }
888
889
0
  out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%c%010ld", prefix, (long)i);
890
0
  if (out->data == NULL) {
891
0
    ldb_oom(ldb);
892
0
    return LDB_ERR_OPERATIONS_ERROR;
893
0
  }
894
895
0
  len = talloc_array_length(out->data) - 1;
896
0
  if (len != 11) {
897
0
    ldb_debug(ldb, LDB_DEBUG_ERROR,
898
0
        __location__ ": expected index format str %s to"
899
0
        " have length 11 but got %zu",
900
0
        (char*)out->data, len);
901
0
    return LDB_ERR_OPERATIONS_ERROR;
902
0
  }
903
904
0
  out->length = 11;
905
0
  return 0;
906
0
}
907
908
/* Comparison of two 32-bit integers */
909
static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
910
         const struct ldb_val *v1, const struct ldb_val *v2)
911
0
{
912
0
  int32_t i1=0, i2=0;
913
0
  val_to_int32(v1, &i1);
914
0
  val_to_int32(v2, &i2);
915
0
  if (i1 == i2) return 0;
916
0
  return i1 > i2? 1 : -1;
917
0
}
918
919
/* Canonicalisation of two 64-bit integers */
920
static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx,
921
           const struct ldb_val *in, struct ldb_val *out)
922
0
{
923
0
  int64_t i;
924
0
  int ret;
925
926
0
  ret = val_to_int64(in, &i);
927
0
  if (ret != LDB_SUCCESS) {
928
0
    return ret;
929
0
  }
930
0
  out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
931
0
  if (out->data == NULL) {
932
0
    ldb_oom(ldb);
933
0
    return LDB_ERR_OPERATIONS_ERROR;
934
0
  }
935
0
  out->length = strlen((char *)out->data);
936
0
  return 0;
937
0
}
938
939
/* Comparison of two 64-bit integers */
940
static int ldif_comparison_int64(struct ldb_context *ldb, void *mem_ctx,
941
         const struct ldb_val *v1, const struct ldb_val *v2)
942
0
{
943
0
  int64_t i1=0, i2=0;
944
0
  val_to_int64(v1, &i1);
945
0
  val_to_int64(v2, &i2);
946
0
  if (i1 == i2) return 0;
947
0
  return i1 > i2? 1 : -1;
948
0
}
949
950
/*
951
  convert a NDR formatted blob to a ldif formatted repsFromTo
952
*/
953
static int ldif_write_repsFromTo(struct ldb_context *ldb, void *mem_ctx,
954
         const struct ldb_val *in, struct ldb_val *out)
955
0
{
956
0
  return ldif_write_NDR(ldb, mem_ctx, in, out,
957
0
            sizeof(struct repsFromToBlob),
958
0
            (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob,
959
0
            (ndr_print_fn_t)ndr_print_repsFromToBlob,
960
0
            true);
961
0
}
962
963
/*
964
  convert a NDR formatted blob to a ldif formatted replPropertyMetaData
965
*/
966
static int ldif_write_replPropertyMetaData(struct ldb_context *ldb, void *mem_ctx,
967
             const struct ldb_val *in, struct ldb_val *out)
968
0
{
969
0
  return ldif_write_NDR(ldb, mem_ctx, in, out,
970
0
            sizeof(struct replPropertyMetaDataBlob),
971
0
            (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob,
972
0
            (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
973
0
            true);
974
0
}
975
976
/*
977
  convert a NDR formatted blob to a ldif formatted replUpToDateVector
978
*/
979
static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
980
           const struct ldb_val *in, struct ldb_val *out)
981
0
{
982
0
  return ldif_write_NDR(ldb, mem_ctx, in, out,
983
0
            sizeof(struct replUpToDateVectorBlob),
984
0
            (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob,
985
0
            (ndr_print_fn_t)ndr_print_replUpToDateVectorBlob,
986
0
            true);
987
0
}
988
989
static int ldif_write_dn_binary_NDR(struct ldb_context *ldb, void *mem_ctx,
990
            const struct ldb_val *in, struct ldb_val *out,
991
            size_t struct_size,
992
            ndr_pull_flags_fn_t pull_fn,
993
            ndr_print_fn_t print_fn,
994
            bool mask_errors)
995
0
{
996
0
  uint8_t *p = NULL;
997
0
  enum ndr_err_code err;
998
0
  struct dsdb_dn *dsdb_dn = NULL;
999
0
  char *dn_str = NULL;
1000
0
  char *str = NULL;
1001
1002
0
  if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
1003
0
    return ldb_handler_copy(ldb, mem_ctx, in, out);
1004
0
  }
1005
1006
0
  dsdb_dn = dsdb_dn_parse(mem_ctx, ldb, in, DSDB_SYNTAX_BINARY_DN);
1007
0
  if (dsdb_dn == NULL) {
1008
0
    return ldb_handler_copy(ldb, mem_ctx, in, out);
1009
0
  }
1010
1011
0
  p = talloc_size(dsdb_dn, struct_size);
1012
0
  if (p == NULL) {
1013
0
    TALLOC_FREE(dsdb_dn);
1014
0
    return ldb_handler_copy(ldb, mem_ctx, in, out);
1015
0
  }
1016
1017
0
  err = ndr_pull_struct_blob(&dsdb_dn->extra_part, p, p, pull_fn);
1018
0
  if (err != NDR_ERR_SUCCESS) {
1019
    /* fail in not in mask_error mode */
1020
0
    if (!mask_errors) {
1021
0
      return -1;
1022
0
    }
1023
0
    TALLOC_FREE(dsdb_dn);
1024
0
    return ldb_handler_copy(ldb, mem_ctx, in, out);
1025
0
  }
1026
1027
0
  dn_str = ldb_dn_get_extended_linearized(dsdb_dn, dsdb_dn->dn, 1);
1028
0
  if (dn_str == NULL) {
1029
0
    TALLOC_FREE(dsdb_dn);
1030
0
    return ldb_handler_copy(ldb, mem_ctx, in, out);
1031
0
  }
1032
1033
0
  str = ndr_print_struct_string(mem_ctx, print_fn, dn_str, p);
1034
0
  TALLOC_FREE(dsdb_dn);
1035
0
  if (str == NULL) {
1036
0
    return ldb_handler_copy(ldb, mem_ctx, in, out);
1037
0
  }
1038
1039
0
  *out = data_blob_string_const(str);
1040
0
  return 0;
1041
0
}
1042
1043
static int ldif_write_msDS_RevealedUsers(struct ldb_context *ldb, void *mem_ctx,
1044
           const struct ldb_val *in, struct ldb_val *out)
1045
0
{
1046
0
  return ldif_write_dn_binary_NDR(ldb, mem_ctx, in, out,
1047
0
            sizeof(struct replPropertyMetaData1),
1048
0
            (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaData1,
1049
0
            (ndr_print_fn_t)ndr_print_replPropertyMetaData1,
1050
0
            true);
1051
0
}
1052
1053
/*
1054
  convert a NDR formatted blob to a ldif formatted dnsRecord
1055
*/
1056
static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
1057
        const struct ldb_val *in, struct ldb_val *out)
1058
0
{
1059
0
  return ldif_write_NDR(ldb, mem_ctx, in, out,
1060
0
            sizeof(struct dnsp_DnssrvRpcRecord),
1061
0
            (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord,
1062
0
            (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord,
1063
0
            true);
1064
0
}
1065
1066
/*
1067
  convert a NDR formatted blob to a ldif formatted dnsProperty
1068
*/
1069
static int ldif_write_dnsProperty(struct ldb_context *ldb, void *mem_ctx,
1070
        const struct ldb_val *in, struct ldb_val *out)
1071
0
{
1072
0
  return ldif_write_NDR(ldb, mem_ctx, in, out,
1073
0
            sizeof(struct dnsp_DnsProperty),
1074
0
            (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnsProperty,
1075
0
            (ndr_print_fn_t)ndr_print_dnsp_DnsProperty,
1076
0
            true);
1077
0
}
1078
1079
/*
1080
  convert a NDR formatted blob of a supplementalCredentials into text
1081
*/
1082
static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx,
1083
              const struct ldb_val *in, struct ldb_val *out)
1084
0
{
1085
0
  return ldif_write_NDR(ldb, mem_ctx, in, out,
1086
0
            sizeof(struct supplementalCredentialsBlob),
1087
0
            (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob,
1088
0
            (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob,
1089
0
            true);
1090
0
}
1091
1092
/*
1093
  convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
1094
*/
1095
static int ldif_write_trustAuthInOutBlob(struct ldb_context *ldb, void *mem_ctx,
1096
             const struct ldb_val *in, struct ldb_val *out)
1097
0
{
1098
0
  return ldif_write_NDR(ldb, mem_ctx, in, out,
1099
0
            sizeof(struct trustAuthInOutBlob),
1100
0
            (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob,
1101
0
            (ndr_print_fn_t)ndr_print_trustAuthInOutBlob,
1102
0
            true);
1103
0
}
1104
1105
/*
1106
  convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
1107
*/
1108
static int ldif_write_ForestTrustInfo(struct ldb_context *ldb, void *mem_ctx,
1109
              const struct ldb_val *in, struct ldb_val *out)
1110
0
{
1111
0
  return ldif_write_NDR(ldb, mem_ctx, in, out,
1112
0
            sizeof(struct ForestTrustInfo),
1113
0
            (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo,
1114
0
            (ndr_print_fn_t)ndr_print_ForestTrustInfo,
1115
0
            true);
1116
0
}
1117
/*
1118
  convert a NDR formatted blob of a partialAttributeSet into text
1119
*/
1120
static int ldif_write_partialAttributeSet(struct ldb_context *ldb, void *mem_ctx,
1121
            const struct ldb_val *in, struct ldb_val *out)
1122
0
{
1123
0
  return ldif_write_NDR(ldb, mem_ctx, in, out,
1124
0
            sizeof(struct partialAttributeSetBlob),
1125
0
            (ndr_pull_flags_fn_t)ndr_pull_partialAttributeSetBlob,
1126
0
            (ndr_print_fn_t)ndr_print_partialAttributeSetBlob,
1127
0
            true);
1128
0
}
1129
1130
1131
static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
1132
         const struct ldb_val *in, struct ldb_val *out)
1133
0
{
1134
0
  *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
1135
0
  if (!out->data) {
1136
0
    return -1;
1137
0
  }
1138
0
  return 0;
1139
0
}
1140
1141
/*
1142
  compare two dns
1143
*/
1144
static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
1145
          const struct ldb_val *v1, const struct ldb_val *v2)
1146
0
{
1147
0
  struct ldb_dn *dn1 = NULL, *dn2 = NULL;
1148
0
  int ret;
1149
1150
  /*
1151
   * In a sort context, Deleted DNs get shifted to the end.
1152
   * They never match in an equality
1153
   */
1154
0
  if (dsdb_dn_is_deleted_val(v1)) {
1155
0
    if (! dsdb_dn_is_deleted_val(v2)) {
1156
0
      return 1;
1157
0
    }
1158
    /*
1159
     * They are both deleted!
1160
     *
1161
     * The soundest thing to do at this point is carry on
1162
     * and compare the DNs normally. This matches the
1163
     * behaviour of samba_dn_extended_match() below.
1164
     */
1165
0
  } else if (dsdb_dn_is_deleted_val(v2)) {
1166
0
    return -1;
1167
0
  }
1168
1169
0
  dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
1170
0
  dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
1171
1172
0
  if ( ! ldb_dn_validate(dn1)) {
1173
0
    TALLOC_FREE(dn1);
1174
0
    if ( ! ldb_dn_validate(dn2)) {
1175
0
      TALLOC_FREE(dn2);
1176
0
      return 0;
1177
0
    }
1178
0
    TALLOC_FREE(dn2);
1179
0
    return 1;
1180
0
  }
1181
1182
0
  if ( ! ldb_dn_validate(dn2)) {
1183
0
    TALLOC_FREE(dn1);
1184
0
    TALLOC_FREE(dn2);
1185
0
    return -1;
1186
0
  }
1187
1188
0
  ret = ldb_dn_compare(dn1, dn2);
1189
1190
0
  talloc_free(dn1);
1191
0
  talloc_free(dn2);
1192
0
  return ret;
1193
0
}
1194
1195
static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
1196
            const struct ldb_val *in, struct ldb_val *out)
1197
0
{
1198
0
  struct ldb_dn *dn;
1199
0
  int ret = -1;
1200
1201
0
  out->length = 0;
1202
0
  out->data = NULL;
1203
1204
0
  dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
1205
0
  if ( ! ldb_dn_validate(dn)) {
1206
0
    return LDB_ERR_INVALID_DN_SYNTAX;
1207
0
  }
1208
1209
  /* By including the RMD_FLAGS of a deleted DN, we ensure it
1210
   * does not casually match a not deleted DN */
1211
0
  if (dsdb_dn_is_deleted_val(in)) {
1212
0
    out->data = (uint8_t *)talloc_asprintf(mem_ctx,
1213
0
                   "<RMD_FLAGS=%u>%s",
1214
0
                   dsdb_dn_val_rmd_flags(in),
1215
0
                   ldb_dn_get_casefold(dn));
1216
0
  } else {
1217
0
    out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
1218
0
  }
1219
1220
0
  if (out->data == NULL) {
1221
0
    goto done;
1222
0
  }
1223
0
  out->length = strlen((char *)out->data);
1224
1225
0
  ret = 0;
1226
1227
0
done:
1228
0
  talloc_free(dn);
1229
1230
0
  return ret;
1231
0
}
1232
1233
1234
/*
1235
  write a 64 bit 2-part range
1236
*/
1237
static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
1238
            const struct ldb_val *in, struct ldb_val *out)
1239
0
{
1240
0
  int64_t v;
1241
0
  int ret;
1242
0
  ret = val_to_int64(in, &v);
1243
0
  if (ret != LDB_SUCCESS) {
1244
0
    return ret;
1245
0
  }
1246
0
  out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
1247
0
                 (unsigned long)(v&0xFFFFFFFF),
1248
0
                 (unsigned long)(v>>32));
1249
0
  if (out->data == NULL) {
1250
0
    ldb_oom(ldb);
1251
0
    return LDB_ERR_OPERATIONS_ERROR;
1252
0
  }
1253
0
  out->length = strlen((char *)out->data);
1254
0
  return LDB_SUCCESS;
1255
0
}
1256
1257
/*
1258
  read a 64 bit 2-part range
1259
*/
1260
static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
1261
            const struct ldb_val *in, struct ldb_val *out)
1262
0
{
1263
0
  unsigned long high, low;
1264
0
  char buf[64];
1265
1266
0
  if (memchr(in->data, '-', in->length) == NULL) {
1267
0
    return ldb_handler_copy(ldb, mem_ctx, in, out);
1268
0
  }
1269
1270
0
  if (in->length > sizeof(buf)-1) {
1271
0
    return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1272
0
  }
1273
0
  strncpy(buf, (const char *)in->data, in->length);
1274
0
  buf[in->length] = 0;
1275
1276
0
  if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
1277
0
    return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1278
0
  }
1279
1280
0
  out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
1281
0
                 (unsigned long long)(((uint64_t)high)<<32) | (low));
1282
1283
0
  if (out->data == NULL) {
1284
0
    ldb_oom(ldb);
1285
0
    return LDB_ERR_OPERATIONS_ERROR;
1286
0
  }
1287
0
  out->length = strlen((char *)out->data);
1288
0
  return LDB_SUCCESS;
1289
0
}
1290
1291
/*
1292
  when this operator_fn is set for a syntax, the backend calls is in
1293
  preference to the comparison function. We are told the exact
1294
  comparison operation that is needed, and we can return errors
1295
 */
1296
static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1297
            const struct ldb_schema_attribute *a,
1298
            const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1299
0
{
1300
0
  switch (operation) {
1301
0
  case LDB_OP_AND:
1302
0
  case LDB_OP_OR:
1303
0
  case LDB_OP_NOT:
1304
0
  case LDB_OP_SUBSTRING:
1305
0
  case LDB_OP_APPROX:
1306
0
  case LDB_OP_EXTENDED:
1307
    /* handled in the backends */
1308
0
    return LDB_ERR_INAPPROPRIATE_MATCHING;
1309
1310
0
  case LDB_OP_GREATER:
1311
0
  case LDB_OP_LESS:
1312
0
  case LDB_OP_EQUALITY:
1313
0
  {
1314
0
    TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1315
0
    int ret;
1316
0
    if (tmp_ctx == NULL) {
1317
0
      return ldb_oom(ldb);
1318
0
    }
1319
0
    ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
1320
0
    talloc_free(tmp_ctx);
1321
0
    if (operation == LDB_OP_GREATER) {
1322
0
      *matched = (ret >= 0);
1323
0
    } else if (operation == LDB_OP_LESS) {
1324
0
      *matched = (ret <= 0);
1325
0
    } else {
1326
0
      *matched = (ret == 0);
1327
0
    }
1328
0
    return LDB_SUCCESS;
1329
0
  }
1330
1331
0
  case LDB_OP_PRESENT:
1332
0
    *matched = true;
1333
0
    return LDB_SUCCESS;
1334
0
  }
1335
1336
  /* we shouldn't get here */
1337
0
  return LDB_ERR_INAPPROPRIATE_MATCHING;
1338
0
}
1339
1340
/*
1341
  compare two binary objects.  This is correct for sorting as the sort order is:
1342
1343
  a
1344
  aa
1345
  b
1346
  bb
1347
1348
  rather than ldb_comparison_binary() which is:
1349
1350
  a
1351
  b
1352
  aa
1353
  bb
1354
1355
*/
1356
static int samba_ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
1357
               const struct ldb_val *v1, const struct ldb_val *v2)
1358
0
{
1359
0
  return data_blob_cmp(v1, v2);
1360
0
}
1361
1362
/*
1363
  when this operator_fn is set for a syntax, the backend calls is in
1364
  preference to the comparison function. We are told the exact
1365
  comparison operation that is needed, and we can return errors.
1366
1367
  This mode optimises for ldb_comparison_binary() if we need equality,
1368
  as this should be faster as it can do a length-check first.
1369
 */
1370
static int samba_syntax_binary_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1371
             const struct ldb_schema_attribute *a,
1372
             const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1373
0
{
1374
0
  if (operation == LDB_OP_EQUALITY) {
1375
0
    *matched = (ldb_comparison_binary(ldb, NULL, v1, v2) == 0);
1376
0
    return LDB_SUCCESS;
1377
0
  }
1378
0
  return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1379
0
}
1380
1381
/*
1382
  see if two DNs match, comparing first by GUID, then by SID, and
1383
  finally by string components
1384
 */
1385
static int samba_dn_extended_match(struct ldb_context *ldb,
1386
           const struct ldb_val *v1,
1387
           const struct ldb_val *v2,
1388
           bool *matched)
1389
0
{
1390
0
  TALLOC_CTX *tmp_ctx;
1391
0
  struct ldb_dn *dn1, *dn2;
1392
0
  const struct ldb_val *guid1, *guid2, *sid1, *sid2;
1393
0
  uint32_t rmd_flags1, rmd_flags2;
1394
1395
0
  tmp_ctx = talloc_new(ldb);
1396
1397
0
  dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v1);
1398
0
  dn2 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v2);
1399
0
  if (!dn1 || !dn2) {
1400
    /* couldn't parse as DN's */
1401
0
    talloc_free(tmp_ctx);
1402
0
    (*matched) = false;
1403
0
    return LDB_SUCCESS;
1404
0
  }
1405
1406
0
  rmd_flags1 = dsdb_dn_rmd_flags(dn1);
1407
0
  rmd_flags2 = dsdb_dn_rmd_flags(dn2);
1408
1409
0
  if ((rmd_flags1 & DSDB_RMD_FLAG_DELETED) !=
1410
0
      (rmd_flags2 & DSDB_RMD_FLAG_DELETED)) {
1411
    /* only match if they have the same deletion status */
1412
0
    talloc_free(tmp_ctx);
1413
0
    (*matched) = false;
1414
0
    return LDB_SUCCESS;
1415
0
  }
1416
1417
1418
0
  guid1 = ldb_dn_get_extended_component(dn1, "GUID");
1419
0
  guid2 = ldb_dn_get_extended_component(dn2, "GUID");
1420
0
  if (guid1 && guid2) {
1421
0
    (*matched) = (data_blob_cmp(guid1, guid2) == 0);
1422
0
    talloc_free(tmp_ctx);
1423
0
    return LDB_SUCCESS;
1424
0
  }
1425
1426
0
  sid1 = ldb_dn_get_extended_component(dn1, "SID");
1427
0
  sid2 = ldb_dn_get_extended_component(dn2, "SID");
1428
0
  if (sid1 && sid2) {
1429
0
    (*matched) = (data_blob_cmp(sid1, sid2) == 0);
1430
0
    talloc_free(tmp_ctx);
1431
0
    return LDB_SUCCESS;
1432
0
  }
1433
1434
0
  (*matched) = (ldb_dn_compare(dn1, dn2) == 0);
1435
1436
0
  talloc_free(tmp_ctx);
1437
0
  return LDB_SUCCESS;
1438
0
}
1439
1440
/*
1441
  special operation for DNs, to take account of the RMD_FLAGS deleted bit
1442
 */
1443
static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op operation,
1444
            const struct ldb_schema_attribute *a,
1445
            const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1446
0
{
1447
0
  if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
1448
    /* If the DN is deleted, then we can't search for it */
1449
1450
    /* should this be for equality too? */
1451
0
    *matched = false;
1452
0
    return LDB_SUCCESS;
1453
0
  }
1454
1455
0
  if (operation == LDB_OP_EQUALITY &&
1456
0
      samba_dn_extended_match(ldb, v1, v2, matched) == LDB_SUCCESS) {
1457
0
    return LDB_SUCCESS;
1458
0
  }
1459
1460
0
  return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1461
0
}
1462
1463
1464
static const struct ldb_schema_syntax samba_syntaxes[] = {
1465
  {
1466
    .name     = LDB_SYNTAX_SAMBA_SID,
1467
    .ldif_read_fn   = ldif_read_objectSid,
1468
    .ldif_write_fn    = ldif_write_objectSid,
1469
    .canonicalise_fn  = ldif_canonicalise_objectSid,
1470
    .comparison_fn    = ldif_comparison_objectSid,
1471
    .operator_fn      = samba_syntax_operator_fn
1472
  },{
1473
    .name     = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1474
    .ldif_read_fn   = ldif_read_ntSecurityDescriptor,
1475
    .ldif_write_fn    = ldif_write_ntSecurityDescriptor,
1476
    .canonicalise_fn  = ldb_handler_copy,
1477
    .comparison_fn    = samba_ldb_comparison_binary,
1478
    .operator_fn      = samba_syntax_binary_operator_fn
1479
  },{
1480
    .name     = LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR,
1481
    .ldif_read_fn   = ldb_handler_copy,
1482
    .ldif_write_fn    = ldif_write_sddlSecurityDescriptor,
1483
    .canonicalise_fn  = ldb_handler_fold,
1484
    .comparison_fn    = ldb_comparison_fold,
1485
    .operator_fn      = samba_syntax_operator_fn
1486
  },{
1487
    .name     = LDB_SYNTAX_SAMBA_GUID,
1488
    .ldif_read_fn   = ldif_read_objectGUID,
1489
    .ldif_write_fn    = ldif_write_objectGUID,
1490
    .canonicalise_fn  = ldif_canonicalise_objectGUID,
1491
    .comparison_fn    = ldif_comparison_objectGUID,
1492
    .operator_fn      = samba_syntax_operator_fn
1493
  },{
1494
    .name     = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
1495
    .ldif_read_fn   = ldb_handler_copy,
1496
    .ldif_write_fn    = ldb_handler_copy,
1497
    .canonicalise_fn  = ldif_canonicalise_objectCategory,
1498
    .comparison_fn    = ldif_comparison_objectCategory,
1499
    .operator_fn      = samba_syntax_operator_fn
1500
  },{
1501
    .name     = LDB_SYNTAX_SAMBA_SCHEMAINFO,
1502
    .ldif_read_fn   = ldb_handler_copy,
1503
    .ldif_write_fn    = ldif_write_schemaInfo,
1504
    .canonicalise_fn  = ldb_handler_copy,
1505
    .comparison_fn    = samba_ldb_comparison_binary,
1506
    .operator_fn      = samba_syntax_binary_operator_fn
1507
  },{
1508
    .name     = LDB_SYNTAX_SAMBA_PREFIX_MAP,
1509
    .ldif_read_fn   = ldif_read_prefixMap,
1510
    .ldif_write_fn    = ldif_write_prefixMap,
1511
    .canonicalise_fn  = ldif_canonicalise_prefixMap,
1512
    .comparison_fn    = ldif_comparison_prefixMap,
1513
    .operator_fn      = samba_syntax_operator_fn
1514
  },{
1515
    .name     = LDB_SYNTAX_SAMBA_INT32,
1516
    .ldif_read_fn   = ldb_handler_copy,
1517
    .ldif_write_fn    = ldb_handler_copy,
1518
    .canonicalise_fn  = ldif_canonicalise_int32,
1519
    .index_format_fn  = ldif_index_format_int32,
1520
    .comparison_fn    = ldif_comparison_int32,
1521
    .operator_fn      = samba_syntax_operator_fn
1522
  },{
1523
    .name     = LDB_SYNTAX_SAMBA_REPSFROMTO,
1524
    .ldif_read_fn   = ldb_handler_copy,
1525
    .ldif_write_fn    = ldif_write_repsFromTo,
1526
    .canonicalise_fn  = ldb_handler_copy,
1527
    .comparison_fn    = samba_ldb_comparison_binary,
1528
    .operator_fn      = samba_syntax_binary_operator_fn
1529
  },{
1530
    .name     = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
1531
    .ldif_read_fn   = ldb_handler_copy,
1532
    .ldif_write_fn    = ldif_write_replPropertyMetaData,
1533
    .canonicalise_fn  = ldb_handler_copy,
1534
    .comparison_fn    = samba_ldb_comparison_binary,
1535
    .operator_fn      = samba_syntax_binary_operator_fn
1536
  },{
1537
    .name     = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
1538
    .ldif_read_fn   = ldb_handler_copy,
1539
    .ldif_write_fn    = ldif_write_replUpToDateVector,
1540
    .canonicalise_fn  = ldb_handler_copy,
1541
    .comparison_fn    = samba_ldb_comparison_binary,
1542
    .operator_fn      = samba_syntax_binary_operator_fn
1543
  },{
1544
    .name     = LDB_SYNTAX_SAMBA_REVEALEDUSERS,
1545
    .ldif_read_fn   = ldb_handler_copy,
1546
    .ldif_write_fn    = ldif_write_msDS_RevealedUsers,
1547
    .canonicalise_fn  = dsdb_dn_binary_canonicalise,
1548
    .comparison_fn    = dsdb_dn_binary_comparison,
1549
    .operator_fn      = samba_syntax_operator_fn
1550
  },{
1551
    .name     = LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB,
1552
    .ldif_read_fn   = ldb_handler_copy,
1553
    .ldif_write_fn    = ldif_write_trustAuthInOutBlob,
1554
    .canonicalise_fn  = ldb_handler_copy,
1555
    .comparison_fn    = samba_ldb_comparison_binary,
1556
    .operator_fn      = samba_syntax_binary_operator_fn
1557
  },{
1558
    .name     = LDB_SYNTAX_SAMBA_FORESTTRUSTINFO,
1559
    .ldif_read_fn   = ldb_handler_copy,
1560
    .ldif_write_fn    = ldif_write_ForestTrustInfo,
1561
    .canonicalise_fn  = ldb_handler_copy,
1562
    .comparison_fn    = samba_ldb_comparison_binary,
1563
    .operator_fn      = samba_syntax_binary_operator_fn
1564
  },{
1565
    .name     = DSDB_SYNTAX_BINARY_DN,
1566
    .ldif_read_fn   = ldb_handler_copy,
1567
    .ldif_write_fn    = ldb_handler_copy,
1568
    .canonicalise_fn  = dsdb_dn_binary_canonicalise,
1569
    .comparison_fn    = dsdb_dn_binary_comparison,
1570
    .operator_fn      = samba_syntax_operator_fn
1571
  },{
1572
    .name     = DSDB_SYNTAX_STRING_DN,
1573
    .ldif_read_fn   = ldb_handler_copy,
1574
    .ldif_write_fn    = ldb_handler_copy,
1575
    .canonicalise_fn  = dsdb_dn_string_canonicalise,
1576
    .comparison_fn    = dsdb_dn_string_comparison,
1577
    .operator_fn      = samba_syntax_operator_fn
1578
  },{
1579
    .name     = LDB_SYNTAX_DN,
1580
    .ldif_read_fn   = ldb_handler_copy,
1581
    .ldif_write_fn    = ldb_handler_copy,
1582
    .canonicalise_fn  = samba_ldb_dn_link_canonicalise,
1583
    .comparison_fn    = samba_ldb_dn_link_comparison,
1584
    .operator_fn      = samba_syntax_operator_dn
1585
  },{
1586
    .name     = LDB_SYNTAX_SAMBA_RANGE64,
1587
    .ldif_read_fn   = ldif_read_range64,
1588
    .ldif_write_fn    = ldif_write_range64,
1589
    .canonicalise_fn  = ldif_canonicalise_int64,
1590
    .comparison_fn    = ldif_comparison_int64,
1591
    .operator_fn      = samba_syntax_operator_fn
1592
  },{
1593
    .name     = LDB_SYNTAX_SAMBA_DNSRECORD,
1594
    .ldif_read_fn   = ldb_handler_copy,
1595
    .ldif_write_fn    = ldif_write_dnsRecord,
1596
    .canonicalise_fn  = ldb_handler_copy,
1597
    .comparison_fn    = samba_ldb_comparison_binary,
1598
    .operator_fn      = samba_syntax_binary_operator_fn
1599
  },{
1600
    .name     = LDB_SYNTAX_SAMBA_DNSPROPERTY,
1601
    .ldif_read_fn   = ldb_handler_copy,
1602
    .ldif_write_fn    = ldif_write_dnsProperty,
1603
    .canonicalise_fn  = ldb_handler_copy,
1604
    .comparison_fn    = samba_ldb_comparison_binary,
1605
    .operator_fn      = samba_syntax_binary_operator_fn
1606
  },{
1607
    .name     = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
1608
    .ldif_read_fn   = ldb_handler_copy,
1609
    .ldif_write_fn    = ldif_write_supplementalCredentialsBlob,
1610
    .canonicalise_fn  = ldb_handler_copy,
1611
    .comparison_fn    = samba_ldb_comparison_binary,
1612
    .operator_fn      = samba_syntax_binary_operator_fn
1613
  },{
1614
    .name     = LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET,
1615
    .ldif_read_fn   = ldb_handler_copy,
1616
    .ldif_write_fn    = ldif_write_partialAttributeSet,
1617
    .canonicalise_fn  = ldb_handler_copy,
1618
    .comparison_fn    = samba_ldb_comparison_binary,
1619
    .operator_fn      = samba_syntax_binary_operator_fn
1620
  },{
1621
    .name     = LDB_SYNTAX_SAMBA_OCTET_STRING,
1622
    .ldif_read_fn   = ldb_handler_copy,
1623
    .ldif_write_fn    = ldb_handler_copy,
1624
    .canonicalise_fn  = ldb_handler_copy,
1625
    .comparison_fn    = samba_ldb_comparison_binary,
1626
    .operator_fn      = samba_syntax_binary_operator_fn
1627
  }
1628
};
1629
1630
static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
1631
  {
1632
    .name     = "SID",
1633
    .read_fn          = extended_dn_read_SID,
1634
    .write_clear_fn   = ldif_write_objectSid,
1635
    .write_hex_fn     = extended_dn_write_hex
1636
  },{
1637
    .name     = "GUID",
1638
    .read_fn          = extended_dn_read_GUID,
1639
    .write_clear_fn   = ldif_write_objectGUID,
1640
    .write_hex_fn     = extended_dn_write_hex
1641
  },{
1642
    .name     = "WKGUID",
1643
    .read_fn          = ldb_handler_copy,
1644
    .write_clear_fn   = ldb_handler_copy,
1645
    .write_hex_fn     = ldb_handler_copy
1646
  },{
1647
    .name     = "RMD_INVOCID",
1648
    .read_fn          = extended_dn_read_GUID,
1649
    .write_clear_fn   = ldif_write_objectGUID,
1650
    .write_hex_fn     = extended_dn_write_hex
1651
  },{
1652
    .name     = "RMD_FLAGS",
1653
    .read_fn          = ldb_handler_copy,
1654
    .write_clear_fn   = ldb_handler_copy,
1655
    .write_hex_fn     = ldb_handler_copy
1656
  },{
1657
    .name     = "RMD_ADDTIME",
1658
    .read_fn          = ldb_handler_copy,
1659
    .write_clear_fn   = ldb_handler_copy,
1660
    .write_hex_fn     = ldb_handler_copy
1661
  },{
1662
    .name     = "RMD_CHANGETIME",
1663
    .read_fn          = ldb_handler_copy,
1664
    .write_clear_fn   = ldb_handler_copy,
1665
    .write_hex_fn     = ldb_handler_copy
1666
  },{
1667
    .name     = "RMD_LOCAL_USN",
1668
    .read_fn          = ldb_handler_copy,
1669
    .write_clear_fn   = ldb_handler_copy,
1670
    .write_hex_fn     = ldb_handler_copy
1671
  },{
1672
    .name     = "RMD_ORIGINATING_USN",
1673
    .read_fn          = ldb_handler_copy,
1674
    .write_clear_fn   = ldb_handler_copy,
1675
    .write_hex_fn     = ldb_handler_copy
1676
  },{
1677
    .name     = "RMD_VERSION",
1678
    .read_fn          = ldb_handler_copy,
1679
    .write_clear_fn   = ldb_handler_copy,
1680
    .write_hex_fn     = ldb_handler_copy
1681
  }
1682
};
1683
1684
/* TODO: Should be dynamic at some point */
1685
static const struct {
1686
  const char *name;
1687
  const char *syntax;
1688
} samba_attributes[] = {
1689
  { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
1690
  { "oMSyntax",     LDB_SYNTAX_SAMBA_INT32 },
1691
  { "objectCategory",   LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
1692
  { "schemaInfo",     LDB_SYNTAX_SAMBA_SCHEMAINFO },
1693
  { "prefixMap",                  LDB_SYNTAX_SAMBA_PREFIX_MAP },
1694
  { "repsFrom",                   LDB_SYNTAX_SAMBA_REPSFROMTO },
1695
  { "repsTo",                     LDB_SYNTAX_SAMBA_REPSFROMTO },
1696
  { "replPropertyMetaData",       LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
1697
  { "replUpToDateVector",         LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
1698
  { "msDS-RevealedUsers",         LDB_SYNTAX_SAMBA_REVEALEDUSERS },
1699
  { "trustAuthIncoming",          LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1700
  { "trustAuthOutgoing",          LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1701
  { "msDS-TrustForestTrustInfo",  LDB_SYNTAX_SAMBA_FORESTTRUSTINFO },
1702
  { "rIDAllocationPool",    LDB_SYNTAX_SAMBA_RANGE64 },
1703
  { "rIDPreviousAllocationPool",  LDB_SYNTAX_SAMBA_RANGE64 },
1704
  { "rIDAvailablePool",   LDB_SYNTAX_SAMBA_RANGE64 },
1705
  { "defaultSecurityDescriptor",  LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR },
1706
1707
  /*
1708
   * these are extracted by searching
1709
   * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
1710
   *
1711
   * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
1712
   * adminDescription: For a Central Access Policy, this attribute defines a GUID t
1713
   * hat can be used to identify the set of policies when applied to a resource.
1714
   * Until we see a msAuthz-CentralAccessPolicyID value on a windows
1715
   * server, we ignore it here.
1716
   */
1717
  { "mS-DS-CreatorSID",   LDB_SYNTAX_SAMBA_SID },
1718
  { "msDS-QuotaTrustee",    LDB_SYNTAX_SAMBA_SID },
1719
  { "objectSid",      LDB_SYNTAX_SAMBA_SID },
1720
  { "tokenGroups",          LDB_SYNTAX_SAMBA_SID },
1721
  { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID },
1722
  { "tokenGroupsNoGCAcceptable",  LDB_SYNTAX_SAMBA_SID },
1723
  { "securityIdentifier",   LDB_SYNTAX_SAMBA_SID },
1724
  { "sIDHistory",     LDB_SYNTAX_SAMBA_SID },
1725
  { "syncWithSID",    LDB_SYNTAX_SAMBA_SID },
1726
1727
  /*
1728
   * these are extracted by searching
1729
   * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1730
   */
1731
  { "attributeSecurityGUID",    LDB_SYNTAX_SAMBA_GUID },
1732
  { "categoryId",       LDB_SYNTAX_SAMBA_GUID },
1733
  { "controlAccessRights",    LDB_SYNTAX_SAMBA_GUID },
1734
  { "currMachineId",      LDB_SYNTAX_SAMBA_GUID },
1735
  { "fRSReplicaSetGUID",      LDB_SYNTAX_SAMBA_GUID },
1736
  { "fRSVersionGUID",     LDB_SYNTAX_SAMBA_GUID },
1737
  { "implementedCategories",    LDB_SYNTAX_SAMBA_GUID },
1738
  { "msDS-AzObjectGuid",      LDB_SYNTAX_SAMBA_GUID },
1739
  { "msDS-GenerationId",      LDB_SYNTAX_SAMBA_GUID },
1740
  { "msDS-OptionalFeatureGUID",   LDB_SYNTAX_SAMBA_GUID },
1741
  { "msDFSR-ContentSetGuid",    LDB_SYNTAX_SAMBA_GUID },
1742
  { "msDFSR-ReplicationGroupGuid",  LDB_SYNTAX_SAMBA_GUID },
1743
  { "mSMQDigests",      LDB_SYNTAX_SAMBA_GUID },
1744
  { "mSMQOwnerID",      LDB_SYNTAX_SAMBA_GUID },
1745
  { "mSMQQMID",       LDB_SYNTAX_SAMBA_GUID },
1746
  { "mSMQQueueType",      LDB_SYNTAX_SAMBA_GUID },
1747
  { "mSMQSites",        LDB_SYNTAX_SAMBA_GUID },
1748
  { "netbootGUID",      LDB_SYNTAX_SAMBA_GUID },
1749
  { "objectGUID",       LDB_SYNTAX_SAMBA_GUID },
1750
  { "pKTGuid",        LDB_SYNTAX_SAMBA_GUID },
1751
  { "requiredCategories",     LDB_SYNTAX_SAMBA_GUID },
1752
  { "schemaIDGUID",     LDB_SYNTAX_SAMBA_GUID },
1753
  { "siteGUID",       LDB_SYNTAX_SAMBA_GUID },
1754
  { "msDFS-GenerationGUIDv2",   LDB_SYNTAX_SAMBA_GUID },
1755
  { "msDFS-LinkIdentityGUIDv2",   LDB_SYNTAX_SAMBA_GUID },
1756
  { "msDFS-NamespaceIdentityGUIDv2",  LDB_SYNTAX_SAMBA_GUID },
1757
  { "msSPP-CSVLKSkuId",     LDB_SYNTAX_SAMBA_GUID },
1758
  { "msSPP-KMSIds",     LDB_SYNTAX_SAMBA_GUID },
1759
1760
  /*
1761
   * these are known to be GUIDs
1762
   */
1763
  { "invocationId",     LDB_SYNTAX_SAMBA_GUID },
1764
  { "parentGUID",       LDB_SYNTAX_SAMBA_GUID },
1765
1766
  /* These NDR encoded things we want to be able to read with --show-binary */
1767
  { "dnsRecord",        LDB_SYNTAX_SAMBA_DNSRECORD },
1768
  { "dNSProperty",      LDB_SYNTAX_SAMBA_DNSPROPERTY },
1769
  { "supplementalCredentials",    LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS},
1770
  { "partialAttributeSet",    LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET}
1771
};
1772
1773
const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
1774
0
{
1775
0
  unsigned int j;
1776
0
  const struct ldb_schema_syntax *s = NULL;
1777
1778
0
  for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
1779
0
    if (strcmp(name, samba_syntaxes[j].name) == 0) {
1780
0
      s = &samba_syntaxes[j];
1781
0
      break;
1782
0
    }
1783
0
  }
1784
0
  return s;
1785
0
}
1786
1787
const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
1788
0
{
1789
0
  unsigned int j;
1790
0
  const struct ldb_schema_syntax *s = NULL;
1791
1792
0
  for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
1793
0
    if (strcmp(samba_attributes[j].name, name) == 0) {
1794
0
      s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
1795
0
      break;
1796
0
    }
1797
0
  }
1798
1799
0
  return s;
1800
0
}
1801
1802
static const char *secret_attributes[] = {DSDB_SECRET_ATTRIBUTES, "secret",
1803
                                          "priorSecret", NULL};
1804
1805
/*
1806
  register the samba ldif handlers
1807
*/
1808
int ldb_register_samba_handlers(struct ldb_context *ldb)
1809
0
{
1810
0
  unsigned int i;
1811
0
  int ret;
1812
1813
0
  if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
1814
0
    return LDB_SUCCESS;
1815
0
  }
1816
1817
0
  ret = ldb_set_opaque(ldb, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE, discard_const_p(char *, secret_attributes));
1818
0
  if (ret != LDB_SUCCESS) {
1819
0
    return ret;
1820
0
  }
1821
1822
0
  for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
1823
0
    const struct ldb_schema_syntax *s = NULL;
1824
1825
0
    s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
1826
1827
0
    if (!s) {
1828
0
      s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
1829
0
    }
1830
1831
0
    if (!s) {
1832
0
      return LDB_ERR_OPERATIONS_ERROR;
1833
0
    }
1834
1835
0
    ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
1836
0
    if (ret != LDB_SUCCESS) {
1837
0
      return ret;
1838
0
    }
1839
0
  }
1840
1841
0
  for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
1842
0
    ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
1843
0
    if (ret != LDB_SUCCESS) {
1844
0
      return ret;
1845
0
    }
1846
1847
0
  }
1848
1849
0
  ret = ldb_register_samba_matching_rules(ldb);
1850
0
  if (ret != LDB_SUCCESS) {
1851
0
    talloc_free(ldb);
1852
0
    return LDB_SUCCESS;
1853
0
  }
1854
1855
0
  ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1856
0
  if (ret != LDB_SUCCESS) {
1857
0
    return ret;
1858
0
  }
1859
1860
0
  return LDB_SUCCESS;
1861
0
}