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