Coverage Report

Created: 2025-11-16 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source4/dsdb/schema/schema_syntax.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS Implementation.
3
   DSDB schema syntaxes
4
5
   Copyright (C) Stefan Metzmacher <metze@samba.org> 2006
6
   Copyright (C) Simo Sorce 2005
7
   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
8
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 3 of the License, or
12
   (at your option) any later version.
13
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
19
   You should have received a copy of the GNU General Public License
20
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
22
*/
23
#include "includes.h"
24
#include "dsdb/samdb/samdb.h"
25
#include "librpc/gen_ndr/ndr_drsuapi.h"
26
#include "librpc/gen_ndr/ndr_security.h"
27
#include "librpc/gen_ndr/ndr_misc.h"
28
#include <ldb.h>
29
#include <ldb_errors.h>
30
#include "system/time.h"
31
#include "../lib/util/charset/charset.h"
32
#include "librpc/ndr/libndr.h"
33
#include "../lib/util/asn1.h"
34
35
#undef strcasecmp
36
37
/**
38
 * Initialize dsdb_syntax_ctx with default values
39
 * for common cases.
40
 */
41
void dsdb_syntax_ctx_init(struct dsdb_syntax_ctx *ctx,
42
        struct ldb_context *ldb,
43
        const struct dsdb_schema *schema)
44
0
{
45
0
  ctx->ldb  = ldb;
46
0
  ctx->schema   = schema;
47
48
  /*
49
   * 'true' will keep current behavior,
50
   * i.e. attributeID_id will be returned by default
51
   */
52
0
  ctx->is_schema_nc = true;
53
54
0
  ctx->pfm_remote = NULL;
55
0
}
56
57
58
/**
59
 * Returns ATTID for DRS attribute.
60
 *
61
 * ATTID depends on whether we are replicating
62
 * Schema NC or msDs-IntId is set for schemaAttribute
63
 * for the attribute.
64
 */
65
uint32_t dsdb_attribute_get_attid(const struct dsdb_attribute *attr,
66
          bool for_schema_nc)
67
0
{
68
0
  if (!for_schema_nc && attr->msDS_IntId) {
69
0
    return attr->msDS_IntId;
70
0
  }
71
72
0
  return attr->attributeID_id;
73
0
}
74
75
/**
76
 * Map an ATTID from remote DC to a local ATTID
77
 * using remote prefixMap
78
 */
79
static bool dsdb_syntax_attid_from_remote_attid(const struct dsdb_syntax_ctx *ctx,
80
            TALLOC_CTX *mem_ctx,
81
            uint32_t id_remote,
82
            uint32_t *id_local)
83
0
{
84
0
  WERROR werr;
85
0
  const char *oid;
86
87
  /*
88
   * map remote ATTID to local directly in case
89
   * of no remote prefixMap (during provision for instance)
90
   */
91
0
  if (!ctx->pfm_remote) {
92
0
    *id_local = id_remote;
93
0
    return true;
94
0
  }
95
96
0
  werr = dsdb_schema_pfm_oid_from_attid(ctx->pfm_remote, id_remote, mem_ctx, &oid);
97
0
  if (!W_ERROR_IS_OK(werr)) {
98
0
    DEBUG(0,("ATTID->OID failed (%s) for: 0x%08X\n", win_errstr(werr), id_remote));
99
0
    return false;
100
0
  }
101
102
0
  werr = dsdb_schema_pfm_attid_from_oid(ctx->schema->prefixmap, oid, id_local);
103
0
  if (!W_ERROR_IS_OK(werr)) {
104
0
    DEBUG(0,("OID->ATTID failed (%s) for: %s\n", win_errstr(werr), oid));
105
0
    return false;
106
0
  }
107
108
0
  return true;
109
0
}
110
111
static WERROR dsdb_syntax_FOOBAR_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
112
            const struct dsdb_attribute *attr,
113
            const struct drsuapi_DsReplicaAttribute *in,
114
            TALLOC_CTX *mem_ctx,
115
            struct ldb_message_element *out)
116
0
{
117
0
  unsigned int i;
118
119
0
  out->flags  = 0;
120
0
  out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
121
0
  W_ERROR_HAVE_NO_MEMORY(out->name);
122
123
0
  out->num_values = in->value_ctr.num_values;
124
0
  out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
125
0
  W_ERROR_HAVE_NO_MEMORY(out->values);
126
127
0
  for (i=0; i < out->num_values; i++) {
128
0
    char *str;
129
130
0
    if (in->value_ctr.values[i].blob == NULL) {
131
0
      return WERR_FOOBAR;
132
0
    }
133
134
0
    str = talloc_asprintf(out->values, "%s: not implemented",
135
0
              attr->syntax->name);
136
0
    W_ERROR_HAVE_NO_MEMORY(str);
137
138
0
    out->values[i] = data_blob_string_const(str);
139
0
  }
140
141
0
  return WERR_OK;
142
0
}
143
144
static WERROR dsdb_syntax_FOOBAR_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
145
            const struct dsdb_attribute *attr,
146
            const struct ldb_message_element *in,
147
            TALLOC_CTX *mem_ctx,
148
            struct drsuapi_DsReplicaAttribute *out)
149
0
{
150
0
  return WERR_FOOBAR;
151
0
}
152
153
static WERROR dsdb_syntax_FOOBAR_validate_ldb(const struct dsdb_syntax_ctx *ctx,
154
                const struct dsdb_attribute *attr,
155
                const struct ldb_message_element *in)
156
0
{
157
0
  return WERR_FOOBAR;
158
0
}
159
160
static WERROR dsdb_syntax_BOOL_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
161
                const struct dsdb_attribute *attr,
162
                const struct drsuapi_DsReplicaAttribute *in,
163
                TALLOC_CTX *mem_ctx,
164
                struct ldb_message_element *out)
165
0
{
166
0
  unsigned int i;
167
168
0
  out->flags  = 0;
169
0
  out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
170
0
  W_ERROR_HAVE_NO_MEMORY(out->name);
171
172
0
  out->num_values = in->value_ctr.num_values;
173
0
  out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
174
0
  W_ERROR_HAVE_NO_MEMORY(out->values);
175
176
0
  for (i=0; i < out->num_values; i++) {
177
0
    uint32_t v;
178
0
    char *str;
179
180
0
    if (in->value_ctr.values[i].blob == NULL) {
181
0
      return WERR_FOOBAR;
182
0
    }
183
184
0
    if (in->value_ctr.values[i].blob->length != 4) {
185
0
      return WERR_FOOBAR;
186
0
    }
187
188
0
    v = IVAL(in->value_ctr.values[i].blob->data, 0);
189
190
0
    if (v != 0) {
191
0
      str = talloc_strdup(out->values, "TRUE");
192
0
      W_ERROR_HAVE_NO_MEMORY(str);
193
0
    } else {
194
0
      str = talloc_strdup(out->values, "FALSE");
195
0
      W_ERROR_HAVE_NO_MEMORY(str);
196
0
    }
197
198
0
    out->values[i] = data_blob_string_const(str);
199
0
  }
200
201
0
  return WERR_OK;
202
0
}
203
204
static WERROR dsdb_syntax_BOOL_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
205
                const struct dsdb_attribute *attr,
206
                const struct ldb_message_element *in,
207
                TALLOC_CTX *mem_ctx,
208
                struct drsuapi_DsReplicaAttribute *out)
209
0
{
210
0
  unsigned int i;
211
0
  DATA_BLOB *blobs;
212
213
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
214
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
215
0
  }
216
217
0
  out->attid      = dsdb_attribute_get_attid(attr,
218
0
                   ctx->is_schema_nc);
219
0
  out->value_ctr.num_values = in->num_values;
220
0
  out->value_ctr.values   = talloc_array(mem_ctx,
221
0
                   struct drsuapi_DsAttributeValue,
222
0
                   in->num_values);
223
0
  W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
224
225
0
  blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
226
0
  W_ERROR_HAVE_NO_MEMORY(blobs);
227
228
0
  for (i=0; i < in->num_values; i++) {
229
0
    out->value_ctr.values[i].blob = &blobs[i];
230
231
0
    blobs[i] = data_blob_talloc(blobs, NULL, 4);
232
0
    W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
233
234
0
    if (in->values[i].length >= 4 &&
235
0
        strncmp("TRUE", (const char *)in->values[i].data, in->values[i].length) == 0) {
236
0
      SIVAL(blobs[i].data, 0, 0x00000001);
237
0
    } else if (in->values[i].length >= 5 &&
238
0
         strncmp("FALSE", (const char *)in->values[i].data, in->values[i].length) == 0) {
239
0
      SIVAL(blobs[i].data, 0, 0x00000000);
240
0
    } else {
241
0
      return WERR_FOOBAR;
242
0
    }
243
0
  }
244
245
0
  return WERR_OK;
246
0
}
247
248
static WERROR dsdb_syntax_BOOL_validate_ldb(const struct dsdb_syntax_ctx *ctx,
249
              const struct dsdb_attribute *attr,
250
              const struct ldb_message_element *in)
251
0
{
252
0
  unsigned int i;
253
254
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
255
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
256
0
  }
257
258
0
  for (i=0; i < in->num_values; i++) {
259
0
    if (in->values[i].length == 0) {
260
0
      return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
261
0
    }
262
263
0
    if (in->values[i].length >= 4 &&
264
0
        strncmp("TRUE",
265
0
          (const char *)in->values[i].data,
266
0
          in->values[i].length) == 0) {
267
0
      continue;
268
0
    }
269
0
    if (in->values[i].length >= 5 &&
270
0
        strncmp("FALSE",
271
0
          (const char *)in->values[i].data,
272
0
          in->values[i].length) == 0) {
273
0
      continue;
274
0
    }
275
0
    return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
276
0
  }
277
278
0
  return WERR_OK;
279
0
}
280
281
static WERROR dsdb_syntax_INT32_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
282
                 const struct dsdb_attribute *attr,
283
                 const struct drsuapi_DsReplicaAttribute *in,
284
                 TALLOC_CTX *mem_ctx,
285
                 struct ldb_message_element *out)
286
0
{
287
0
  unsigned int i;
288
289
0
  out->flags  = 0;
290
0
  out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
291
0
  W_ERROR_HAVE_NO_MEMORY(out->name);
292
293
0
  out->num_values = in->value_ctr.num_values;
294
0
  out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
295
0
  W_ERROR_HAVE_NO_MEMORY(out->values);
296
297
0
  for (i=0; i < out->num_values; i++) {
298
0
    int32_t v;
299
0
    char *str;
300
301
0
    if (in->value_ctr.values[i].blob == NULL) {
302
0
      return WERR_FOOBAR;
303
0
    }
304
305
0
    if (in->value_ctr.values[i].blob->length != 4) {
306
0
      return WERR_FOOBAR;
307
0
    }
308
309
0
    v = IVALS(in->value_ctr.values[i].blob->data, 0);
310
311
0
    str = talloc_asprintf(out->values, "%d", v);
312
0
    W_ERROR_HAVE_NO_MEMORY(str);
313
314
0
    out->values[i] = data_blob_string_const(str);
315
0
  }
316
317
0
  return WERR_OK;
318
0
}
319
320
static WERROR dsdb_syntax_INT32_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
321
                 const struct dsdb_attribute *attr,
322
                 const struct ldb_message_element *in,
323
                 TALLOC_CTX *mem_ctx,
324
                 struct drsuapi_DsReplicaAttribute *out)
325
0
{
326
0
  unsigned int i;
327
0
  DATA_BLOB *blobs;
328
329
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
330
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
331
0
  }
332
333
0
  out->attid      = dsdb_attribute_get_attid(attr,
334
0
                   ctx->is_schema_nc);
335
0
  out->value_ctr.num_values = in->num_values;
336
0
  out->value_ctr.values   = talloc_array(mem_ctx,
337
0
                   struct drsuapi_DsAttributeValue,
338
0
                   in->num_values);
339
0
  W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
340
341
0
  blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
342
0
  W_ERROR_HAVE_NO_MEMORY(blobs);
343
344
0
  for (i=0; i < in->num_values; i++) {
345
0
    int32_t v;
346
347
0
    out->value_ctr.values[i].blob = &blobs[i];
348
349
0
    blobs[i] = data_blob_talloc(blobs, NULL, 4);
350
0
    W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
351
352
    /* We've to use "strtoll" here to have the intended overflows.
353
     * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
354
0
    v = (int32_t) strtoll((char *)in->values[i].data, NULL, 0);
355
356
0
    SIVALS(blobs[i].data, 0, v);
357
0
  }
358
359
0
  return WERR_OK;
360
0
}
361
362
static WERROR dsdb_syntax_INT32_validate_ldb(const struct dsdb_syntax_ctx *ctx,
363
               const struct dsdb_attribute *attr,
364
               const struct ldb_message_element *in)
365
0
{
366
0
  unsigned int i;
367
368
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
369
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
370
0
  }
371
372
0
  for (i=0; i < in->num_values; i++) {
373
0
    long v;
374
0
    char buf[sizeof("-2147483648")];
375
0
    char *end = NULL;
376
377
0
    ZERO_STRUCT(buf);
378
0
    if (in->values[i].length >= sizeof(buf)) {
379
0
      return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
380
0
    }
381
382
0
    memcpy(buf, in->values[i].data, in->values[i].length);
383
0
    errno = 0;
384
0
    v = strtol(buf, &end, 10);
385
0
    if (errno != 0) {
386
0
      return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
387
0
    }
388
0
    if (end && end[0] != '\0') {
389
0
      return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
390
0
    }
391
392
0
    if (attr->rangeLower) {
393
0
      if ((int32_t)v < (int32_t)*attr->rangeLower) {
394
0
        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
395
0
      }
396
0
    }
397
398
0
    if (attr->rangeUpper) {
399
0
      if ((int32_t)v > (int32_t)*attr->rangeUpper) {
400
0
        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
401
0
      }
402
0
    }
403
0
  }
404
405
0
  return WERR_OK;
406
0
}
407
408
static WERROR dsdb_syntax_INT64_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
409
                 const struct dsdb_attribute *attr,
410
                 const struct drsuapi_DsReplicaAttribute *in,
411
                 TALLOC_CTX *mem_ctx,
412
                 struct ldb_message_element *out)
413
0
{
414
0
  unsigned int i;
415
416
0
  out->flags  = 0;
417
0
  out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
418
0
  W_ERROR_HAVE_NO_MEMORY(out->name);
419
420
0
  out->num_values = in->value_ctr.num_values;
421
0
  out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
422
0
  W_ERROR_HAVE_NO_MEMORY(out->values);
423
424
0
  for (i=0; i < out->num_values; i++) {
425
0
    int64_t v;
426
0
    char *str;
427
428
0
    if (in->value_ctr.values[i].blob == NULL) {
429
0
      return WERR_FOOBAR;
430
0
    }
431
432
0
    if (in->value_ctr.values[i].blob->length != 8) {
433
0
      return WERR_FOOBAR;
434
0
    }
435
436
0
    v = BVALS(in->value_ctr.values[i].blob->data, 0);
437
438
0
    str = talloc_asprintf(out->values, "%lld", (long long int)v);
439
0
    W_ERROR_HAVE_NO_MEMORY(str);
440
441
0
    out->values[i] = data_blob_string_const(str);
442
0
  }
443
444
0
  return WERR_OK;
445
0
}
446
447
static WERROR dsdb_syntax_INT64_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
448
                 const struct dsdb_attribute *attr,
449
                 const struct ldb_message_element *in,
450
                 TALLOC_CTX *mem_ctx,
451
                 struct drsuapi_DsReplicaAttribute *out)
452
0
{
453
0
  unsigned int i;
454
0
  DATA_BLOB *blobs;
455
456
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
457
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
458
0
  }
459
460
0
  out->attid      = dsdb_attribute_get_attid(attr,
461
0
                   ctx->is_schema_nc);
462
0
  out->value_ctr.num_values = in->num_values;
463
0
  out->value_ctr.values   = talloc_array(mem_ctx,
464
0
                   struct drsuapi_DsAttributeValue,
465
0
                   in->num_values);
466
0
  W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
467
468
0
  blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
469
0
  W_ERROR_HAVE_NO_MEMORY(blobs);
470
471
0
  for (i=0; i < in->num_values; i++) {
472
0
    int64_t v;
473
474
0
    out->value_ctr.values[i].blob = &blobs[i];
475
476
0
    blobs[i] = data_blob_talloc(blobs, NULL, 8);
477
0
    W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
478
479
0
    v = strtoll((const char *)in->values[i].data, NULL, 10);
480
481
0
    SBVALS(blobs[i].data, 0, v);
482
0
  }
483
484
0
  return WERR_OK;
485
0
}
486
487
static WERROR dsdb_syntax_INT64_validate_ldb(const struct dsdb_syntax_ctx *ctx,
488
               const struct dsdb_attribute *attr,
489
               const struct ldb_message_element *in)
490
0
{
491
0
  unsigned int i;
492
493
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
494
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
495
0
  }
496
497
0
  for (i=0; i < in->num_values; i++) {
498
0
    long long v;
499
0
    char buf[sizeof("-9223372036854775808")];
500
0
    char *end = NULL;
501
502
0
    ZERO_STRUCT(buf);
503
0
    if (in->values[i].length >= sizeof(buf)) {
504
0
      return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
505
0
    }
506
0
    memcpy(buf, in->values[i].data, in->values[i].length);
507
508
0
    errno = 0;
509
0
    v = strtoll(buf, &end, 10);
510
0
    if (errno != 0) {
511
0
      return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
512
0
    }
513
0
    if (end && end[0] != '\0') {
514
0
      return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
515
0
    }
516
517
0
    if (attr->rangeLower) {
518
0
      if ((int64_t)v < (int64_t)*attr->rangeLower) {
519
0
        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
520
0
      }
521
0
    }
522
523
0
    if (attr->rangeUpper) {
524
0
      if ((int64_t)v > (int64_t)*attr->rangeUpper) {
525
0
        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
526
0
      }
527
0
    }
528
0
  }
529
530
0
  return WERR_OK;
531
0
}
532
static WERROR dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
533
                const struct dsdb_attribute *attr,
534
                const struct drsuapi_DsReplicaAttribute *in,
535
                TALLOC_CTX *mem_ctx,
536
                struct ldb_message_element *out)
537
0
{
538
0
  unsigned int i;
539
540
0
  out->flags  = 0;
541
0
  out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
542
0
  W_ERROR_HAVE_NO_MEMORY(out->name);
543
544
0
  out->num_values = in->value_ctr.num_values;
545
0
  out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
546
0
  W_ERROR_HAVE_NO_MEMORY(out->values);
547
548
0
  for (i=0; i < out->num_values; i++) {
549
0
    NTTIME v;
550
0
    time_t t;
551
0
    char *str;
552
553
0
    if (in->value_ctr.values[i].blob == NULL) {
554
0
      return WERR_FOOBAR;
555
0
    }
556
557
0
    if (in->value_ctr.values[i].blob->length != 8) {
558
0
      return WERR_FOOBAR;
559
0
    }
560
561
0
    v = BVAL(in->value_ctr.values[i].blob->data, 0);
562
0
    if (v == 0) {
563
      /* special case for 1601 zero timestamp */
564
0
      out->values[i] = data_blob_string_const("16010101000000.0Z");
565
0
      continue;
566
0
    }
567
0
    v *= 10000000;
568
0
    t = nt_time_to_unix(v);
569
570
    /*
571
     * NOTE: On a w2k3 server you can set a GeneralizedTime string
572
     *       via LDAP, but you get back an UTCTime string,
573
     *       but via DRSUAPI you get back the NTTIME_1sec value
574
     *       that represents the GeneralizedTime value!
575
     *
576
     *       So if we store the UTCTime string in our ldb
577
     *       we'll loose information!
578
     */
579
0
    str = ldb_timestring_utc(out->values, t);
580
0
    W_ERROR_HAVE_NO_MEMORY(str);
581
0
    out->values[i] = data_blob_string_const(str);
582
0
  }
583
584
0
  return WERR_OK;
585
0
}
586
587
static WERROR dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
588
                const struct dsdb_attribute *attr,
589
                const struct ldb_message_element *in,
590
                TALLOC_CTX *mem_ctx,
591
                struct drsuapi_DsReplicaAttribute *out)
592
0
{
593
0
  unsigned int i;
594
0
  DATA_BLOB *blobs;
595
596
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
597
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
598
0
  }
599
600
0
  out->attid      = dsdb_attribute_get_attid(attr,
601
0
                   ctx->is_schema_nc);
602
0
  out->value_ctr.num_values = in->num_values;
603
0
  out->value_ctr.values   = talloc_array(mem_ctx,
604
0
                   struct drsuapi_DsAttributeValue,
605
0
                   in->num_values);
606
0
  W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
607
608
0
  blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
609
0
  W_ERROR_HAVE_NO_MEMORY(blobs);
610
611
0
  for (i=0; i < in->num_values; i++) {
612
0
    NTTIME v;
613
0
    time_t t;
614
615
0
    out->value_ctr.values[i].blob = &blobs[i];
616
617
0
    blobs[i] = data_blob_talloc(blobs, NULL, 8);
618
0
    W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
619
620
0
    if (ldb_val_string_cmp(&in->values[i], "16010101000000.0Z") == 0) {
621
0
      SBVALS(blobs[i].data, 0, 0);
622
0
      continue;
623
0
    }
624
625
0
    t = ldb_string_utc_to_time((const char *)in->values[i].data);
626
0
    unix_to_nt_time(&v, t);
627
0
    v /= 10000000;
628
629
0
    SBVAL(blobs[i].data, 0, v);
630
0
  }
631
632
0
  return WERR_OK;
633
0
}
634
635
static WERROR dsdb_syntax_NTTIME_UTC_validate_ldb(const struct dsdb_syntax_ctx *ctx,
636
              const struct dsdb_attribute *attr,
637
              const struct ldb_message_element *in)
638
0
{
639
0
  unsigned int i;
640
641
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
642
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
643
0
  }
644
645
0
  for (i=0; i < in->num_values; i++) {
646
0
    time_t t;
647
0
    char buf[sizeof("090826075717Z")];
648
649
0
    ZERO_STRUCT(buf);
650
0
    if (in->values[i].length >= sizeof(buf)) {
651
0
      return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
652
0
    }
653
0
    memcpy(buf, in->values[i].data, in->values[i].length);
654
655
0
    t = ldb_string_utc_to_time(buf);
656
0
    if (t == 0) {
657
0
      return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
658
0
    }
659
660
0
    if (attr->rangeLower) {
661
0
      if ((int32_t)t < (int32_t)*attr->rangeLower) {
662
0
        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
663
0
      }
664
0
    }
665
666
0
    if (attr->rangeUpper) {
667
0
      if ((int32_t)t > (int32_t)*attr->rangeUpper) {
668
0
        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
669
0
      }
670
0
    }
671
672
    /*
673
     * TODO: verify the comment in the
674
     * dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb() function!
675
     */
676
0
  }
677
678
0
  return WERR_OK;
679
0
}
680
681
static WERROR dsdb_syntax_NTTIME_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
682
            const struct dsdb_attribute *attr,
683
            const struct drsuapi_DsReplicaAttribute *in,
684
            TALLOC_CTX *mem_ctx,
685
            struct ldb_message_element *out)
686
0
{
687
0
  unsigned int i;
688
689
0
  out->flags  = 0;
690
0
  out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
691
0
  W_ERROR_HAVE_NO_MEMORY(out->name);
692
693
0
  out->num_values = in->value_ctr.num_values;
694
0
  out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
695
0
  W_ERROR_HAVE_NO_MEMORY(out->values);
696
697
0
  for (i=0; i < out->num_values; i++) {
698
0
    NTTIME v;
699
0
    time_t t;
700
0
    char *str;
701
702
0
    if (in->value_ctr.values[i].blob == NULL) {
703
0
      return WERR_FOOBAR;
704
0
    }
705
706
0
    if (in->value_ctr.values[i].blob->length != 8) {
707
0
      return WERR_FOOBAR;
708
0
    }
709
710
0
    v = BVAL(in->value_ctr.values[i].blob->data, 0);
711
0
    if (v == 0) {
712
      /* special case for 1601 zero timestamp */
713
0
      out->values[i] = data_blob_string_const("16010101000000.0Z");
714
0
      continue;
715
0
    }
716
0
    v *= 10000000;
717
0
    t = nt_time_to_unix(v);
718
719
0
    str = ldb_timestring(out->values, t);
720
0
    W_ERROR_HAVE_NO_MEMORY(str);
721
722
0
    out->values[i] = data_blob_string_const(str);
723
0
  }
724
725
0
  return WERR_OK;
726
0
}
727
728
static WERROR dsdb_syntax_NTTIME_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
729
            const struct dsdb_attribute *attr,
730
            const struct ldb_message_element *in,
731
            TALLOC_CTX *mem_ctx,
732
            struct drsuapi_DsReplicaAttribute *out)
733
0
{
734
0
  unsigned int i;
735
0
  DATA_BLOB *blobs;
736
737
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
738
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
739
0
  }
740
741
0
  out->attid      = dsdb_attribute_get_attid(attr,
742
0
                   ctx->is_schema_nc);
743
0
  out->value_ctr.num_values = in->num_values;
744
0
  out->value_ctr.values   = talloc_array(mem_ctx,
745
0
                   struct drsuapi_DsAttributeValue,
746
0
                   in->num_values);
747
0
  W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
748
749
0
  blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
750
0
  W_ERROR_HAVE_NO_MEMORY(blobs);
751
752
0
  for (i=0; i < in->num_values; i++) {
753
0
    NTTIME v;
754
0
    time_t t;
755
0
    int ret;
756
757
0
    out->value_ctr.values[i].blob = &blobs[i];
758
759
0
    blobs[i] = data_blob_talloc(blobs, NULL, 8);
760
0
    W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
761
762
0
    if (ldb_val_string_cmp(&in->values[i], "16010101000000.0Z") == 0) {
763
0
      SBVALS(blobs[i].data, 0, 0);
764
0
      continue;
765
0
    }
766
767
0
    ret = ldb_val_to_time(&in->values[i], &t);
768
0
    if (ret != LDB_SUCCESS) {
769
0
      return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
770
0
    }
771
0
    unix_to_nt_time(&v, t);
772
0
    v /= 10000000;
773
774
0
    SBVAL(blobs[i].data, 0, v);
775
0
  }
776
777
0
  return WERR_OK;
778
0
}
779
780
static WERROR dsdb_syntax_NTTIME_validate_ldb(const struct dsdb_syntax_ctx *ctx,
781
                const struct dsdb_attribute *attr,
782
                const struct ldb_message_element *in)
783
0
{
784
0
  unsigned int i;
785
786
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
787
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
788
0
  }
789
790
0
  for (i=0; i < in->num_values; i++) {
791
0
    time_t t;
792
0
    int ret;
793
794
0
    ret = ldb_val_to_time(&in->values[i], &t);
795
0
    if (ret != LDB_SUCCESS) {
796
0
      return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
797
0
    }
798
799
0
    if (attr->rangeLower) {
800
0
      if ((int32_t)t < (int32_t)*attr->rangeLower) {
801
0
        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
802
0
      }
803
0
    }
804
805
0
    if (attr->rangeUpper) {
806
0
      if ((int32_t)t > (int32_t)*attr->rangeUpper) {
807
0
        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
808
0
      }
809
0
    }
810
0
  }
811
812
0
  return WERR_OK;
813
0
}
814
815
static WERROR dsdb_syntax_DATA_BLOB_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
816
               const struct dsdb_attribute *attr,
817
               const struct drsuapi_DsReplicaAttribute *in,
818
               TALLOC_CTX *mem_ctx,
819
               struct ldb_message_element *out)
820
0
{
821
0
  unsigned int i;
822
823
0
  out->flags  = 0;
824
0
  out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
825
0
  W_ERROR_HAVE_NO_MEMORY(out->name);
826
827
0
  out->num_values = in->value_ctr.num_values;
828
0
  out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
829
0
  W_ERROR_HAVE_NO_MEMORY(out->values);
830
831
0
  for (i=0; i < out->num_values; i++) {
832
0
    if (in->value_ctr.values[i].blob == NULL) {
833
0
      return WERR_FOOBAR;
834
0
    }
835
836
0
    if (in->value_ctr.values[i].blob->length == 0) {
837
0
      return WERR_FOOBAR;
838
0
    }
839
840
0
    out->values[i] = data_blob_dup_talloc(out->values,
841
0
                  *in->value_ctr.values[i].blob);
842
0
    W_ERROR_HAVE_NO_MEMORY(out->values[i].data);
843
0
  }
844
845
0
  return WERR_OK;
846
0
}
847
848
static WERROR dsdb_syntax_DATA_BLOB_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
849
               const struct dsdb_attribute *attr,
850
               const struct ldb_message_element *in,
851
               TALLOC_CTX *mem_ctx,
852
               struct drsuapi_DsReplicaAttribute *out)
853
0
{
854
0
  unsigned int i;
855
0
  DATA_BLOB *blobs;
856
857
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
858
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
859
0
  }
860
861
0
  out->attid      = dsdb_attribute_get_attid(attr,
862
0
                   ctx->is_schema_nc);
863
0
  out->value_ctr.num_values = in->num_values;
864
0
  out->value_ctr.values   = talloc_array(mem_ctx,
865
0
                   struct drsuapi_DsAttributeValue,
866
0
                   in->num_values);
867
0
  W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
868
869
0
  blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
870
0
  W_ERROR_HAVE_NO_MEMORY(blobs);
871
872
0
  for (i=0; i < in->num_values; i++) {
873
0
    out->value_ctr.values[i].blob = &blobs[i];
874
875
0
    blobs[i] = data_blob_dup_talloc(blobs, in->values[i]);
876
0
    W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
877
0
  }
878
879
0
  return WERR_OK;
880
0
}
881
882
static WERROR dsdb_syntax_DATA_BLOB_validate_one_val(const struct dsdb_syntax_ctx *ctx,
883
                 const struct dsdb_attribute *attr,
884
                 const struct ldb_val *val)
885
0
{
886
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
887
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
888
0
  }
889
890
0
  if (attr->rangeLower) {
891
0
    if ((uint32_t)val->length < (uint32_t)*attr->rangeLower) {
892
0
      return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
893
0
    }
894
0
  }
895
896
0
  if (attr->rangeUpper) {
897
0
    if ((uint32_t)val->length > (uint32_t)*attr->rangeUpper) {
898
0
      return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
899
0
    }
900
0
  }
901
902
0
  return WERR_OK;
903
0
}
904
905
static WERROR dsdb_syntax_DATA_BLOB_validate_ldb(const struct dsdb_syntax_ctx *ctx,
906
             const struct dsdb_attribute *attr,
907
             const struct ldb_message_element *in)
908
0
{
909
0
  unsigned int i;
910
0
  WERROR status;
911
912
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
913
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
914
0
  }
915
916
0
  for (i=0; i < in->num_values; i++) {
917
0
    if (in->values[i].length == 0) {
918
0
      return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
919
0
    }
920
921
0
    status = dsdb_syntax_DATA_BLOB_validate_one_val(ctx,
922
0
                attr,
923
0
                &in->values[i]);
924
0
    if (!W_ERROR_IS_OK(status)) {
925
0
      return status;
926
0
    }
927
0
  }
928
929
0
  return WERR_OK;
930
0
}
931
932
static WERROR _dsdb_syntax_auto_OID_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
933
               const struct dsdb_attribute *attr,
934
               const struct drsuapi_DsReplicaAttribute *in,
935
               TALLOC_CTX *mem_ctx,
936
               struct ldb_message_element *out)
937
0
{
938
0
  unsigned int i;
939
940
0
  out->flags  = 0;
941
0
  out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
942
0
  W_ERROR_HAVE_NO_MEMORY(out->name);
943
944
0
  out->num_values = in->value_ctr.num_values;
945
0
  out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
946
0
  W_ERROR_HAVE_NO_MEMORY(out->values);
947
948
0
  for (i=0; i < out->num_values; i++) {
949
0
    uint32_t v;
950
0
    const struct dsdb_class *c;
951
0
    const struct dsdb_attribute *a;
952
0
    const char *str = NULL;
953
954
0
    if (in->value_ctr.values[i].blob == NULL) {
955
0
      return WERR_FOOBAR;
956
0
    }
957
958
0
    if (in->value_ctr.values[i].blob->length != 4) {
959
0
      return WERR_FOOBAR;
960
0
    }
961
962
0
    v = IVAL(in->value_ctr.values[i].blob->data, 0);
963
964
0
    if ((c = dsdb_class_by_governsID_id(ctx->schema, v))) {
965
0
      str = talloc_strdup(out->values, c->lDAPDisplayName);
966
0
    } else if ((a = dsdb_attribute_by_attributeID_id(ctx->schema, v))) {
967
0
      str = talloc_strdup(out->values, a->lDAPDisplayName);
968
0
    } else {
969
0
      WERROR werr;
970
0
      SMB_ASSERT(ctx->pfm_remote);
971
0
      werr = dsdb_schema_pfm_oid_from_attid(ctx->pfm_remote, v,
972
0
                    out->values, &str);
973
0
      W_ERROR_NOT_OK_RETURN(werr);
974
0
    }
975
0
    W_ERROR_HAVE_NO_MEMORY(str);
976
977
    /* the values need to be reversed */
978
0
    out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
979
0
  }
980
981
0
  return WERR_OK;
982
0
}
983
984
static WERROR _dsdb_syntax_OID_obj_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
985
              const struct dsdb_attribute *attr,
986
              const struct drsuapi_DsReplicaAttribute *in,
987
              TALLOC_CTX *mem_ctx,
988
              struct ldb_message_element *out)
989
0
{
990
0
  unsigned int i;
991
992
0
  out->flags  = 0;
993
0
  out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
994
0
  W_ERROR_HAVE_NO_MEMORY(out->name);
995
996
0
  out->num_values = in->value_ctr.num_values;
997
0
  out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
998
0
  W_ERROR_HAVE_NO_MEMORY(out->values);
999
1000
0
  for (i=0; i < out->num_values; i++) {
1001
0
    uint32_t v, vo;
1002
0
    const struct dsdb_class *c;
1003
0
    const char *str;
1004
1005
0
    if (in->value_ctr.values[i].blob == NULL) {
1006
0
      return WERR_FOOBAR;
1007
0
    }
1008
1009
0
    if (in->value_ctr.values[i].blob->length != 4) {
1010
0
      return WERR_FOOBAR;
1011
0
    }
1012
1013
0
    v = IVAL(in->value_ctr.values[i].blob->data, 0);
1014
0
    vo = v;
1015
1016
    /* convert remote ATTID to local ATTID */
1017
0
    if (!dsdb_syntax_attid_from_remote_attid(ctx, mem_ctx, v, &v)) {
1018
0
      DEBUG(1,(__location__ ": Failed to map remote ATTID to local ATTID!\n"));
1019
0
      return WERR_FOOBAR;
1020
0
    }
1021
1022
0
    c = dsdb_class_by_governsID_id(ctx->schema, v);
1023
0
    if (!c) {
1024
0
      int dbg_level = ctx->schema->resolving_in_progress ? 10 : 0;
1025
0
      DEBUG(dbg_level,(__location__ ": %s unknown local governsID 0x%08X remote 0x%08X%s\n",
1026
0
            attr->lDAPDisplayName, v, vo,
1027
0
            ctx->schema->resolving_in_progress ? "resolving in progress" : ""));
1028
0
      return WERR_DS_OBJ_CLASS_NOT_DEFINED;
1029
0
    }
1030
1031
0
    str = talloc_strdup(out->values, c->lDAPDisplayName);
1032
0
    W_ERROR_HAVE_NO_MEMORY(str);
1033
1034
    /* the values need to be reversed */
1035
0
    out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
1036
0
  }
1037
1038
0
  return WERR_OK;
1039
0
}
1040
1041
static WERROR _dsdb_syntax_OID_attr_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
1042
               const struct dsdb_attribute *attr,
1043
               const struct drsuapi_DsReplicaAttribute *in,
1044
               TALLOC_CTX *mem_ctx,
1045
               struct ldb_message_element *out)
1046
0
{
1047
0
  unsigned int i;
1048
1049
0
  out->flags  = 0;
1050
0
  out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1051
0
  W_ERROR_HAVE_NO_MEMORY(out->name);
1052
1053
0
  out->num_values = in->value_ctr.num_values;
1054
0
  out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1055
0
  W_ERROR_HAVE_NO_MEMORY(out->values);
1056
1057
0
  for (i=0; i < out->num_values; i++) {
1058
0
    uint32_t v, vo;
1059
0
    const struct dsdb_attribute *a;
1060
0
    const char *str;
1061
1062
0
    if (in->value_ctr.values[i].blob == NULL) {
1063
0
      DEBUG(0, ("Attribute has no value\n"));
1064
0
      return WERR_FOOBAR;
1065
0
    }
1066
1067
0
    if (in->value_ctr.values[i].blob->length != 4) {
1068
0
      DEBUG(0, ("Attribute has a value with 0 length\n"));
1069
0
      return WERR_FOOBAR;
1070
0
    }
1071
1072
0
    v = IVAL(in->value_ctr.values[i].blob->data, 0);
1073
0
    vo = v;
1074
1075
    /* convert remote ATTID to local ATTID */
1076
0
    if (!dsdb_syntax_attid_from_remote_attid(ctx, mem_ctx, v, &v)) {
1077
0
      DEBUG(1,(__location__ ": Failed to map remote ATTID to local ATTID!\n"));
1078
0
      return WERR_FOOBAR;
1079
0
    }
1080
1081
0
    a = dsdb_attribute_by_attributeID_id(ctx->schema, v);
1082
0
    if (!a) {
1083
0
      int dbg_level = ctx->schema->resolving_in_progress ? 10 : 0;
1084
0
      DEBUG(dbg_level,(__location__ ": %s unknown local attributeID_id 0x%08X remote 0x%08X%s\n",
1085
0
            attr->lDAPDisplayName, v, vo,
1086
0
            ctx->schema->resolving_in_progress ? "resolving in progress" : ""));
1087
0
      return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
1088
0
    }
1089
1090
0
    str = talloc_strdup(out->values, a->lDAPDisplayName);
1091
0
    W_ERROR_HAVE_NO_MEMORY(str);
1092
1093
    /* the values need to be reversed */
1094
0
    out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
1095
0
  }
1096
1097
0
  return WERR_OK;
1098
0
}
1099
1100
static WERROR _dsdb_syntax_OID_oid_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
1101
              const struct dsdb_attribute *attr,
1102
              const struct drsuapi_DsReplicaAttribute *in,
1103
              TALLOC_CTX *mem_ctx,
1104
              struct ldb_message_element *out)
1105
0
{
1106
0
  unsigned int i;
1107
0
  const struct dsdb_schema_prefixmap *prefixmap;
1108
1109
0
  if (ctx->pfm_remote != NULL) {
1110
0
    prefixmap = ctx->pfm_remote;
1111
0
  } else {
1112
0
    prefixmap = ctx->schema->prefixmap;
1113
0
  }
1114
0
  SMB_ASSERT(prefixmap);
1115
1116
0
  out->flags  = 0;
1117
0
  out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1118
0
  W_ERROR_HAVE_NO_MEMORY(out->name);
1119
1120
0
  out->num_values = in->value_ctr.num_values;
1121
0
  out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1122
0
  W_ERROR_HAVE_NO_MEMORY(out->values);
1123
1124
0
  for (i=0; i < out->num_values; i++) {
1125
0
    uint32_t attid;
1126
0
    WERROR status;
1127
0
    const char *oid;
1128
1129
0
    if (in->value_ctr.values[i].blob == NULL) {
1130
0
      return WERR_FOOBAR;
1131
0
    }
1132
1133
0
    if (in->value_ctr.values[i].blob->length != 4) {
1134
0
      return WERR_FOOBAR;
1135
0
    }
1136
1137
0
    attid = IVAL(in->value_ctr.values[i].blob->data, 0);
1138
1139
0
    status = dsdb_schema_pfm_oid_from_attid(prefixmap, attid,
1140
0
              out->values, &oid);
1141
0
    if (!W_ERROR_IS_OK(status)) {
1142
0
      DEBUG(0,(__location__ ": Error: Unknown ATTID 0x%08X\n",
1143
0
         attid));
1144
0
      return status;
1145
0
    }
1146
1147
0
    out->values[i] = data_blob_string_const(oid);
1148
0
  }
1149
1150
0
  return WERR_OK;
1151
0
}
1152
1153
static WERROR _dsdb_syntax_auto_OID_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1154
               const struct dsdb_attribute *attr,
1155
               const struct ldb_message_element *in,
1156
               TALLOC_CTX *mem_ctx,
1157
               struct drsuapi_DsReplicaAttribute *out)
1158
0
{
1159
0
        unsigned int i;
1160
0
        DATA_BLOB *blobs;
1161
1162
0
        out->attid= dsdb_attribute_get_attid(attr,
1163
0
               ctx->is_schema_nc);
1164
0
        out->value_ctr.num_values= in->num_values;
1165
0
        out->value_ctr.values= talloc_array(mem_ctx,
1166
0
                                            struct drsuapi_DsAttributeValue,
1167
0
                                            in->num_values);
1168
0
        W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1169
1170
0
        blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1171
0
        W_ERROR_HAVE_NO_MEMORY(blobs);
1172
1173
0
        for (i=0; i < in->num_values; i++) {
1174
0
    const struct dsdb_class *obj_class;
1175
0
    const struct dsdb_attribute *obj_attr;
1176
0
    struct ldb_val *v;
1177
1178
0
    out->value_ctr.values[i].blob= &blobs[i];
1179
1180
0
    blobs[i] = data_blob_talloc(blobs, NULL, 4);
1181
0
    W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1182
1183
    /* in DRS windows puts the classes in the opposite
1184
       order to the order used in ldap */
1185
0
    v = &in->values[(in->num_values-1)-i];
1186
1187
0
    if ((obj_class = dsdb_class_by_lDAPDisplayName_ldb_val(ctx->schema, v))) {
1188
0
      SIVAL(blobs[i].data, 0, obj_class->governsID_id);
1189
0
    } else if ((obj_attr = dsdb_attribute_by_lDAPDisplayName_ldb_val(ctx->schema, v))) {
1190
0
      SIVAL(blobs[i].data, 0, obj_attr->attributeID_id);
1191
0
    } else {
1192
0
      uint32_t attid;
1193
0
      WERROR werr;
1194
0
      werr = dsdb_schema_pfm_attid_from_oid(ctx->schema->prefixmap,
1195
0
                    (const char *)v->data,
1196
0
                    &attid);
1197
0
      W_ERROR_NOT_OK_RETURN(werr);
1198
0
      SIVAL(blobs[i].data, 0, attid);
1199
0
    }
1200
1201
0
        }
1202
1203
1204
0
        return WERR_OK;
1205
0
}
1206
1207
static WERROR _dsdb_syntax_OID_obj_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1208
              const struct dsdb_attribute *attr,
1209
              const struct ldb_message_element *in,
1210
              TALLOC_CTX *mem_ctx,
1211
              struct drsuapi_DsReplicaAttribute *out)
1212
0
{
1213
0
        unsigned int i;
1214
0
        DATA_BLOB *blobs;
1215
1216
0
        out->attid= dsdb_attribute_get_attid(attr,
1217
0
               ctx->is_schema_nc);
1218
0
        out->value_ctr.num_values= in->num_values;
1219
0
        out->value_ctr.values= talloc_array(mem_ctx,
1220
0
                                            struct drsuapi_DsAttributeValue,
1221
0
                                            in->num_values);
1222
0
        W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1223
1224
0
        blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1225
0
        W_ERROR_HAVE_NO_MEMORY(blobs);
1226
1227
0
        for (i=0; i < in->num_values; i++) {
1228
0
    const struct dsdb_class *obj_class;
1229
1230
0
    out->value_ctr.values[i].blob= &blobs[i];
1231
1232
0
    blobs[i] = data_blob_talloc(blobs, NULL, 4);
1233
0
    W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1234
1235
    /* in DRS windows puts the classes in the opposite
1236
       order to the order used in ldap */
1237
0
    obj_class = dsdb_class_by_lDAPDisplayName(ctx->schema,
1238
0
                (const char *)in->values[(in->num_values-1)-i].data);
1239
0
    if (!obj_class) {
1240
0
      return WERR_FOOBAR;
1241
0
    }
1242
0
    SIVAL(blobs[i].data, 0, obj_class->governsID_id);
1243
0
        }
1244
1245
1246
0
        return WERR_OK;
1247
0
}
1248
1249
static WERROR _dsdb_syntax_OID_attr_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1250
               const struct dsdb_attribute *attr,
1251
               const struct ldb_message_element *in,
1252
               TALLOC_CTX *mem_ctx,
1253
               struct drsuapi_DsReplicaAttribute *out)
1254
0
{
1255
0
        unsigned int i;
1256
0
        DATA_BLOB *blobs;
1257
1258
0
        out->attid= dsdb_attribute_get_attid(attr,
1259
0
               ctx->is_schema_nc);
1260
0
        out->value_ctr.num_values= in->num_values;
1261
0
        out->value_ctr.values= talloc_array(mem_ctx,
1262
0
                                            struct drsuapi_DsAttributeValue,
1263
0
                                            in->num_values);
1264
0
        W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1265
1266
0
        blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1267
0
        W_ERROR_HAVE_NO_MEMORY(blobs);
1268
1269
0
        for (i=0; i < in->num_values; i++) {
1270
0
    const struct dsdb_attribute *obj_attr;
1271
1272
0
    out->value_ctr.values[i].blob= &blobs[i];
1273
1274
0
    blobs[i] = data_blob_talloc(blobs, NULL, 4);
1275
0
    W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1276
1277
0
    obj_attr = dsdb_attribute_by_lDAPDisplayName(ctx->schema, (const char *)in->values[i].data);
1278
0
    if (!obj_attr) {
1279
0
      DEBUG(0, ("Unable to find attribute %s in the schema\n", (const char *)in->values[i].data));
1280
0
      return WERR_FOOBAR;
1281
0
    }
1282
0
    SIVAL(blobs[i].data, 0, obj_attr->attributeID_id);
1283
0
        }
1284
1285
1286
0
        return WERR_OK;
1287
0
}
1288
1289
static WERROR _dsdb_syntax_OID_oid_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1290
              const struct dsdb_attribute *attr,
1291
              const struct ldb_message_element *in,
1292
              TALLOC_CTX *mem_ctx,
1293
              struct drsuapi_DsReplicaAttribute *out)
1294
0
{
1295
0
  unsigned int i;
1296
0
  DATA_BLOB *blobs;
1297
1298
0
  out->attid= dsdb_attribute_get_attid(attr,
1299
0
               ctx->is_schema_nc);
1300
0
  out->value_ctr.num_values= in->num_values;
1301
0
  out->value_ctr.values= talloc_array(mem_ctx,
1302
0
              struct drsuapi_DsAttributeValue,
1303
0
              in->num_values);
1304
0
  W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1305
1306
0
  blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1307
0
  W_ERROR_HAVE_NO_MEMORY(blobs);
1308
1309
0
  for (i=0; i < in->num_values; i++) {
1310
0
    uint32_t attid;
1311
0
    WERROR status;
1312
1313
0
    out->value_ctr.values[i].blob= &blobs[i];
1314
1315
0
    blobs[i] = data_blob_talloc(blobs, NULL, 4);
1316
0
    W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1317
1318
0
    status = dsdb_schema_pfm_attid_from_oid(ctx->schema->prefixmap,
1319
0
                    (const char *)in->values[i].data,
1320
0
                    &attid);
1321
0
    W_ERROR_NOT_OK_RETURN(status);
1322
1323
0
    SIVAL(blobs[i].data, 0, attid);
1324
0
  }
1325
1326
0
  return WERR_OK;
1327
0
}
1328
1329
static WERROR dsdb_syntax_OID_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
1330
               const struct dsdb_attribute *attr,
1331
               const struct drsuapi_DsReplicaAttribute *in,
1332
               TALLOC_CTX *mem_ctx,
1333
               struct ldb_message_element *out)
1334
0
{
1335
0
  WERROR werr;
1336
1337
0
  switch (attr->attributeID_id) {
1338
0
  case DRSUAPI_ATTID_objectClass:
1339
0
  case DRSUAPI_ATTID_subClassOf:
1340
0
  case DRSUAPI_ATTID_auxiliaryClass:
1341
0
  case DRSUAPI_ATTID_systemAuxiliaryClass:
1342
0
  case DRSUAPI_ATTID_systemPossSuperiors:
1343
0
  case DRSUAPI_ATTID_possSuperiors:
1344
0
    werr = _dsdb_syntax_OID_obj_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
1345
0
    break;
1346
0
  case DRSUAPI_ATTID_systemMustContain:
1347
0
  case DRSUAPI_ATTID_systemMayContain:
1348
0
  case DRSUAPI_ATTID_mustContain:
1349
0
  case DRSUAPI_ATTID_rDNAttId:
1350
0
  case DRSUAPI_ATTID_transportAddressAttribute:
1351
0
  case DRSUAPI_ATTID_mayContain:
1352
0
    werr = _dsdb_syntax_OID_attr_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
1353
0
    break;
1354
0
  case DRSUAPI_ATTID_governsID:
1355
0
  case DRSUAPI_ATTID_attributeID:
1356
0
  case DRSUAPI_ATTID_attributeSyntax:
1357
0
    werr = _dsdb_syntax_OID_oid_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
1358
0
    break;
1359
0
  default:
1360
0
    DEBUG(0,(__location__ ": Unknown handling for attributeID_id for %s\n",
1361
0
       attr->lDAPDisplayName));
1362
0
    return _dsdb_syntax_auto_OID_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
1363
0
  }
1364
1365
  /* When we are doing the vampire of a schema, we don't want
1366
   * the inability to reference an OID to get in the way.
1367
   * Otherwise, we won't get the new schema with which to
1368
   * understand this */
1369
0
  if (!W_ERROR_IS_OK(werr) && ctx->schema->relax_OID_conversions) {
1370
0
    return _dsdb_syntax_OID_oid_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
1371
0
  }
1372
0
  return werr;
1373
0
}
1374
1375
static WERROR dsdb_syntax_OID_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1376
               const struct dsdb_attribute *attr,
1377
               const struct ldb_message_element *in,
1378
               TALLOC_CTX *mem_ctx,
1379
               struct drsuapi_DsReplicaAttribute *out)
1380
0
{
1381
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1382
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
1383
0
  }
1384
1385
0
  switch (attr->attributeID_id) {
1386
0
  case DRSUAPI_ATTID_objectClass:
1387
0
  case DRSUAPI_ATTID_subClassOf:
1388
0
  case DRSUAPI_ATTID_auxiliaryClass:
1389
0
  case DRSUAPI_ATTID_systemAuxiliaryClass:
1390
0
  case DRSUAPI_ATTID_systemPossSuperiors:
1391
0
  case DRSUAPI_ATTID_possSuperiors:
1392
0
    return _dsdb_syntax_OID_obj_ldb_to_drsuapi(ctx, attr, in, mem_ctx, out);
1393
0
  case DRSUAPI_ATTID_systemMustContain:
1394
0
  case DRSUAPI_ATTID_systemMayContain:
1395
0
  case DRSUAPI_ATTID_mustContain:
1396
0
  case DRSUAPI_ATTID_rDNAttId:
1397
0
  case DRSUAPI_ATTID_transportAddressAttribute:
1398
0
  case DRSUAPI_ATTID_mayContain:
1399
0
    return _dsdb_syntax_OID_attr_ldb_to_drsuapi(ctx, attr, in, mem_ctx, out);
1400
0
  case DRSUAPI_ATTID_governsID:
1401
0
  case DRSUAPI_ATTID_attributeID:
1402
0
  case DRSUAPI_ATTID_attributeSyntax:
1403
0
    return _dsdb_syntax_OID_oid_ldb_to_drsuapi(ctx, attr, in, mem_ctx, out);
1404
0
  }
1405
1406
0
  DEBUG(0,(__location__ ": Unknown handling for attributeID_id for %s\n",
1407
0
     attr->lDAPDisplayName));
1408
1409
0
  return _dsdb_syntax_auto_OID_ldb_to_drsuapi(ctx, attr, in, mem_ctx, out);
1410
0
}
1411
1412
static WERROR _dsdb_syntax_OID_validate_numericoid(const struct dsdb_syntax_ctx *ctx,
1413
               const struct dsdb_attribute *attr,
1414
               const struct ldb_message_element *in)
1415
0
{
1416
0
  unsigned int i;
1417
0
  TALLOC_CTX *tmp_ctx;
1418
1419
0
  tmp_ctx = talloc_new(ctx->ldb);
1420
0
  W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1421
1422
0
  for (i=0; i < in->num_values; i++) {
1423
0
    DATA_BLOB blob;
1424
0
    char *oid_out;
1425
0
    const char *oid = (const char*)in->values[i].data;
1426
1427
0
    if (in->values[i].length == 0) {
1428
0
      talloc_free(tmp_ctx);
1429
0
      return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1430
0
    }
1431
1432
0
    if (!ber_write_OID_String(tmp_ctx, &blob, oid)) {
1433
0
      DEBUG(0,("ber_write_OID_String() failed for %s\n", oid));
1434
0
      talloc_free(tmp_ctx);
1435
0
      return WERR_INVALID_PARAMETER;
1436
0
    }
1437
1438
0
    if (!ber_read_OID_String(tmp_ctx, blob, &oid_out)) {
1439
0
      DEBUG(0,("ber_read_OID_String() failed for %s\n",
1440
0
         hex_encode_talloc(tmp_ctx, blob.data, blob.length)));
1441
0
      talloc_free(tmp_ctx);
1442
0
      return WERR_INVALID_PARAMETER;
1443
0
    }
1444
1445
0
    if (strcmp(oid, oid_out) != 0) {
1446
0
      talloc_free(tmp_ctx);
1447
0
      return WERR_INVALID_PARAMETER;
1448
0
    }
1449
0
  }
1450
1451
0
  talloc_free(tmp_ctx);
1452
0
  return WERR_OK;
1453
0
}
1454
1455
static WERROR dsdb_syntax_OID_validate_ldb(const struct dsdb_syntax_ctx *ctx,
1456
             const struct dsdb_attribute *attr,
1457
             const struct ldb_message_element *in)
1458
0
{
1459
0
  WERROR status;
1460
0
  struct drsuapi_DsReplicaAttribute drs_tmp;
1461
0
  struct ldb_message_element ldb_tmp;
1462
0
  TALLOC_CTX *tmp_ctx;
1463
1464
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1465
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
1466
0
  }
1467
1468
0
  switch (attr->attributeID_id) {
1469
0
  case DRSUAPI_ATTID_governsID:
1470
0
  case DRSUAPI_ATTID_attributeID:
1471
0
  case DRSUAPI_ATTID_attributeSyntax:
1472
0
    return _dsdb_syntax_OID_validate_numericoid(ctx, attr, in);
1473
0
  }
1474
1475
  /*
1476
   * TODO: optimize and verify this code
1477
   */
1478
1479
0
  tmp_ctx = talloc_new(ctx->ldb);
1480
0
  W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1481
1482
0
  status = dsdb_syntax_OID_ldb_to_drsuapi(ctx,
1483
0
            attr,
1484
0
            in,
1485
0
            tmp_ctx,
1486
0
            &drs_tmp);
1487
0
  if (!W_ERROR_IS_OK(status)) {
1488
0
    talloc_free(tmp_ctx);
1489
0
    return status;
1490
0
  }
1491
1492
0
  status = dsdb_syntax_OID_drsuapi_to_ldb(ctx,
1493
0
            attr,
1494
0
            &drs_tmp,
1495
0
            tmp_ctx,
1496
0
            &ldb_tmp);
1497
0
  if (!W_ERROR_IS_OK(status)) {
1498
0
    talloc_free(tmp_ctx);
1499
0
    return status;
1500
0
  }
1501
1502
0
  talloc_free(tmp_ctx);
1503
0
  return WERR_OK;
1504
0
}
1505
1506
static WERROR dsdb_syntax_UNICODE_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
1507
             const struct dsdb_attribute *attr,
1508
             const struct drsuapi_DsReplicaAttribute *in,
1509
             TALLOC_CTX *mem_ctx,
1510
             struct ldb_message_element *out)
1511
0
{
1512
0
  unsigned int i;
1513
1514
0
  out->flags  = 0;
1515
0
  out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1516
0
  W_ERROR_HAVE_NO_MEMORY(out->name);
1517
1518
0
  out->num_values = in->value_ctr.num_values;
1519
0
  out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1520
0
  W_ERROR_HAVE_NO_MEMORY(out->values);
1521
1522
0
  for (i=0; i < out->num_values; i++) {
1523
0
    size_t converted_size = 0;
1524
0
    char *str;
1525
1526
0
    if (in->value_ctr.values[i].blob == NULL) {
1527
0
      return WERR_FOOBAR;
1528
0
    }
1529
1530
0
    if (in->value_ctr.values[i].blob->length == 0) {
1531
0
      return WERR_FOOBAR;
1532
0
    }
1533
1534
0
    if (!convert_string_talloc(out->values,
1535
0
             CH_UTF16, CH_UNIX,
1536
0
             in->value_ctr.values[i].blob->data,
1537
0
             in->value_ctr.values[i].blob->length,
1538
0
             &str, &converted_size)) {
1539
0
      return WERR_FOOBAR;
1540
0
    }
1541
1542
0
    out->values[i] = data_blob_const(str, converted_size);
1543
0
  }
1544
1545
0
  return WERR_OK;
1546
0
}
1547
1548
static WERROR dsdb_syntax_UNICODE_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1549
             const struct dsdb_attribute *attr,
1550
             const struct ldb_message_element *in,
1551
             TALLOC_CTX *mem_ctx,
1552
             struct drsuapi_DsReplicaAttribute *out)
1553
0
{
1554
0
  unsigned int i;
1555
0
  DATA_BLOB *blobs;
1556
1557
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1558
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
1559
0
  }
1560
1561
0
  out->attid      = dsdb_attribute_get_attid(attr,
1562
0
                   ctx->is_schema_nc);
1563
0
  out->value_ctr.num_values = in->num_values;
1564
0
  out->value_ctr.values   = talloc_array(mem_ctx,
1565
0
                   struct drsuapi_DsAttributeValue,
1566
0
                   in->num_values);
1567
0
  W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1568
1569
0
  blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1570
0
  W_ERROR_HAVE_NO_MEMORY(blobs);
1571
1572
0
  for (i=0; i < in->num_values; i++) {
1573
0
    out->value_ctr.values[i].blob = &blobs[i];
1574
1575
0
    if (!convert_string_talloc(blobs,
1576
0
             CH_UNIX, CH_UTF16,
1577
0
             in->values[i].data, in->values[i].length,
1578
0
             &blobs[i].data, &blobs[i].length)) {
1579
0
      return WERR_FOOBAR;
1580
0
    }
1581
0
  }
1582
1583
0
  return WERR_OK;
1584
0
}
1585
1586
static WERROR dsdb_syntax_UNICODE_validate_one_val(const struct dsdb_syntax_ctx *ctx,
1587
               const struct dsdb_attribute *attr,
1588
               const struct ldb_val *val)
1589
0
{
1590
0
  void *dst = NULL;
1591
0
  size_t size;
1592
0
  bool ok;
1593
1594
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1595
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
1596
0
  }
1597
1598
0
  ok = convert_string_talloc(ctx->ldb,
1599
0
           CH_UNIX, CH_UTF16,
1600
0
           val->data,
1601
0
           val->length,
1602
0
           &dst,
1603
0
           &size);
1604
0
  TALLOC_FREE(dst);
1605
0
  if (!ok) {
1606
0
    return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1607
0
  }
1608
1609
0
  if (attr->rangeLower) {
1610
0
    if ((size/2) < *attr->rangeLower) {
1611
0
      return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1612
0
    }
1613
0
  }
1614
1615
0
  if (attr->rangeUpper) {
1616
0
    if ((size/2) > *attr->rangeUpper) {
1617
0
      return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1618
0
    }
1619
0
  }
1620
1621
0
  return WERR_OK;
1622
0
}
1623
1624
static WERROR dsdb_syntax_UNICODE_validate_ldb(const struct dsdb_syntax_ctx *ctx,
1625
                 const struct dsdb_attribute *attr,
1626
                 const struct ldb_message_element *in)
1627
0
{
1628
0
  WERROR status;
1629
0
  unsigned int i;
1630
1631
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1632
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
1633
0
  }
1634
1635
0
  for (i=0; i < in->num_values; i++) {
1636
0
    if (in->values[i].length == 0) {
1637
0
      return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1638
0
    }
1639
1640
0
    status = dsdb_syntax_UNICODE_validate_one_val(ctx,
1641
0
                    attr,
1642
0
                    &in->values[i]);
1643
0
    if (!W_ERROR_IS_OK(status)) {
1644
0
      return status;
1645
0
    }
1646
0
  }
1647
1648
0
  return WERR_OK;
1649
0
}
1650
1651
static WERROR dsdb_syntax_one_DN_drsuapi_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
1652
            const struct dsdb_syntax *syntax,
1653
            const DATA_BLOB *in, DATA_BLOB *out)
1654
0
{
1655
0
  struct drsuapi_DsReplicaObjectIdentifier3 id3;
1656
0
  enum ndr_err_code ndr_err;
1657
0
  DATA_BLOB guid_blob;
1658
0
  struct ldb_dn *dn;
1659
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1660
0
  int ret;
1661
0
  NTSTATUS status;
1662
1663
0
  if (!tmp_ctx) {
1664
0
    W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1665
0
  }
1666
1667
0
  if (in == NULL) {
1668
0
    talloc_free(tmp_ctx);
1669
0
    return WERR_FOOBAR;
1670
0
  }
1671
1672
0
  if (in->length == 0) {
1673
0
    talloc_free(tmp_ctx);
1674
0
    return WERR_FOOBAR;
1675
0
  }
1676
1677
1678
  /* windows sometimes sends an extra two pad bytes here */
1679
0
  ndr_err = ndr_pull_struct_blob(in,
1680
0
               tmp_ctx, &id3,
1681
0
               (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3);
1682
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1683
0
    status = ndr_map_error2ntstatus(ndr_err);
1684
0
    talloc_free(tmp_ctx);
1685
0
    return ntstatus_to_werror(status);
1686
0
  }
1687
1688
0
  dn = ldb_dn_new(tmp_ctx, ldb, id3.dn);
1689
0
  if (!dn) {
1690
0
    talloc_free(tmp_ctx);
1691
    /* If this fails, it must be out of memory, as it does not do much parsing */
1692
0
    W_ERROR_HAVE_NO_MEMORY(dn);
1693
0
  }
1694
1695
0
  if (!GUID_all_zero(&id3.guid)) {
1696
0
    status = GUID_to_ndr_blob(&id3.guid, tmp_ctx, &guid_blob);
1697
0
    if (!NT_STATUS_IS_OK(status)) {
1698
0
      talloc_free(tmp_ctx);
1699
0
      return ntstatus_to_werror(status);
1700
0
    }
1701
1702
0
    ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
1703
0
    if (ret != LDB_SUCCESS) {
1704
0
      talloc_free(tmp_ctx);
1705
0
      return WERR_FOOBAR;
1706
0
    }
1707
0
    talloc_free(guid_blob.data);
1708
0
  }
1709
1710
0
  if (id3.__ndr_size_sid) {
1711
0
    DATA_BLOB sid_blob;
1712
0
    ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, &id3.sid,
1713
0
                 (ndr_push_flags_fn_t)ndr_push_dom_sid);
1714
0
    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1715
0
      status = ndr_map_error2ntstatus(ndr_err);
1716
0
      talloc_free(tmp_ctx);
1717
0
      return ntstatus_to_werror(status);
1718
0
    }
1719
1720
0
    ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
1721
0
    if (ret != LDB_SUCCESS) {
1722
0
      talloc_free(tmp_ctx);
1723
0
      return WERR_FOOBAR;
1724
0
    }
1725
0
  }
1726
1727
0
  *out = data_blob_string_const(ldb_dn_get_extended_linearized(mem_ctx, dn, 1));
1728
0
  talloc_free(tmp_ctx);
1729
0
  W_ERROR_HAVE_NO_MEMORY(out->data);
1730
0
  return WERR_OK;
1731
0
}
1732
1733
static WERROR dsdb_syntax_DN_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
1734
              const struct dsdb_attribute *attr,
1735
              const struct drsuapi_DsReplicaAttribute *in,
1736
              TALLOC_CTX *mem_ctx,
1737
              struct ldb_message_element *out)
1738
0
{
1739
0
  unsigned int i;
1740
1741
0
  out->flags  = 0;
1742
0
  out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1743
0
  W_ERROR_HAVE_NO_MEMORY(out->name);
1744
1745
0
  out->num_values = in->value_ctr.num_values;
1746
0
  out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1747
0
  W_ERROR_HAVE_NO_MEMORY(out->values);
1748
1749
0
  for (i=0; i < out->num_values; i++) {
1750
0
    WERROR status = dsdb_syntax_one_DN_drsuapi_to_ldb(out->values, ctx->ldb, attr->syntax,
1751
0
                  in->value_ctr.values[i].blob,
1752
0
                  &out->values[i]);
1753
0
    if (!W_ERROR_IS_OK(status)) {
1754
0
      return status;
1755
0
    }
1756
1757
0
  }
1758
1759
0
  return WERR_OK;
1760
0
}
1761
1762
static WERROR dsdb_syntax_DN_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1763
              const struct dsdb_attribute *attr,
1764
              const struct ldb_message_element *in,
1765
              TALLOC_CTX *mem_ctx,
1766
              struct drsuapi_DsReplicaAttribute *out)
1767
0
{
1768
0
  unsigned int i;
1769
0
  DATA_BLOB *blobs;
1770
1771
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1772
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
1773
0
  }
1774
1775
0
  out->attid      = dsdb_attribute_get_attid(attr,
1776
0
                   ctx->is_schema_nc);
1777
0
  out->value_ctr.num_values = in->num_values;
1778
0
  out->value_ctr.values   = talloc_array(mem_ctx,
1779
0
                   struct drsuapi_DsAttributeValue,
1780
0
                   in->num_values);
1781
0
  W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1782
1783
0
  blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1784
0
  W_ERROR_HAVE_NO_MEMORY(blobs);
1785
1786
0
  for (i=0; i < in->num_values; i++) {
1787
0
    struct drsuapi_DsReplicaObjectIdentifier3 id3;
1788
0
    enum ndr_err_code ndr_err;
1789
0
    struct ldb_dn *dn;
1790
0
    TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1791
0
    NTSTATUS status;
1792
1793
0
    W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1794
1795
0
    out->value_ctr.values[i].blob = &blobs[i];
1796
1797
0
    dn = ldb_dn_from_ldb_val(tmp_ctx, ctx->ldb, &in->values[i]);
1798
1799
0
    W_ERROR_HAVE_NO_MEMORY(dn);
1800
1801
0
    ZERO_STRUCT(id3);
1802
1803
0
    status = dsdb_get_extended_dn_guid(dn, &id3.guid, "GUID");
1804
0
    if (!NT_STATUS_IS_OK(status) &&
1805
0
        !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1806
0
      talloc_free(tmp_ctx);
1807
0
      return ntstatus_to_werror(status);
1808
0
    }
1809
1810
0
    status = dsdb_get_extended_dn_sid(dn, &id3.sid, "SID");
1811
0
    if (!NT_STATUS_IS_OK(status) &&
1812
0
        !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1813
0
      talloc_free(tmp_ctx);
1814
0
      return ntstatus_to_werror(status);
1815
0
    }
1816
1817
0
    id3.dn = ldb_dn_get_linearized(dn);
1818
1819
0
    ndr_err = ndr_push_struct_blob(&blobs[i], blobs, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
1820
0
    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1821
0
      status = ndr_map_error2ntstatus(ndr_err);
1822
0
      talloc_free(tmp_ctx);
1823
0
      return ntstatus_to_werror(status);
1824
0
    }
1825
0
    talloc_free(tmp_ctx);
1826
0
  }
1827
1828
0
  return WERR_OK;
1829
0
}
1830
1831
static WERROR dsdb_syntax_DN_validate_one_val(const struct dsdb_syntax_ctx *ctx,
1832
                const struct dsdb_attribute *attr,
1833
                const struct ldb_val *val,
1834
                TALLOC_CTX *mem_ctx,
1835
                struct dsdb_dn **_dsdb_dn)
1836
0
{
1837
0
  static const char * const extended_list[] = { "GUID", "SID", NULL };
1838
0
  enum ndr_err_code ndr_err;
1839
0
  struct GUID guid;
1840
0
  struct dom_sid sid;
1841
0
  const DATA_BLOB *sid_blob;
1842
0
  struct dsdb_dn *dsdb_dn;
1843
0
  struct ldb_dn *dn;
1844
0
  char *dn_str;
1845
0
  struct ldb_dn *dn2;
1846
0
  char *dn2_str;
1847
0
  int num_components;
1848
0
  TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1849
0
  NTSTATUS status;
1850
1851
0
  W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1852
1853
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1854
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
1855
0
  }
1856
1857
0
  dsdb_dn = dsdb_dn_parse(tmp_ctx, ctx->ldb, val,
1858
0
        attr->syntax->ldap_oid);
1859
0
  if (!dsdb_dn) {
1860
0
    talloc_free(tmp_ctx);
1861
0
    return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1862
0
  }
1863
0
  dn = dsdb_dn->dn;
1864
1865
0
  dn2 = ldb_dn_copy(tmp_ctx, dn);
1866
0
  if (dn == NULL) {
1867
0
    talloc_free(tmp_ctx);
1868
0
    return WERR_NOT_ENOUGH_MEMORY;
1869
0
  }
1870
1871
0
  num_components = ldb_dn_get_comp_num(dn);
1872
1873
0
  status = dsdb_get_extended_dn_guid(dn, &guid, "GUID");
1874
0
  if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1875
0
    num_components++;
1876
0
  } else if (!NT_STATUS_IS_OK(status)) {
1877
0
    talloc_free(tmp_ctx);
1878
0
    return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1879
0
  }
1880
1881
0
  sid_blob = ldb_dn_get_extended_component(dn, "SID");
1882
0
  if (sid_blob) {
1883
0
    num_components++;
1884
0
    ndr_err = ndr_pull_struct_blob_all(sid_blob,
1885
0
               tmp_ctx,
1886
0
               &sid,
1887
0
               (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1888
0
    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1889
0
      talloc_free(tmp_ctx);
1890
0
      return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1891
0
    }
1892
0
  }
1893
1894
  /* Do not allow links to the RootDSE */
1895
0
  if (num_components == 0) {
1896
0
    talloc_free(tmp_ctx);
1897
0
    return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1898
0
  }
1899
1900
  /*
1901
   * We need to check that only "GUID" and "SID" are
1902
   * specified as extended components, we do that
1903
   * by comparing the dn's after removing all components
1904
   * from one dn and only the allowed subset from the other
1905
   * one.
1906
   */
1907
0
  ldb_dn_extended_filter(dn, extended_list);
1908
1909
0
  dn_str = ldb_dn_get_extended_linearized(tmp_ctx, dn, 0);
1910
0
  if (dn_str == NULL) {
1911
0
    talloc_free(tmp_ctx);
1912
0
    return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1913
0
  }
1914
0
  dn2_str = ldb_dn_get_extended_linearized(tmp_ctx, dn2, 0);
1915
0
  if (dn2_str == NULL) {
1916
0
    talloc_free(tmp_ctx);
1917
0
    return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1918
0
  }
1919
1920
0
  if (strcmp(dn_str, dn2_str) != 0) {
1921
0
    talloc_free(tmp_ctx);
1922
0
    return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1923
0
  }
1924
1925
0
  *_dsdb_dn = talloc_move(mem_ctx, &dsdb_dn);
1926
0
  talloc_free(tmp_ctx);
1927
0
  return WERR_OK;
1928
0
}
1929
1930
static WERROR dsdb_syntax_DN_validate_ldb(const struct dsdb_syntax_ctx *ctx,
1931
            const struct dsdb_attribute *attr,
1932
            const struct ldb_message_element *in)
1933
0
{
1934
0
  unsigned int i;
1935
1936
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1937
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
1938
0
  }
1939
1940
0
  for (i=0; i < in->num_values; i++) {
1941
0
    WERROR status;
1942
0
    struct dsdb_dn *dsdb_dn;
1943
0
    TALLOC_CTX *tmp_ctx = talloc_new(ctx->ldb);
1944
0
    W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1945
1946
0
    status = dsdb_syntax_DN_validate_one_val(ctx,
1947
0
               attr,
1948
0
               &in->values[i],
1949
0
               tmp_ctx, &dsdb_dn);
1950
0
    if (!W_ERROR_IS_OK(status)) {
1951
0
      talloc_free(tmp_ctx);
1952
0
      return status;
1953
0
    }
1954
1955
0
    if (dsdb_dn->dn_format != DSDB_NORMAL_DN) {
1956
0
      talloc_free(tmp_ctx);
1957
0
      return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1958
0
    }
1959
1960
0
    talloc_free(tmp_ctx);
1961
0
  }
1962
1963
0
  return WERR_OK;
1964
0
}
1965
1966
static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
1967
               const struct dsdb_attribute *attr,
1968
               const struct drsuapi_DsReplicaAttribute *in,
1969
               TALLOC_CTX *mem_ctx,
1970
               struct ldb_message_element *out)
1971
0
{
1972
0
  unsigned int i;
1973
0
  int ret;
1974
1975
0
  out->flags  = 0;
1976
0
  out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1977
0
  W_ERROR_HAVE_NO_MEMORY(out->name);
1978
1979
0
  out->num_values = in->value_ctr.num_values;
1980
0
  out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1981
0
  W_ERROR_HAVE_NO_MEMORY(out->values);
1982
1983
0
  for (i=0; i < out->num_values; i++) {
1984
0
    struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
1985
0
    enum ndr_err_code ndr_err;
1986
0
    DATA_BLOB guid_blob;
1987
0
    struct ldb_dn *dn;
1988
0
    struct dsdb_dn *dsdb_dn;
1989
0
    NTSTATUS status;
1990
0
    TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1991
0
    if (!tmp_ctx) {
1992
0
      W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1993
0
    }
1994
1995
0
    if (in->value_ctr.values[i].blob == NULL) {
1996
0
      talloc_free(tmp_ctx);
1997
0
      return WERR_FOOBAR;
1998
0
    }
1999
2000
0
    if (in->value_ctr.values[i].blob->length == 0) {
2001
0
      talloc_free(tmp_ctx);
2002
0
      return WERR_FOOBAR;
2003
0
    }
2004
2005
2006
    /* windows sometimes sends an extra two pad bytes here */
2007
0
    ndr_err = ndr_pull_struct_blob(in->value_ctr.values[i].blob,
2008
0
                 tmp_ctx, &id3,
2009
0
                 (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3Binary);
2010
0
    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2011
0
      status = ndr_map_error2ntstatus(ndr_err);
2012
0
      talloc_free(tmp_ctx);
2013
0
      return ntstatus_to_werror(status);
2014
0
    }
2015
2016
0
    dn = ldb_dn_new(tmp_ctx, ctx->ldb, id3.dn);
2017
0
    if (!dn) {
2018
0
      talloc_free(tmp_ctx);
2019
      /* If this fails, it must be out of memory, as it does not do much parsing */
2020
0
      W_ERROR_HAVE_NO_MEMORY(dn);
2021
0
    }
2022
2023
0
    if (!GUID_all_zero(&id3.guid)) {
2024
0
      status = GUID_to_ndr_blob(&id3.guid, tmp_ctx, &guid_blob);
2025
0
      if (!NT_STATUS_IS_OK(status)) {
2026
0
        talloc_free(tmp_ctx);
2027
0
        return ntstatus_to_werror(status);
2028
0
      }
2029
2030
0
      ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
2031
0
      if (ret != LDB_SUCCESS) {
2032
0
        talloc_free(tmp_ctx);
2033
0
        return WERR_FOOBAR;
2034
0
      }
2035
0
      talloc_free(guid_blob.data);
2036
0
    }
2037
2038
0
    if (id3.__ndr_size_sid) {
2039
0
      DATA_BLOB sid_blob;
2040
0
      ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, &id3.sid,
2041
0
                   (ndr_push_flags_fn_t)ndr_push_dom_sid);
2042
0
      if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2043
0
        status = ndr_map_error2ntstatus(ndr_err);
2044
0
        talloc_free(tmp_ctx);
2045
0
        return ntstatus_to_werror(status);
2046
0
      }
2047
2048
0
      ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
2049
0
      if (ret != LDB_SUCCESS) {
2050
0
        talloc_free(tmp_ctx);
2051
0
        return WERR_FOOBAR;
2052
0
      }
2053
0
    }
2054
2055
    /* set binary stuff */
2056
0
    dsdb_dn = dsdb_dn_construct(tmp_ctx, dn, id3.binary, attr->syntax->ldap_oid);
2057
0
    if (!dsdb_dn) {
2058
0
      if (errno == EINVAL) {
2059
        /*
2060
         * This might be Object(OR-Name)
2061
         * failing because of a non empty
2062
         * binary part.
2063
         */
2064
0
        talloc_free(tmp_ctx);
2065
0
        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
2066
0
      }
2067
0
      talloc_free(tmp_ctx);
2068
0
      W_ERROR_HAVE_NO_MEMORY(dsdb_dn);
2069
0
    }
2070
0
    out->values[i] = data_blob_string_const(dsdb_dn_get_extended_linearized(out->values, dsdb_dn, 1));
2071
0
    talloc_free(tmp_ctx);
2072
0
    W_ERROR_HAVE_NO_MEMORY(out->values[i].data);
2073
0
  }
2074
2075
0
  return WERR_OK;
2076
0
}
2077
2078
static WERROR dsdb_syntax_DN_BINARY_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
2079
               const struct dsdb_attribute *attr,
2080
               const struct ldb_message_element *in,
2081
               TALLOC_CTX *mem_ctx,
2082
               struct drsuapi_DsReplicaAttribute *out)
2083
0
{
2084
0
  unsigned int i;
2085
0
  DATA_BLOB *blobs;
2086
2087
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
2088
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
2089
0
  }
2090
2091
0
  out->attid      = dsdb_attribute_get_attid(attr,
2092
0
                   ctx->is_schema_nc);
2093
0
  out->value_ctr.num_values = in->num_values;
2094
0
  out->value_ctr.values   = talloc_array(mem_ctx,
2095
0
                   struct drsuapi_DsAttributeValue,
2096
0
                   in->num_values);
2097
0
  W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
2098
2099
0
  blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
2100
0
  W_ERROR_HAVE_NO_MEMORY(blobs);
2101
2102
0
  for (i=0; i < in->num_values; i++) {
2103
0
    struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
2104
0
    enum ndr_err_code ndr_err;
2105
0
    const DATA_BLOB *sid_blob;
2106
0
    struct dsdb_dn *dsdb_dn;
2107
0
    TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
2108
0
    NTSTATUS status;
2109
2110
0
    W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
2111
2112
0
    out->value_ctr.values[i].blob = &blobs[i];
2113
2114
0
    dsdb_dn = dsdb_dn_parse(tmp_ctx, ctx->ldb, &in->values[i], attr->syntax->ldap_oid);
2115
2116
0
    if (!dsdb_dn) {
2117
0
      talloc_free(tmp_ctx);
2118
0
      return ntstatus_to_werror(NT_STATUS_INVALID_PARAMETER);
2119
0
    }
2120
2121
0
    ZERO_STRUCT(id3);
2122
2123
0
    status = dsdb_get_extended_dn_guid(dsdb_dn->dn, &id3.guid, "GUID");
2124
0
    if (!NT_STATUS_IS_OK(status) &&
2125
0
        !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2126
0
      talloc_free(tmp_ctx);
2127
0
      return ntstatus_to_werror(status);
2128
0
    }
2129
2130
0
    sid_blob = ldb_dn_get_extended_component(dsdb_dn->dn, "SID");
2131
0
    if (sid_blob) {
2132
2133
0
      ndr_err = ndr_pull_struct_blob_all(sid_blob,
2134
0
                 tmp_ctx, &id3.sid,
2135
0
                 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
2136
0
      if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2137
0
        status = ndr_map_error2ntstatus(ndr_err);
2138
0
        talloc_free(tmp_ctx);
2139
0
        return ntstatus_to_werror(status);
2140
0
      }
2141
0
    }
2142
2143
0
    id3.dn = ldb_dn_get_linearized(dsdb_dn->dn);
2144
2145
    /* get binary stuff */
2146
0
    id3.binary = dsdb_dn->extra_part;
2147
2148
0
    ndr_err = ndr_push_struct_blob(&blobs[i], blobs, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3Binary);
2149
0
    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2150
0
      status = ndr_map_error2ntstatus(ndr_err);
2151
0
      talloc_free(tmp_ctx);
2152
0
      return ntstatus_to_werror(status);
2153
0
    }
2154
0
    talloc_free(tmp_ctx);
2155
0
  }
2156
2157
0
  return WERR_OK;
2158
0
}
2159
2160
static WERROR dsdb_syntax_DN_BINARY_validate_ldb(const struct dsdb_syntax_ctx *ctx,
2161
             const struct dsdb_attribute *attr,
2162
             const struct ldb_message_element *in)
2163
0
{
2164
0
  unsigned int i;
2165
2166
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
2167
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
2168
0
  }
2169
2170
0
  for (i=0; i < in->num_values; i++) {
2171
0
    WERROR status;
2172
0
    struct dsdb_dn *dsdb_dn;
2173
0
    TALLOC_CTX *tmp_ctx = talloc_new(ctx->ldb);
2174
0
    W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
2175
2176
0
    status = dsdb_syntax_DN_validate_one_val(ctx,
2177
0
               attr,
2178
0
               &in->values[i],
2179
0
               tmp_ctx, &dsdb_dn);
2180
0
    if (!W_ERROR_IS_OK(status)) {
2181
0
      talloc_free(tmp_ctx);
2182
0
      return status;
2183
0
    }
2184
2185
0
    if (dsdb_dn->dn_format != DSDB_BINARY_DN) {
2186
0
      talloc_free(tmp_ctx);
2187
0
      return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
2188
0
    }
2189
2190
0
    status = dsdb_syntax_DATA_BLOB_validate_one_val(ctx,
2191
0
                attr,
2192
0
                &dsdb_dn->extra_part);
2193
0
    if (!W_ERROR_IS_OK(status)) {
2194
0
      talloc_free(tmp_ctx);
2195
0
      return status;
2196
0
    }
2197
2198
0
    talloc_free(tmp_ctx);
2199
0
  }
2200
2201
0
  return WERR_OK;
2202
0
}
2203
2204
static WERROR dsdb_syntax_DN_STRING_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
2205
               const struct dsdb_attribute *attr,
2206
               const struct drsuapi_DsReplicaAttribute *in,
2207
               TALLOC_CTX *mem_ctx,
2208
               struct ldb_message_element *out)
2209
0
{
2210
0
  return dsdb_syntax_DN_BINARY_drsuapi_to_ldb(ctx,
2211
0
                attr,
2212
0
                in,
2213
0
                mem_ctx,
2214
0
                out);
2215
0
}
2216
2217
static WERROR dsdb_syntax_DN_STRING_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
2218
               const struct dsdb_attribute *attr,
2219
               const struct ldb_message_element *in,
2220
               TALLOC_CTX *mem_ctx,
2221
               struct drsuapi_DsReplicaAttribute *out)
2222
0
{
2223
0
  return dsdb_syntax_DN_BINARY_ldb_to_drsuapi(ctx,
2224
0
                attr,
2225
0
                in,
2226
0
                mem_ctx,
2227
0
                out);
2228
0
}
2229
2230
static WERROR dsdb_syntax_DN_STRING_validate_ldb(const struct dsdb_syntax_ctx *ctx,
2231
             const struct dsdb_attribute *attr,
2232
             const struct ldb_message_element *in)
2233
0
{
2234
0
  unsigned int i;
2235
2236
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
2237
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
2238
0
  }
2239
2240
0
  for (i=0; i < in->num_values; i++) {
2241
0
    WERROR status;
2242
0
    struct dsdb_dn *dsdb_dn;
2243
0
    TALLOC_CTX *tmp_ctx = talloc_new(ctx->ldb);
2244
0
    W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
2245
2246
0
    status = dsdb_syntax_DN_validate_one_val(ctx,
2247
0
               attr,
2248
0
               &in->values[i],
2249
0
               tmp_ctx, &dsdb_dn);
2250
0
    if (!W_ERROR_IS_OK(status)) {
2251
0
      talloc_free(tmp_ctx);
2252
0
      return status;
2253
0
    }
2254
2255
0
    if (dsdb_dn->dn_format != DSDB_STRING_DN) {
2256
0
      talloc_free(tmp_ctx);
2257
0
      return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
2258
0
    }
2259
2260
0
    status = dsdb_syntax_UNICODE_validate_one_val(ctx,
2261
0
                    attr,
2262
0
                    &dsdb_dn->extra_part);
2263
0
    if (!W_ERROR_IS_OK(status)) {
2264
0
      talloc_free(tmp_ctx);
2265
0
      return status;
2266
0
    }
2267
2268
0
    talloc_free(tmp_ctx);
2269
0
  }
2270
2271
0
  return WERR_OK;
2272
0
}
2273
2274
static WERROR dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
2275
                    const struct dsdb_attribute *attr,
2276
                    const struct drsuapi_DsReplicaAttribute *in,
2277
                    TALLOC_CTX *mem_ctx,
2278
                    struct ldb_message_element *out)
2279
0
{
2280
0
  unsigned int i;
2281
2282
0
  out->flags  = 0;
2283
0
  out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
2284
0
  W_ERROR_HAVE_NO_MEMORY(out->name);
2285
2286
0
  out->num_values = in->value_ctr.num_values;
2287
0
  out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
2288
0
  W_ERROR_HAVE_NO_MEMORY(out->values);
2289
2290
0
  for (i=0; i < out->num_values; i++) {
2291
0
    size_t len;
2292
0
    size_t converted_size = 0;
2293
0
    char *str;
2294
2295
0
    if (in->value_ctr.values[i].blob == NULL) {
2296
0
      return WERR_FOOBAR;
2297
0
    }
2298
2299
0
    if (in->value_ctr.values[i].blob->length < 4) {
2300
0
      return WERR_FOOBAR;
2301
0
    }
2302
2303
0
    len = IVAL(in->value_ctr.values[i].blob->data, 0);
2304
2305
0
    if (len != in->value_ctr.values[i].blob->length) {
2306
0
      return WERR_FOOBAR;
2307
0
    }
2308
2309
0
    if (!convert_string_talloc(out->values, CH_UTF16, CH_UNIX,
2310
0
             in->value_ctr.values[i].blob->data+4,
2311
0
             in->value_ctr.values[i].blob->length-4,
2312
0
             (void **)&str, &converted_size)) {
2313
0
      return WERR_FOOBAR;
2314
0
    }
2315
2316
0
    out->values[i] = data_blob_string_const(str);
2317
0
  }
2318
2319
0
  return WERR_OK;
2320
0
}
2321
2322
static WERROR dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
2323
                    const struct dsdb_attribute *attr,
2324
                    const struct ldb_message_element *in,
2325
                    TALLOC_CTX *mem_ctx,
2326
                    struct drsuapi_DsReplicaAttribute *out)
2327
0
{
2328
0
  unsigned int i;
2329
0
  DATA_BLOB *blobs;
2330
2331
0
  if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
2332
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
2333
0
  }
2334
2335
0
  out->attid      = dsdb_attribute_get_attid(attr,
2336
0
                   ctx->is_schema_nc);
2337
0
  out->value_ctr.num_values = in->num_values;
2338
0
  out->value_ctr.values   = talloc_array(mem_ctx,
2339
0
                   struct drsuapi_DsAttributeValue,
2340
0
                   in->num_values);
2341
0
  W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
2342
2343
0
  blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
2344
0
  W_ERROR_HAVE_NO_MEMORY(blobs);
2345
2346
0
  for (i=0; i < in->num_values; i++) {
2347
0
    uint8_t *data;
2348
0
    size_t ret;
2349
2350
0
    out->value_ctr.values[i].blob = &blobs[i];
2351
2352
0
    if (!convert_string_talloc(blobs, CH_UNIX, CH_UTF16,
2353
0
             in->values[i].data,
2354
0
             in->values[i].length,
2355
0
             (void **)&data, &ret)) {
2356
0
      return WERR_FOOBAR;
2357
0
    }
2358
2359
0
    blobs[i] = data_blob_talloc(blobs, NULL, 4 + ret);
2360
0
    W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
2361
2362
0
    SIVAL(blobs[i].data, 0, 4 + ret);
2363
2364
0
    if (ret > 0) {
2365
0
      memcpy(blobs[i].data + 4, data, ret);
2366
0
      talloc_free(data);
2367
0
    }
2368
0
  }
2369
2370
0
  return WERR_OK;
2371
0
}
2372
2373
static WERROR dsdb_syntax_PRESENTATION_ADDRESS_validate_ldb(const struct dsdb_syntax_ctx *ctx,
2374
                  const struct dsdb_attribute *attr,
2375
                  const struct ldb_message_element *in)
2376
0
{
2377
0
  return dsdb_syntax_UNICODE_validate_ldb(ctx,
2378
0
            attr,
2379
0
            in);
2380
0
}
2381
2382
#define OMOBJECTCLASS(val) { .length = sizeof(val) - 1, .data = discard_const_p(uint8_t, val) }
2383
2384
static const struct dsdb_syntax dsdb_syntaxes[] = {
2385
  {
2386
    .name     = "Boolean",
2387
    .ldap_oid   = LDB_SYNTAX_BOOLEAN,
2388
    .oMSyntax   = 1,
2389
    .attributeSyntax_oid  = "2.5.5.8",
2390
    .drsuapi_to_ldb   = dsdb_syntax_BOOL_drsuapi_to_ldb,
2391
    .ldb_to_drsuapi   = dsdb_syntax_BOOL_ldb_to_drsuapi,
2392
    .validate_ldb   = dsdb_syntax_BOOL_validate_ldb,
2393
    .equality               = "booleanMatch",
2394
    .comment                = "Boolean",
2395
    .auto_normalise   = true
2396
  },{
2397
    .name     = "Integer",
2398
    .ldap_oid   = LDB_SYNTAX_INTEGER,
2399
    .oMSyntax   = 2,
2400
    .attributeSyntax_oid  = "2.5.5.9",
2401
    .drsuapi_to_ldb   = dsdb_syntax_INT32_drsuapi_to_ldb,
2402
    .ldb_to_drsuapi   = dsdb_syntax_INT32_ldb_to_drsuapi,
2403
    .validate_ldb   = dsdb_syntax_INT32_validate_ldb,
2404
    .equality               = "integerMatch",
2405
    .comment                = "Integer",
2406
    .ldb_syntax   = LDB_SYNTAX_SAMBA_INT32,
2407
    .auto_normalise   = true
2408
  },{
2409
    .name     = "String(Octet)",
2410
    .ldap_oid   = LDB_SYNTAX_OCTET_STRING,
2411
    .oMSyntax   = 4,
2412
    .attributeSyntax_oid  = "2.5.5.10",
2413
    .drsuapi_to_ldb   = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2414
    .ldb_to_drsuapi   = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2415
    .validate_ldb   = dsdb_syntax_DATA_BLOB_validate_ldb,
2416
    .equality               = "octetStringMatch",
2417
    .comment                = "Octet String",
2418
    .userParameters         = true,
2419
    .ldb_syntax             = LDB_SYNTAX_SAMBA_OCTET_STRING
2420
  },{
2421
    .name     = "String(Sid)",
2422
    .ldap_oid   = LDB_SYNTAX_OCTET_STRING,
2423
    .oMSyntax   = 4,
2424
    .attributeSyntax_oid  = "2.5.5.17",
2425
    .drsuapi_to_ldb   = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2426
    .ldb_to_drsuapi   = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2427
    .validate_ldb   = dsdb_syntax_DATA_BLOB_validate_ldb,
2428
    .equality               = "octetStringMatch",
2429
    .comment                = "Octet String - Security Identifier (SID)",
2430
    .ldb_syntax             = LDB_SYNTAX_SAMBA_SID
2431
  },{
2432
    .name     = "String(Object-Identifier)",
2433
    .ldap_oid   = "1.3.6.1.4.1.1466.115.121.1.38",
2434
    .oMSyntax   = 6,
2435
    .attributeSyntax_oid  = "2.5.5.2",
2436
    .drsuapi_to_ldb   = dsdb_syntax_OID_drsuapi_to_ldb,
2437
    .ldb_to_drsuapi   = dsdb_syntax_OID_ldb_to_drsuapi,
2438
    .validate_ldb   = dsdb_syntax_OID_validate_ldb,
2439
    .equality               = "caseIgnoreMatch", /* Would use "objectIdentifierMatch" but most are ldap attribute/class names */
2440
    .comment                = "OID String",
2441
    .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING
2442
  },{
2443
    .name     = "Enumeration",
2444
    .ldap_oid   = LDB_SYNTAX_INTEGER,
2445
    .oMSyntax   = 10,
2446
    .attributeSyntax_oid  = "2.5.5.9",
2447
    .drsuapi_to_ldb   = dsdb_syntax_INT32_drsuapi_to_ldb,
2448
    .ldb_to_drsuapi   = dsdb_syntax_INT32_ldb_to_drsuapi,
2449
    .validate_ldb   = dsdb_syntax_INT32_validate_ldb,
2450
    .ldb_syntax   = LDB_SYNTAX_SAMBA_INT32,
2451
    .auto_normalise   = true
2452
  },{
2453
  /* not used in w2k3 forest */
2454
    .name     = "String(Numeric)",
2455
    .ldap_oid   = "1.3.6.1.4.1.1466.115.121.1.36",
2456
    .oMSyntax   = 18,
2457
    .attributeSyntax_oid  = "2.5.5.6",
2458
    .drsuapi_to_ldb   = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2459
    .ldb_to_drsuapi   = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2460
    .validate_ldb   = dsdb_syntax_DATA_BLOB_validate_ldb,
2461
    .equality               = "numericStringMatch",
2462
    .substring              = "numericStringSubstringsMatch",
2463
    .comment                = "Numeric String",
2464
    .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
2465
  },{
2466
    .name     = "String(Printable)",
2467
    .ldap_oid   = "1.3.6.1.4.1.1466.115.121.1.44",
2468
    .oMSyntax   = 19,
2469
    .attributeSyntax_oid  = "2.5.5.5",
2470
    .drsuapi_to_ldb   = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2471
    .ldb_to_drsuapi   = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2472
    .validate_ldb   = dsdb_syntax_DATA_BLOB_validate_ldb,
2473
    .ldb_syntax   = LDB_SYNTAX_SAMBA_OCTET_STRING,
2474
  },{
2475
    .name     = "String(Teletex)",
2476
    .ldap_oid   = "1.2.840.113556.1.4.905",
2477
    .oMSyntax   = 20,
2478
    .attributeSyntax_oid  = "2.5.5.4",
2479
    .drsuapi_to_ldb   = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2480
    .ldb_to_drsuapi   = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2481
    .validate_ldb   = dsdb_syntax_DATA_BLOB_validate_ldb,
2482
    .equality               = "caseIgnoreMatch",
2483
    .substring              = "caseIgnoreSubstringsMatch",
2484
    .comment                = "Case Insensitive String",
2485
    .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
2486
  },{
2487
    .name     = "String(IA5)",
2488
    .ldap_oid   = "1.3.6.1.4.1.1466.115.121.1.26",
2489
    .oMSyntax   = 22,
2490
    .attributeSyntax_oid  = "2.5.5.5",
2491
    .drsuapi_to_ldb   = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2492
    .ldb_to_drsuapi   = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2493
    .validate_ldb   = dsdb_syntax_DATA_BLOB_validate_ldb,
2494
    .equality               = "caseExactIA5Match",
2495
    .comment                = "Printable String",
2496
    .ldb_syntax   = LDB_SYNTAX_SAMBA_OCTET_STRING,
2497
  },{
2498
    .name     = "String(UTC-Time)",
2499
    .ldap_oid   = "1.3.6.1.4.1.1466.115.121.1.53",
2500
    .oMSyntax   = 23,
2501
    .attributeSyntax_oid  = "2.5.5.11",
2502
    .drsuapi_to_ldb   = dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb,
2503
    .ldb_to_drsuapi   = dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi,
2504
    .validate_ldb   = dsdb_syntax_NTTIME_UTC_validate_ldb,
2505
    .equality               = "generalizedTimeMatch",
2506
    .comment                = "UTC Time",
2507
    .auto_normalise   = true
2508
  },{
2509
    .name     = "String(Generalized-Time)",
2510
    .ldap_oid   = "1.3.6.1.4.1.1466.115.121.1.24",
2511
    .oMSyntax   = 24,
2512
    .attributeSyntax_oid  = "2.5.5.11",
2513
    .drsuapi_to_ldb   = dsdb_syntax_NTTIME_drsuapi_to_ldb,
2514
    .ldb_to_drsuapi   = dsdb_syntax_NTTIME_ldb_to_drsuapi,
2515
    .validate_ldb   = dsdb_syntax_NTTIME_validate_ldb,
2516
    .equality               = "generalizedTimeMatch",
2517
    .comment                = "Generalized Time",
2518
    .auto_normalise   = true
2519
  },{
2520
  /* not used in w2k3 schema */
2521
    .name     = "String(Case Sensitive)",
2522
    .ldap_oid   = "1.2.840.113556.1.4.1362",
2523
    .oMSyntax   = 27,
2524
    .attributeSyntax_oid  = "2.5.5.3",
2525
    .drsuapi_to_ldb   = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2526
    .ldb_to_drsuapi   = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2527
    .validate_ldb   = dsdb_syntax_DATA_BLOB_validate_ldb,
2528
    .equality               = "caseExactMatch",
2529
    .substring              = "caseExactSubstringsMatch",
2530
    /* TODO (kim): according to LDAP rfc we should be using same comparison
2531
     * as Directory String (LDB_SYNTAX_DIRECTORY_STRING), but case sensitive.
2532
     * But according to ms docs binary compare should do the job:
2533
     * http://msdn.microsoft.com/en-us/library/cc223200(v=PROT.10).aspx */
2534
    .ldb_syntax   = LDB_SYNTAX_SAMBA_OCTET_STRING,
2535
  },{
2536
    .name     = "String(Unicode)",
2537
    .ldap_oid   = LDB_SYNTAX_DIRECTORY_STRING,
2538
    .oMSyntax   = 64,
2539
    .attributeSyntax_oid  = "2.5.5.12",
2540
    .drsuapi_to_ldb   = dsdb_syntax_UNICODE_drsuapi_to_ldb,
2541
    .ldb_to_drsuapi   = dsdb_syntax_UNICODE_ldb_to_drsuapi,
2542
    .validate_ldb   = dsdb_syntax_UNICODE_validate_ldb,
2543
    .equality               = "caseIgnoreMatch",
2544
    .substring              = "caseIgnoreSubstringsMatch",
2545
    .comment                = "Directory String",
2546
  },{
2547
    .name     = "Interval/LargeInteger",
2548
    .ldap_oid   = "1.2.840.113556.1.4.906",
2549
    .oMSyntax   = 65,
2550
    .attributeSyntax_oid  = "2.5.5.16",
2551
    .drsuapi_to_ldb   = dsdb_syntax_INT64_drsuapi_to_ldb,
2552
    .ldb_to_drsuapi   = dsdb_syntax_INT64_ldb_to_drsuapi,
2553
    .validate_ldb   = dsdb_syntax_INT64_validate_ldb,
2554
    .equality               = "integerMatch",
2555
    .comment                = "Large Integer",
2556
    .ldb_syntax             = LDB_SYNTAX_ORDERED_INTEGER,
2557
    .auto_normalise   = true
2558
  },{
2559
    .name     = "String(NT-Sec-Desc)",
2560
    .ldap_oid   = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
2561
    .oMSyntax   = 66,
2562
    .attributeSyntax_oid  = "2.5.5.15",
2563
    .drsuapi_to_ldb   = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2564
    .ldb_to_drsuapi   = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2565
    .validate_ldb   = dsdb_syntax_DATA_BLOB_validate_ldb,
2566
  },{
2567
    .name     = "Object(DS-DN)",
2568
    .ldap_oid   = LDB_SYNTAX_DN,
2569
    .oMSyntax   = 127,
2570
    .oMObjectClass    = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x4a"),
2571
    .attributeSyntax_oid  = "2.5.5.1",
2572
    .drsuapi_to_ldb   = dsdb_syntax_DN_drsuapi_to_ldb,
2573
    .ldb_to_drsuapi   = dsdb_syntax_DN_ldb_to_drsuapi,
2574
    .validate_ldb   = dsdb_syntax_DN_validate_ldb,
2575
    .equality               = "distinguishedNameMatch",
2576
    .comment                = "Object(DS-DN) == a DN",
2577
  },{
2578
    .name     = "Object(DN-Binary)",
2579
    .ldap_oid   = DSDB_SYNTAX_BINARY_DN,
2580
    .oMSyntax   = 127,
2581
    .oMObjectClass    = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0b"),
2582
    .attributeSyntax_oid  = "2.5.5.7",
2583
    .drsuapi_to_ldb   = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
2584
    .ldb_to_drsuapi   = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
2585
    .validate_ldb   = dsdb_syntax_DN_BINARY_validate_ldb,
2586
    .equality               = "octetStringMatch",
2587
    .comment                = "OctetString: Binary+DN",
2588
  },{
2589
  /* not used in w2k3 schema, but used in Exchange schema*/
2590
    .name     = "Object(OR-Name)",
2591
    .ldap_oid   = DSDB_SYNTAX_OR_NAME,
2592
    .oMSyntax   = 127,
2593
    .oMObjectClass    = OMOBJECTCLASS("\x56\x06\x01\x02\x05\x0b\x1D"),
2594
    .attributeSyntax_oid  = "2.5.5.7",
2595
    .drsuapi_to_ldb   = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
2596
    .ldb_to_drsuapi   = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
2597
    .validate_ldb   = dsdb_syntax_DN_validate_ldb,
2598
    .equality               = "distinguishedNameMatch",
2599
    .ldb_syntax   = LDB_SYNTAX_DN,
2600
  },{
2601
  /*
2602
   * TODO: verify if DATA_BLOB is correct here...!
2603
   *
2604
   *       repsFrom and repsTo are the only attributes using
2605
   *       this attribute syntax, but they're not replicated...
2606
   */
2607
    .name     = "Object(Replica-Link)",
2608
    .ldap_oid   = "1.3.6.1.4.1.1466.115.121.1.40",
2609
    .oMSyntax   = 127,
2610
    .oMObjectClass    = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x06"),
2611
    .attributeSyntax_oid  = "2.5.5.10",
2612
    .drsuapi_to_ldb   = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2613
    .ldb_to_drsuapi   = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2614
    .validate_ldb   = dsdb_syntax_DATA_BLOB_validate_ldb,
2615
  },{
2616
    .name     = "Object(Presentation-Address)",
2617
    .ldap_oid   = "1.3.6.1.4.1.1466.115.121.1.43",
2618
    .oMSyntax   = 127,
2619
    .oMObjectClass    = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x5c"),
2620
    .attributeSyntax_oid  = "2.5.5.13",
2621
    .drsuapi_to_ldb   = dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb,
2622
    .ldb_to_drsuapi   = dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi,
2623
    .validate_ldb   = dsdb_syntax_PRESENTATION_ADDRESS_validate_ldb,
2624
    .comment                = "Presentation Address",
2625
    .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
2626
  },{
2627
  /* not used in w2k3 schema */
2628
    .name     = "Object(Access-Point)",
2629
    .ldap_oid   = DSDB_SYNTAX_ACCESS_POINT,
2630
    .oMSyntax   = 127,
2631
    .oMObjectClass    = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x3e"),
2632
    .attributeSyntax_oid  = "2.5.5.14",
2633
    .drsuapi_to_ldb   = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
2634
    .ldb_to_drsuapi   = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
2635
    .validate_ldb   = dsdb_syntax_FOOBAR_validate_ldb,
2636
    .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
2637
  },{
2638
  /* not used in w2k3 schema */
2639
    .name     = "Object(DN-String)",
2640
    .ldap_oid   = DSDB_SYNTAX_STRING_DN,
2641
    .oMSyntax   = 127,
2642
    .oMObjectClass    = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0c"),
2643
    .attributeSyntax_oid  = "2.5.5.14",
2644
    .drsuapi_to_ldb   = dsdb_syntax_DN_STRING_drsuapi_to_ldb,
2645
    .ldb_to_drsuapi   = dsdb_syntax_DN_STRING_ldb_to_drsuapi,
2646
    .validate_ldb   = dsdb_syntax_DN_STRING_validate_ldb,
2647
    .equality               = "octetStringMatch",
2648
    .comment                = "OctetString: String+DN",
2649
  }
2650
};
2651
2652
const struct dsdb_syntax *find_syntax_map_by_ad_oid(const char *ad_oid)
2653
0
{
2654
0
  unsigned int i;
2655
0
  for (i=0; i < ARRAY_SIZE(dsdb_syntaxes); i++) {
2656
0
    if (strcasecmp(ad_oid, dsdb_syntaxes[i].attributeSyntax_oid) == 0) {
2657
0
      return &dsdb_syntaxes[i];
2658
0
    }
2659
0
  }
2660
0
  return NULL;
2661
0
}
2662
2663
const struct dsdb_syntax *find_syntax_map_by_ad_syntax(int oMSyntax)
2664
0
{
2665
0
  unsigned int i;
2666
0
  for (i=0; i < ARRAY_SIZE(dsdb_syntaxes); i++) {
2667
0
    if (oMSyntax == dsdb_syntaxes[i].oMSyntax) {
2668
0
      return &dsdb_syntaxes[i];
2669
0
    }
2670
0
  }
2671
0
  return NULL;
2672
0
}
2673
2674
const struct dsdb_syntax *find_syntax_map_by_standard_oid(const char *standard_oid)
2675
0
{
2676
0
  unsigned int i;
2677
0
  for (i=0; i < ARRAY_SIZE(dsdb_syntaxes); i++) {
2678
0
    if (strcasecmp(standard_oid, dsdb_syntaxes[i].ldap_oid) == 0) {
2679
0
      return &dsdb_syntaxes[i];
2680
0
    }
2681
0
  }
2682
0
  return NULL;
2683
0
}
2684
2685
const struct dsdb_syntax *dsdb_syntax_for_attribute(const struct dsdb_attribute *attr)
2686
0
{
2687
0
  unsigned int i;
2688
2689
0
  for (i=0; i < ARRAY_SIZE(dsdb_syntaxes); i++) {
2690
    /*
2691
     * We must pretend that userParameters was declared
2692
     * binary string, so we can store the 'UTF16' (not
2693
     * really string) structure as given over SAMR to samba
2694
     */
2695
0
    if (dsdb_syntaxes[i].userParameters &&
2696
0
        (strcasecmp(attr->lDAPDisplayName, "userParameters") == 0))
2697
0
    {
2698
0
      return &dsdb_syntaxes[i];
2699
0
    }
2700
0
    if (attr->oMSyntax != dsdb_syntaxes[i].oMSyntax) continue;
2701
2702
0
    if (attr->oMObjectClass.length != dsdb_syntaxes[i].oMObjectClass.length) continue;
2703
2704
0
    if (attr->oMObjectClass.length) {
2705
0
      int ret;
2706
0
      ret = memcmp(attr->oMObjectClass.data,
2707
0
             dsdb_syntaxes[i].oMObjectClass.data,
2708
0
             attr->oMObjectClass.length);
2709
0
      if (ret != 0) continue;
2710
0
    }
2711
2712
0
    if (strcmp(attr->attributeSyntax_oid, dsdb_syntaxes[i].attributeSyntax_oid) != 0) continue;
2713
2714
0
    return &dsdb_syntaxes[i];
2715
0
  }
2716
2717
0
  return NULL;
2718
0
}
2719
2720
WERROR dsdb_attribute_drsuapi_remote_to_local(const struct dsdb_syntax_ctx *ctx,
2721
                enum drsuapi_DsAttributeId remote_attid_as_enum,
2722
                enum drsuapi_DsAttributeId *local_attid_as_enum,
2723
                const struct dsdb_attribute **_sa)
2724
0
{
2725
0
  TALLOC_CTX *frame = talloc_stackframe();
2726
0
  const struct dsdb_attribute *sa;
2727
0
  uint32_t attid_local;
2728
0
  bool ok;
2729
2730
0
  if (ctx->pfm_remote == NULL) {
2731
0
    smb_panic(__location__);
2732
0
  }
2733
2734
0
  switch (dsdb_pfm_get_attid_type(remote_attid_as_enum)) {
2735
0
  case DSDB_ATTID_TYPE_PFM:
2736
    /* map remote ATTID to local ATTID */
2737
0
    ok = dsdb_syntax_attid_from_remote_attid(ctx, frame,
2738
0
               remote_attid_as_enum,
2739
0
               &attid_local);
2740
0
    if (!ok) {
2741
0
      DEBUG(0,(__location__ ": Can't find local ATTID for 0x%08X\n",
2742
0
         remote_attid_as_enum));
2743
0
      TALLOC_FREE(frame);
2744
0
      return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
2745
0
    }
2746
0
    break;
2747
0
  case DSDB_ATTID_TYPE_INTID:
2748
    /* use IntId value directly */
2749
0
    attid_local = remote_attid_as_enum;
2750
0
    break;
2751
0
  default:
2752
    /* we should never get here */
2753
0
    DEBUG(0,(__location__ ": Invalid ATTID type passed for conversion - 0x%08X\n",
2754
0
       remote_attid_as_enum));
2755
0
    TALLOC_FREE(frame);
2756
0
    return WERR_INVALID_PARAMETER;
2757
0
  }
2758
2759
0
  sa = dsdb_attribute_by_attributeID_id(ctx->schema, attid_local);
2760
0
  if (!sa) {
2761
0
    int dbg_level = ctx->schema->resolving_in_progress ? 10 : 0;
2762
0
    DEBUG(dbg_level,(__location__ ": Unknown local attributeID_id 0x%08X remote 0x%08X%s\n",
2763
0
          attid_local, remote_attid_as_enum,
2764
0
          ctx->schema->resolving_in_progress ? "resolving in progress" : ""));
2765
0
    TALLOC_FREE(frame);
2766
0
    return WERR_DS_ATT_NOT_DEF_IN_SCHEMA;
2767
0
  }
2768
2769
  /*
2770
   * We return the same class of attid as we were given.  That
2771
   * is, we trust the remote server not to use an
2772
   * msDS-IntId value in the schema partition
2773
   */
2774
0
  if (local_attid_as_enum != NULL) {
2775
0
    *local_attid_as_enum = (enum drsuapi_DsAttributeId)attid_local;
2776
0
  }
2777
2778
0
  if (_sa != NULL) {
2779
0
    *_sa = sa;
2780
0
  }
2781
2782
0
  TALLOC_FREE(frame);
2783
0
  return WERR_OK;
2784
0
}
2785
2786
WERROR dsdb_attribute_drsuapi_to_ldb(struct ldb_context *ldb,
2787
             const struct dsdb_schema *schema,
2788
             const struct dsdb_schema_prefixmap *pfm_remote,
2789
             const struct drsuapi_DsReplicaAttribute *in,
2790
             TALLOC_CTX *mem_ctx,
2791
             struct ldb_message_element *out,
2792
             enum drsuapi_DsAttributeId *local_attid_as_enum)
2793
0
{
2794
0
  struct dsdb_syntax_ctx syntax_ctx;
2795
0
  const struct dsdb_attribute *sa = NULL;
2796
0
  WERROR werr;
2797
2798
  /* use default syntax conversion context */
2799
0
  dsdb_syntax_ctx_init(&syntax_ctx, ldb, schema);
2800
0
  syntax_ctx.pfm_remote = pfm_remote;
2801
2802
0
  werr = dsdb_attribute_drsuapi_remote_to_local(&syntax_ctx,
2803
0
                  in->attid,
2804
0
                  local_attid_as_enum,
2805
0
                  &sa);
2806
0
  if (!W_ERROR_IS_OK(werr)) {
2807
0
    return werr;
2808
0
  }
2809
2810
0
  return sa->syntax->drsuapi_to_ldb(&syntax_ctx, sa, in, mem_ctx, out);
2811
0
}