s4-dsdb_syntax: Use remote prefixMap to handle generic cases in drsuapi_to_ldb conver...
[metze/samba/wip.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                         SMB_ASSERT(ctx->pfm_remote);
908                         werr = dsdb_schema_pfm_oid_from_attid(ctx->pfm_remote, v,
909                                                               out->values, &str);
910                         W_ERROR_NOT_OK_RETURN(werr);
911                 }
912                 W_ERROR_HAVE_NO_MEMORY(str);
913
914                 /* the values need to be reversed */
915                 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
916         }
917
918         return WERR_OK;
919 }
920
921 static WERROR _dsdb_syntax_OID_obj_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
922                                                   const struct dsdb_attribute *attr,
923                                                   const struct drsuapi_DsReplicaAttribute *in,
924                                                   TALLOC_CTX *mem_ctx,
925                                                   struct ldb_message_element *out)
926 {
927         unsigned int i;
928
929         out->flags      = 0;
930         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
931         W_ERROR_HAVE_NO_MEMORY(out->name);
932
933         out->num_values = in->value_ctr.num_values;
934         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
935         W_ERROR_HAVE_NO_MEMORY(out->values);
936
937         for (i=0; i < out->num_values; i++) {
938                 uint32_t v;
939                 const struct dsdb_class *c;
940                 const char *str;
941
942                 if (in->value_ctr.values[i].blob == NULL) {
943                         return WERR_FOOBAR;
944                 }
945
946                 if (in->value_ctr.values[i].blob->length != 4) {
947                         return WERR_FOOBAR;
948                 }
949
950                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
951
952                 c = dsdb_class_by_governsID_id(ctx->schema, v);
953                 if (!c) {
954                         return WERR_FOOBAR;
955                 }
956
957                 str = talloc_strdup(out->values, c->lDAPDisplayName);
958                 W_ERROR_HAVE_NO_MEMORY(str);
959
960                 /* the values need to be reversed */
961                 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
962         }
963
964         return WERR_OK;
965 }
966
967 static WERROR _dsdb_syntax_OID_attr_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
968                                                    const struct dsdb_attribute *attr,
969                                                    const struct drsuapi_DsReplicaAttribute *in,
970                                                    TALLOC_CTX *mem_ctx,
971                                                    struct ldb_message_element *out)
972 {
973         unsigned int i;
974
975         out->flags      = 0;
976         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
977         W_ERROR_HAVE_NO_MEMORY(out->name);
978
979         out->num_values = in->value_ctr.num_values;
980         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
981         W_ERROR_HAVE_NO_MEMORY(out->values);
982
983         for (i=0; i < out->num_values; i++) {
984                 uint32_t v;
985                 const struct dsdb_attribute *a;
986                 const char *str;
987
988                 if (in->value_ctr.values[i].blob == NULL) {
989                         return WERR_FOOBAR;
990                 }
991
992                 if (in->value_ctr.values[i].blob->length != 4) {
993                         return WERR_FOOBAR;
994                 }
995
996                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
997
998                 a = dsdb_attribute_by_attributeID_id(ctx->schema, v);
999                 if (!a) {
1000                         return WERR_FOOBAR;
1001                 }
1002
1003                 str = talloc_strdup(out->values, a->lDAPDisplayName);
1004                 W_ERROR_HAVE_NO_MEMORY(str);
1005
1006                 /* the values need to be reversed */
1007                 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
1008         }
1009
1010         return WERR_OK;
1011 }
1012
1013 static WERROR _dsdb_syntax_OID_oid_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
1014                                                   const struct dsdb_attribute *attr,
1015                                                   const struct drsuapi_DsReplicaAttribute *in,
1016                                                   TALLOC_CTX *mem_ctx,
1017                                                   struct ldb_message_element *out)
1018 {
1019         unsigned int i;
1020
1021         SMB_ASSERT(ctx->pfm_remote);
1022
1023         out->flags      = 0;
1024         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1025         W_ERROR_HAVE_NO_MEMORY(out->name);
1026
1027         out->num_values = in->value_ctr.num_values;
1028         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1029         W_ERROR_HAVE_NO_MEMORY(out->values);
1030
1031         for (i=0; i < out->num_values; i++) {
1032                 uint32_t attid;
1033                 WERROR status;
1034                 const char *oid;
1035
1036                 if (in->value_ctr.values[i].blob == NULL) {
1037                         return WERR_FOOBAR;
1038                 }
1039
1040                 if (in->value_ctr.values[i].blob->length != 4) {
1041                         return WERR_FOOBAR;
1042                 }
1043
1044                 attid = IVAL(in->value_ctr.values[i].blob->data, 0);
1045
1046                 status = dsdb_schema_pfm_oid_from_attid(ctx->pfm_remote, attid,
1047                                                         out->values, &oid);
1048                 W_ERROR_NOT_OK_RETURN(status);
1049
1050                 out->values[i] = data_blob_string_const(oid);
1051         }
1052
1053         return WERR_OK;
1054 }
1055
1056 static WERROR _dsdb_syntax_auto_OID_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1057                                                    const struct dsdb_attribute *attr,
1058                                                    const struct ldb_message_element *in,
1059                                                    TALLOC_CTX *mem_ctx,
1060                                                    struct drsuapi_DsReplicaAttribute *out)
1061 {
1062         unsigned int i;
1063         DATA_BLOB *blobs;
1064
1065         out->attid= dsdb_attribute_get_attid(attr,
1066                                              ctx->is_schema_nc);
1067         out->value_ctr.num_values= in->num_values;
1068         out->value_ctr.values= talloc_array(mem_ctx,
1069                                             struct drsuapi_DsAttributeValue,
1070                                             in->num_values);
1071         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1072
1073         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1074         W_ERROR_HAVE_NO_MEMORY(blobs);
1075
1076         for (i=0; i < in->num_values; i++) {
1077                 const struct dsdb_class *obj_class;
1078                 const struct dsdb_attribute *obj_attr;
1079                 struct ldb_val *v;
1080
1081                 out->value_ctr.values[i].blob= &blobs[i];
1082
1083                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
1084                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1085
1086                 /* in DRS windows puts the classes in the opposite
1087                    order to the order used in ldap */
1088                 v = &in->values[(in->num_values-1)-i];
1089
1090                 if ((obj_class = dsdb_class_by_lDAPDisplayName_ldb_val(ctx->schema, v))) {
1091                         SIVAL(blobs[i].data, 0, obj_class->governsID_id);
1092                 } else if ((obj_attr = dsdb_attribute_by_lDAPDisplayName_ldb_val(ctx->schema, v))) {
1093                         SIVAL(blobs[i].data, 0, obj_attr->attributeID_id);
1094                 } else {
1095                         uint32_t attid;
1096                         WERROR werr;
1097                         werr = dsdb_schema_pfm_attid_from_oid(ctx->schema->prefixmap,
1098                                                               (const char *)v->data,
1099                                                               &attid);
1100                         W_ERROR_NOT_OK_RETURN(werr);
1101                         SIVAL(blobs[i].data, 0, attid);
1102                 }
1103
1104         }
1105
1106
1107         return WERR_OK;
1108 }
1109
1110 static WERROR _dsdb_syntax_OID_obj_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1111                                                   const struct dsdb_attribute *attr,
1112                                                   const struct ldb_message_element *in,
1113                                                   TALLOC_CTX *mem_ctx,
1114                                                   struct drsuapi_DsReplicaAttribute *out)
1115 {
1116         unsigned int i;
1117         DATA_BLOB *blobs;
1118
1119         out->attid= dsdb_attribute_get_attid(attr,
1120                                              ctx->is_schema_nc);
1121         out->value_ctr.num_values= in->num_values;
1122         out->value_ctr.values= talloc_array(mem_ctx,
1123                                             struct drsuapi_DsAttributeValue,
1124                                             in->num_values);
1125         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1126
1127         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1128         W_ERROR_HAVE_NO_MEMORY(blobs);
1129
1130         for (i=0; i < in->num_values; i++) {
1131                 const struct dsdb_class *obj_class;
1132
1133                 out->value_ctr.values[i].blob= &blobs[i];
1134
1135                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
1136                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1137
1138                 /* in DRS windows puts the classes in the opposite
1139                    order to the order used in ldap */
1140                 obj_class = dsdb_class_by_lDAPDisplayName(ctx->schema,
1141                                                           (const char *)in->values[(in->num_values-1)-i].data);
1142                 if (!obj_class) {
1143                         return WERR_FOOBAR;
1144                 }
1145                 SIVAL(blobs[i].data, 0, obj_class->governsID_id);
1146         }
1147
1148
1149         return WERR_OK;
1150 }
1151
1152 static WERROR _dsdb_syntax_OID_attr_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1153                                                    const struct dsdb_attribute *attr,
1154                                                    const struct ldb_message_element *in,
1155                                                    TALLOC_CTX *mem_ctx,
1156                                                    struct drsuapi_DsReplicaAttribute *out)
1157 {
1158         unsigned int i;
1159         DATA_BLOB *blobs;
1160
1161         out->attid= dsdb_attribute_get_attid(attr,
1162                                              ctx->is_schema_nc);
1163         out->value_ctr.num_values= in->num_values;
1164         out->value_ctr.values= talloc_array(mem_ctx,
1165                                             struct drsuapi_DsAttributeValue,
1166                                             in->num_values);
1167         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1168
1169         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1170         W_ERROR_HAVE_NO_MEMORY(blobs);
1171
1172         for (i=0; i < in->num_values; i++) {
1173                 const struct dsdb_attribute *obj_attr;
1174
1175                 out->value_ctr.values[i].blob= &blobs[i];
1176
1177                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
1178                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1179
1180                 obj_attr = dsdb_attribute_by_lDAPDisplayName(ctx->schema, (const char *)in->values[i].data);
1181                 if (!obj_attr) {
1182                         return WERR_FOOBAR;
1183                 }
1184                 SIVAL(blobs[i].data, 0, obj_attr->attributeID_id);
1185         }
1186
1187
1188         return WERR_OK;
1189 }
1190
1191 static WERROR _dsdb_syntax_OID_oid_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1192                                                   const struct dsdb_attribute *attr,
1193                                                   const struct ldb_message_element *in,
1194                                                   TALLOC_CTX *mem_ctx,
1195                                                   struct drsuapi_DsReplicaAttribute *out)
1196 {
1197         unsigned int i;
1198         DATA_BLOB *blobs;
1199
1200         out->attid= dsdb_attribute_get_attid(attr,
1201                                              ctx->is_schema_nc);
1202         out->value_ctr.num_values= in->num_values;
1203         out->value_ctr.values= talloc_array(mem_ctx,
1204                                             struct drsuapi_DsAttributeValue,
1205                                             in->num_values);
1206         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1207
1208         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1209         W_ERROR_HAVE_NO_MEMORY(blobs);
1210
1211         for (i=0; i < in->num_values; i++) {
1212                 uint32_t attid;
1213                 WERROR status;
1214
1215                 out->value_ctr.values[i].blob= &blobs[i];
1216
1217                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
1218                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1219
1220                 status = dsdb_schema_pfm_attid_from_oid(ctx->schema->prefixmap,
1221                                                         (const char *)in->values[i].data,
1222                                                         &attid);
1223                 W_ERROR_NOT_OK_RETURN(status);
1224
1225                 SIVAL(blobs[i].data, 0, attid);
1226         }
1227
1228         return WERR_OK;
1229 }
1230
1231 static WERROR dsdb_syntax_OID_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
1232                                              const struct dsdb_attribute *attr,
1233                                              const struct drsuapi_DsReplicaAttribute *in,
1234                                              TALLOC_CTX *mem_ctx,
1235                                              struct ldb_message_element *out)
1236 {
1237         WERROR werr;
1238
1239         switch (attr->attributeID_id) {
1240         case DRSUAPI_ATTID_objectClass:
1241         case DRSUAPI_ATTID_subClassOf:
1242         case DRSUAPI_ATTID_auxiliaryClass:
1243         case DRSUAPI_ATTID_systemAuxiliaryClass:
1244         case DRSUAPI_ATTID_systemPossSuperiors:
1245         case DRSUAPI_ATTID_possSuperiors:
1246                 werr = _dsdb_syntax_OID_obj_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
1247                 break;
1248         case DRSUAPI_ATTID_systemMustContain:
1249         case DRSUAPI_ATTID_systemMayContain:
1250         case DRSUAPI_ATTID_mustContain:
1251         case DRSUAPI_ATTID_rDNAttId:
1252         case DRSUAPI_ATTID_transportAddressAttribute:
1253         case DRSUAPI_ATTID_mayContain:
1254                 werr = _dsdb_syntax_OID_attr_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
1255                 break;
1256         case DRSUAPI_ATTID_governsID:
1257         case DRSUAPI_ATTID_attributeID:
1258         case DRSUAPI_ATTID_attributeSyntax:
1259                 werr = _dsdb_syntax_OID_oid_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
1260                 break;
1261         default:
1262                 DEBUG(0,(__location__ ": Unknown handling for attributeID_id for %s\n",
1263                          attr->lDAPDisplayName));
1264                 return _dsdb_syntax_auto_OID_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
1265         }
1266
1267         /* When we are doing the vampire of a schema, we don't want
1268          * the inability to reference an OID to get in the way.
1269          * Otherwise, we won't get the new schema with which to
1270          * understand this */
1271         if (!W_ERROR_IS_OK(werr) && ctx->schema->relax_OID_conversions) {
1272                 return _dsdb_syntax_OID_oid_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
1273         }
1274         return werr;
1275 }
1276
1277 static WERROR dsdb_syntax_OID_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1278                                              const struct dsdb_attribute *attr,
1279                                              const struct ldb_message_element *in,
1280                                              TALLOC_CTX *mem_ctx,
1281                                              struct drsuapi_DsReplicaAttribute *out)
1282 {
1283         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1284                 return WERR_FOOBAR;
1285         }
1286
1287         switch (attr->attributeID_id) {
1288         case DRSUAPI_ATTID_objectClass:
1289         case DRSUAPI_ATTID_subClassOf:
1290         case DRSUAPI_ATTID_auxiliaryClass:
1291         case DRSUAPI_ATTID_systemAuxiliaryClass:
1292         case DRSUAPI_ATTID_systemPossSuperiors:
1293         case DRSUAPI_ATTID_possSuperiors:
1294                 return _dsdb_syntax_OID_obj_ldb_to_drsuapi(ctx, attr, in, mem_ctx, out);
1295         case DRSUAPI_ATTID_systemMustContain:
1296         case DRSUAPI_ATTID_systemMayContain:
1297         case DRSUAPI_ATTID_mustContain:
1298         case DRSUAPI_ATTID_rDNAttId:
1299         case DRSUAPI_ATTID_transportAddressAttribute:
1300         case DRSUAPI_ATTID_mayContain:
1301                 return _dsdb_syntax_OID_attr_ldb_to_drsuapi(ctx, attr, in, mem_ctx, out);
1302         case DRSUAPI_ATTID_governsID:
1303         case DRSUAPI_ATTID_attributeID:
1304         case DRSUAPI_ATTID_attributeSyntax:
1305                 return _dsdb_syntax_OID_oid_ldb_to_drsuapi(ctx, attr, in, mem_ctx, out);
1306         }
1307
1308         DEBUG(0,(__location__ ": Unknown handling for attributeID_id for %s\n",
1309                  attr->lDAPDisplayName));
1310
1311         return _dsdb_syntax_auto_OID_ldb_to_drsuapi(ctx, attr, in, mem_ctx, out);
1312 }
1313
1314 static WERROR _dsdb_syntax_OID_validate_numericoid(const struct dsdb_syntax_ctx *ctx,
1315                                                    const struct dsdb_attribute *attr,
1316                                                    const struct ldb_message_element *in)
1317 {
1318         unsigned int i;
1319         TALLOC_CTX *tmp_ctx;
1320
1321         tmp_ctx = talloc_new(ctx->ldb);
1322         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1323
1324         for (i=0; i < in->num_values; i++) {
1325                 DATA_BLOB blob;
1326                 const char *oid_out;
1327                 const char *oid = (const char*)in->values[i].data;
1328
1329                 if (!ber_write_OID_String(tmp_ctx, &blob, oid)) {
1330                         DEBUG(0,("ber_write_OID_String() failed for %s\n", oid));
1331                         talloc_free(tmp_ctx);
1332                         return WERR_INVALID_PARAMETER;
1333                 }
1334
1335                 if (!ber_read_OID_String(tmp_ctx, blob, &oid_out)) {
1336                         DEBUG(0,("ber_read_OID_String() failed for %s\n",
1337                                  hex_encode_talloc(tmp_ctx, blob.data, blob.length)));
1338                         talloc_free(tmp_ctx);
1339                         return WERR_INVALID_PARAMETER;
1340                 }
1341
1342                 if (strcmp(oid, oid_out) != 0) {
1343                         talloc_free(tmp_ctx);
1344                         return WERR_INVALID_PARAMETER;
1345                 }
1346         }
1347
1348         talloc_free(tmp_ctx);
1349         return WERR_OK;
1350 }
1351
1352 static WERROR dsdb_syntax_OID_validate_ldb(const struct dsdb_syntax_ctx *ctx,
1353                                            const struct dsdb_attribute *attr,
1354                                            const struct ldb_message_element *in)
1355 {
1356         WERROR status;
1357         struct drsuapi_DsReplicaAttribute drs_tmp;
1358         struct ldb_message_element ldb_tmp;
1359         TALLOC_CTX *tmp_ctx;
1360
1361         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1362                 return WERR_FOOBAR;
1363         }
1364
1365         switch (attr->attributeID_id) {
1366         case DRSUAPI_ATTID_governsID:
1367         case DRSUAPI_ATTID_attributeID:
1368         case DRSUAPI_ATTID_attributeSyntax:
1369                 return _dsdb_syntax_OID_validate_numericoid(ctx, attr, in);
1370         }
1371
1372         /*
1373          * TODO: optimize and verify this code
1374          */
1375
1376         tmp_ctx = talloc_new(ctx->ldb);
1377         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1378
1379         status = dsdb_syntax_OID_ldb_to_drsuapi(ctx,
1380                                                 attr,
1381                                                 in,
1382                                                 tmp_ctx,
1383                                                 &drs_tmp);
1384         if (!W_ERROR_IS_OK(status)) {
1385                 talloc_free(tmp_ctx);
1386                 return status;
1387         }
1388
1389         status = dsdb_syntax_OID_drsuapi_to_ldb(ctx,
1390                                                 attr,
1391                                                 &drs_tmp,
1392                                                 tmp_ctx,
1393                                                 &ldb_tmp);
1394         if (!W_ERROR_IS_OK(status)) {
1395                 talloc_free(tmp_ctx);
1396                 return status;
1397         }
1398
1399         talloc_free(tmp_ctx);
1400         return WERR_OK;
1401 }
1402
1403 static WERROR dsdb_syntax_UNICODE_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
1404                                                  const struct dsdb_attribute *attr,
1405                                                  const struct drsuapi_DsReplicaAttribute *in,
1406                                                  TALLOC_CTX *mem_ctx,
1407                                                  struct ldb_message_element *out)
1408 {
1409         unsigned int i;
1410
1411         out->flags      = 0;
1412         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1413         W_ERROR_HAVE_NO_MEMORY(out->name);
1414
1415         out->num_values = in->value_ctr.num_values;
1416         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1417         W_ERROR_HAVE_NO_MEMORY(out->values);
1418
1419         for (i=0; i < out->num_values; i++) {
1420                 char *str;
1421
1422                 if (in->value_ctr.values[i].blob == NULL) {
1423                         return WERR_FOOBAR;
1424                 }
1425
1426                 if (in->value_ctr.values[i].blob->length == 0) {
1427                         return WERR_FOOBAR;
1428                 }
1429
1430                 if (!convert_string_talloc(out->values,
1431                                            CH_UTF16, CH_UNIX,
1432                                            in->value_ctr.values[i].blob->data,
1433                                            in->value_ctr.values[i].blob->length,
1434                                            (void **)&str, NULL, false)) {
1435                         return WERR_FOOBAR;
1436                 }
1437
1438                 out->values[i] = data_blob_string_const(str);
1439         }
1440
1441         return WERR_OK;
1442 }
1443
1444 static WERROR dsdb_syntax_UNICODE_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1445                                                  const struct dsdb_attribute *attr,
1446                                                  const struct ldb_message_element *in,
1447                                                  TALLOC_CTX *mem_ctx,
1448                                                  struct drsuapi_DsReplicaAttribute *out)
1449 {
1450         unsigned int i;
1451         DATA_BLOB *blobs;
1452
1453         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1454                 return WERR_FOOBAR;
1455         }
1456
1457         out->attid                      = dsdb_attribute_get_attid(attr,
1458                                                                    ctx->is_schema_nc);
1459         out->value_ctr.num_values       = in->num_values;
1460         out->value_ctr.values           = talloc_array(mem_ctx,
1461                                                        struct drsuapi_DsAttributeValue,
1462                                                        in->num_values);
1463         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1464
1465         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1466         W_ERROR_HAVE_NO_MEMORY(blobs);
1467
1468         for (i=0; i < in->num_values; i++) {
1469                 out->value_ctr.values[i].blob   = &blobs[i];
1470
1471                 if (!convert_string_talloc(blobs,
1472                                            CH_UNIX, CH_UTF16,
1473                                            in->values[i].data, in->values[i].length,
1474                                            (void **)&blobs[i].data, &blobs[i].length, false)) {
1475                         return WERR_FOOBAR;
1476                 }
1477         }
1478
1479         return WERR_OK;
1480 }
1481
1482 static WERROR dsdb_syntax_UNICODE_validate_one_val(const struct dsdb_syntax_ctx *ctx,
1483                                                    const struct dsdb_attribute *attr,
1484                                                    const struct ldb_val *val)
1485 {
1486         void *dst = NULL;
1487         size_t size;
1488         bool ok;
1489
1490         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1491                 return WERR_FOOBAR;
1492         }
1493
1494         ok = convert_string_talloc(ctx->ldb,
1495                                    CH_UNIX, CH_UTF16,
1496                                    val->data,
1497                                    val->length,
1498                                    (void **)&dst,
1499                                    &size, false);
1500         TALLOC_FREE(dst);
1501         if (!ok) {
1502                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1503         }
1504
1505         if (attr->rangeLower) {
1506                 if ((size/2) < *attr->rangeLower) {
1507                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1508                 }
1509         }
1510
1511         if (attr->rangeUpper) {
1512                 if ((size/2) > *attr->rangeUpper) {
1513                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1514                 }
1515         }
1516
1517         return WERR_OK;
1518 }
1519
1520 static WERROR dsdb_syntax_UNICODE_validate_ldb(const struct dsdb_syntax_ctx *ctx,
1521                                                const struct dsdb_attribute *attr,
1522                                                const struct ldb_message_element *in)
1523 {
1524         WERROR status;
1525         unsigned int i;
1526
1527         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1528                 return WERR_FOOBAR;
1529         }
1530
1531         for (i=0; i < in->num_values; i++) {
1532                 if (in->values[i].length == 0) {
1533                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1534                 }
1535
1536                 status = dsdb_syntax_UNICODE_validate_one_val(ctx,
1537                                                               attr,
1538                                                               &in->values[i]);
1539                 if (!W_ERROR_IS_OK(status)) {
1540                         return status;
1541                 }
1542         }
1543
1544         return WERR_OK;
1545 }
1546
1547 static WERROR dsdb_syntax_one_DN_drsuapi_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
1548                                                 const struct dsdb_syntax *syntax,
1549                                                 const DATA_BLOB *in, DATA_BLOB *out)
1550 {
1551         struct drsuapi_DsReplicaObjectIdentifier3 id3;
1552         enum ndr_err_code ndr_err;
1553         DATA_BLOB guid_blob;
1554         struct ldb_dn *dn;
1555         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1556         int ret;
1557         NTSTATUS status;
1558
1559         if (!tmp_ctx) {
1560                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1561         }
1562
1563         if (in == NULL) {
1564                 talloc_free(tmp_ctx);
1565                 return WERR_FOOBAR;
1566         }
1567
1568         if (in->length == 0) {
1569                 talloc_free(tmp_ctx);
1570                 return WERR_FOOBAR;
1571         }
1572
1573
1574         /* windows sometimes sends an extra two pad bytes here */
1575         ndr_err = ndr_pull_struct_blob(in,
1576                                        tmp_ctx, &id3,
1577                                        (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3);
1578         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1579                 status = ndr_map_error2ntstatus(ndr_err);
1580                 talloc_free(tmp_ctx);
1581                 return ntstatus_to_werror(status);
1582         }
1583
1584         dn = ldb_dn_new(tmp_ctx, ldb, id3.dn);
1585         if (!dn) {
1586                 talloc_free(tmp_ctx);
1587                 /* If this fails, it must be out of memory, as it does not do much parsing */
1588                 W_ERROR_HAVE_NO_MEMORY(dn);
1589         }
1590
1591         if (!GUID_all_zero(&id3.guid)) {
1592                 status = GUID_to_ndr_blob(&id3.guid, tmp_ctx, &guid_blob);
1593                 if (!NT_STATUS_IS_OK(status)) {
1594                         talloc_free(tmp_ctx);
1595                         return ntstatus_to_werror(status);
1596                 }
1597
1598                 ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
1599                 if (ret != LDB_SUCCESS) {
1600                         talloc_free(tmp_ctx);
1601                         return WERR_FOOBAR;
1602                 }
1603                 talloc_free(guid_blob.data);
1604         }
1605
1606         if (id3.__ndr_size_sid) {
1607                 DATA_BLOB sid_blob;
1608                 ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, &id3.sid,
1609                                                (ndr_push_flags_fn_t)ndr_push_dom_sid);
1610                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1611                         status = ndr_map_error2ntstatus(ndr_err);
1612                         talloc_free(tmp_ctx);
1613                         return ntstatus_to_werror(status);
1614                 }
1615
1616                 ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
1617                 if (ret != LDB_SUCCESS) {
1618                         talloc_free(tmp_ctx);
1619                         return WERR_FOOBAR;
1620                 }
1621         }
1622
1623         *out = data_blob_string_const(ldb_dn_get_extended_linearized(mem_ctx, dn, 1));
1624         talloc_free(tmp_ctx);
1625         return WERR_OK;
1626 }
1627
1628 static WERROR dsdb_syntax_DN_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
1629                                             const struct dsdb_attribute *attr,
1630                                             const struct drsuapi_DsReplicaAttribute *in,
1631                                             TALLOC_CTX *mem_ctx,
1632                                             struct ldb_message_element *out)
1633 {
1634         unsigned int i;
1635
1636         out->flags      = 0;
1637         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1638         W_ERROR_HAVE_NO_MEMORY(out->name);
1639
1640         out->num_values = in->value_ctr.num_values;
1641         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1642         W_ERROR_HAVE_NO_MEMORY(out->values);
1643
1644         for (i=0; i < out->num_values; i++) {
1645                 WERROR status = dsdb_syntax_one_DN_drsuapi_to_ldb(out->values, ctx->ldb, attr->syntax,
1646                                                                   in->value_ctr.values[i].blob,
1647                                                                   &out->values[i]);
1648                 if (!W_ERROR_IS_OK(status)) {
1649                         return status;
1650                 }
1651
1652         }
1653
1654         return WERR_OK;
1655 }
1656
1657 static WERROR dsdb_syntax_DN_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1658                                             const struct dsdb_attribute *attr,
1659                                             const struct ldb_message_element *in,
1660                                             TALLOC_CTX *mem_ctx,
1661                                             struct drsuapi_DsReplicaAttribute *out)
1662 {
1663         unsigned int i;
1664         DATA_BLOB *blobs;
1665
1666         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1667                 return WERR_FOOBAR;
1668         }
1669
1670         out->attid                      = dsdb_attribute_get_attid(attr,
1671                                                                    ctx->is_schema_nc);
1672         out->value_ctr.num_values       = in->num_values;
1673         out->value_ctr.values           = talloc_array(mem_ctx,
1674                                                        struct drsuapi_DsAttributeValue,
1675                                                        in->num_values);
1676         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1677
1678         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1679         W_ERROR_HAVE_NO_MEMORY(blobs);
1680
1681         for (i=0; i < in->num_values; i++) {
1682                 struct drsuapi_DsReplicaObjectIdentifier3 id3;
1683                 enum ndr_err_code ndr_err;
1684                 struct ldb_dn *dn;
1685                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1686                 NTSTATUS status;
1687
1688                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1689
1690                 out->value_ctr.values[i].blob   = &blobs[i];
1691
1692                 dn = ldb_dn_from_ldb_val(tmp_ctx, ctx->ldb, &in->values[i]);
1693
1694                 W_ERROR_HAVE_NO_MEMORY(dn);
1695
1696                 ZERO_STRUCT(id3);
1697
1698                 status = dsdb_get_extended_dn_guid(dn, &id3.guid, "GUID");
1699                 if (!NT_STATUS_IS_OK(status) &&
1700                     !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1701                         talloc_free(tmp_ctx);
1702                         return ntstatus_to_werror(status);
1703                 }
1704
1705                 status = dsdb_get_extended_dn_sid(dn, &id3.sid, "SID");
1706                 if (!NT_STATUS_IS_OK(status) &&
1707                     !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1708                         talloc_free(tmp_ctx);
1709                         return ntstatus_to_werror(status);
1710                 }
1711
1712                 id3.dn = ldb_dn_get_linearized(dn);
1713
1714                 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
1715                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1716                         status = ndr_map_error2ntstatus(ndr_err);
1717                         talloc_free(tmp_ctx);
1718                         return ntstatus_to_werror(status);
1719                 }
1720                 talloc_free(tmp_ctx);
1721         }
1722
1723         return WERR_OK;
1724 }
1725
1726 static WERROR dsdb_syntax_DN_validate_one_val(const struct dsdb_syntax_ctx *ctx,
1727                                               const struct dsdb_attribute *attr,
1728                                               const struct ldb_val *val,
1729                                               TALLOC_CTX *mem_ctx,
1730                                               struct dsdb_dn **_dsdb_dn)
1731 {
1732         static const char * const extended_list[] = { "GUID", "SID", NULL };
1733         enum ndr_err_code ndr_err;
1734         struct GUID guid;
1735         struct dom_sid sid;
1736         const DATA_BLOB *sid_blob;
1737         struct dsdb_dn *dsdb_dn;
1738         struct ldb_dn *dn;
1739         char *dn_str;
1740         struct ldb_dn *dn2;
1741         char *dn2_str;
1742         int num_components;
1743         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1744         NTSTATUS status;
1745
1746         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1747
1748         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1749                 return WERR_FOOBAR;
1750         }
1751
1752         dsdb_dn = dsdb_dn_parse(tmp_ctx, ctx->ldb, val,
1753                                 attr->syntax->ldap_oid);
1754         if (!dsdb_dn) {
1755                 talloc_free(tmp_ctx);
1756                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1757         }
1758         dn = dsdb_dn->dn;
1759
1760         dn2 = ldb_dn_copy(tmp_ctx, dn);
1761         if (dn == NULL) {
1762                 talloc_free(tmp_ctx);
1763                 return WERR_NOMEM;
1764         }
1765
1766         num_components = ldb_dn_get_comp_num(dn);
1767
1768         status = dsdb_get_extended_dn_guid(dn, &guid, "GUID");
1769         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1770                 num_components++;
1771         } else if (!NT_STATUS_IS_OK(status)) {
1772                 talloc_free(tmp_ctx);
1773                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1774         }
1775
1776         sid_blob = ldb_dn_get_extended_component(dn, "SID");
1777         if (sid_blob) {
1778                 num_components++;
1779                 ndr_err = ndr_pull_struct_blob_all(sid_blob,
1780                                                    tmp_ctx,
1781                                                    &sid,
1782                                                    (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1783                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1784                         talloc_free(tmp_ctx);
1785                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1786                 }
1787         }
1788
1789         /* Do not allow links to the RootDSE */
1790         if (num_components == 0) {
1791                 talloc_free(tmp_ctx);
1792                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1793         }
1794
1795         /*
1796          * We need to check that only "GUID" and "SID" are
1797          * specified as extended components, we do that
1798          * by comparing the dn's after removing all components
1799          * from one dn and only the allowed subset from the other
1800          * one.
1801          */
1802         ldb_dn_extended_filter(dn, extended_list);
1803
1804         dn_str = ldb_dn_get_extended_linearized(tmp_ctx, dn, 0);
1805         if (dn_str == NULL) {
1806                 talloc_free(tmp_ctx);
1807                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1808         }
1809         dn2_str = ldb_dn_get_extended_linearized(tmp_ctx, dn2, 0);
1810         if (dn2_str == NULL) {
1811                 talloc_free(tmp_ctx);
1812                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1813         }
1814
1815         if (strcmp(dn_str, dn2_str) != 0) {
1816                 talloc_free(tmp_ctx);
1817                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1818         }
1819
1820         *_dsdb_dn = talloc_move(mem_ctx, &dsdb_dn);
1821         talloc_free(tmp_ctx);
1822         return WERR_OK;
1823 }
1824
1825 static WERROR dsdb_syntax_DN_validate_ldb(const struct dsdb_syntax_ctx *ctx,
1826                                           const struct dsdb_attribute *attr,
1827                                           const struct ldb_message_element *in)
1828 {
1829         unsigned int i;
1830
1831         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1832                 return WERR_FOOBAR;
1833         }
1834
1835         for (i=0; i < in->num_values; i++) {
1836                 WERROR status;
1837                 struct dsdb_dn *dsdb_dn;
1838                 TALLOC_CTX *tmp_ctx = talloc_new(ctx->ldb);
1839                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1840
1841                 status = dsdb_syntax_DN_validate_one_val(ctx,
1842                                                          attr,
1843                                                          &in->values[i],
1844                                                          tmp_ctx, &dsdb_dn);
1845                 if (!W_ERROR_IS_OK(status)) {
1846                         talloc_free(tmp_ctx);
1847                         return status;
1848                 }
1849
1850                 if (dsdb_dn->dn_format != DSDB_NORMAL_DN) {
1851                         talloc_free(tmp_ctx);
1852                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1853                 }
1854
1855                 talloc_free(tmp_ctx);
1856         }
1857
1858         return WERR_OK;
1859 }
1860
1861 static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
1862                                                    const struct dsdb_attribute *attr,
1863                                                    const struct drsuapi_DsReplicaAttribute *in,
1864                                                    TALLOC_CTX *mem_ctx,
1865                                                    struct ldb_message_element *out)
1866 {
1867         unsigned int i;
1868         int ret;
1869
1870         out->flags      = 0;
1871         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1872         W_ERROR_HAVE_NO_MEMORY(out->name);
1873
1874         out->num_values = in->value_ctr.num_values;
1875         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1876         W_ERROR_HAVE_NO_MEMORY(out->values);
1877
1878         for (i=0; i < out->num_values; i++) {
1879                 struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
1880                 enum ndr_err_code ndr_err;
1881                 DATA_BLOB guid_blob;
1882                 struct ldb_dn *dn;
1883                 struct dsdb_dn *dsdb_dn;
1884                 NTSTATUS status;
1885                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1886                 if (!tmp_ctx) {
1887                         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1888                 }
1889
1890                 if (in->value_ctr.values[i].blob == NULL) {
1891                         talloc_free(tmp_ctx);
1892                         return WERR_FOOBAR;
1893                 }
1894
1895                 if (in->value_ctr.values[i].blob->length == 0) {
1896                         talloc_free(tmp_ctx);
1897                         return WERR_FOOBAR;
1898                 }
1899
1900
1901                 /* windows sometimes sends an extra two pad bytes here */
1902                 ndr_err = ndr_pull_struct_blob(in->value_ctr.values[i].blob,
1903                                                tmp_ctx, &id3,
1904                                                (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3Binary);
1905                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1906                         status = ndr_map_error2ntstatus(ndr_err);
1907                         talloc_free(tmp_ctx);
1908                         return ntstatus_to_werror(status);
1909                 }
1910
1911                 dn = ldb_dn_new(tmp_ctx, ctx->ldb, id3.dn);
1912                 if (!dn) {
1913                         talloc_free(tmp_ctx);
1914                         /* If this fails, it must be out of memory, as it does not do much parsing */
1915                         W_ERROR_HAVE_NO_MEMORY(dn);
1916                 }
1917
1918                 status = GUID_to_ndr_blob(&id3.guid, tmp_ctx, &guid_blob);
1919                 if (!NT_STATUS_IS_OK(status)) {
1920                         talloc_free(tmp_ctx);
1921                         return ntstatus_to_werror(status);
1922                 }
1923
1924                 ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
1925                 if (ret != LDB_SUCCESS) {
1926                         talloc_free(tmp_ctx);
1927                         return WERR_FOOBAR;
1928                 }
1929
1930                 talloc_free(guid_blob.data);
1931
1932                 if (id3.__ndr_size_sid) {
1933                         DATA_BLOB sid_blob;
1934                         ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, &id3.sid,
1935                                                        (ndr_push_flags_fn_t)ndr_push_dom_sid);
1936                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1937                                 status = ndr_map_error2ntstatus(ndr_err);
1938                                 talloc_free(tmp_ctx);
1939                                 return ntstatus_to_werror(status);
1940                         }
1941
1942                         ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
1943                         if (ret != LDB_SUCCESS) {
1944                                 talloc_free(tmp_ctx);
1945                                 return WERR_FOOBAR;
1946                         }
1947                 }
1948
1949                 /* set binary stuff */
1950                 dsdb_dn = dsdb_dn_construct(tmp_ctx, dn, id3.binary, attr->syntax->ldap_oid);
1951                 if (!dsdb_dn) {
1952                         /* If this fails, it must be out of memory, we know the ldap_oid is valid */
1953                         talloc_free(tmp_ctx);
1954                         W_ERROR_HAVE_NO_MEMORY(dsdb_dn);
1955                 }
1956                 out->values[i] = data_blob_string_const(dsdb_dn_get_extended_linearized(out->values, dsdb_dn, 1));
1957                 talloc_free(tmp_ctx);
1958         }
1959
1960         return WERR_OK;
1961 }
1962
1963 static WERROR dsdb_syntax_DN_BINARY_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1964                                                    const struct dsdb_attribute *attr,
1965                                                    const struct ldb_message_element *in,
1966                                                    TALLOC_CTX *mem_ctx,
1967                                                    struct drsuapi_DsReplicaAttribute *out)
1968 {
1969         unsigned int i;
1970         DATA_BLOB *blobs;
1971
1972         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1973                 return WERR_FOOBAR;
1974         }
1975
1976         out->attid                      = dsdb_attribute_get_attid(attr,
1977                                                                    ctx->is_schema_nc);
1978         out->value_ctr.num_values       = in->num_values;
1979         out->value_ctr.values           = talloc_array(mem_ctx,
1980                                                        struct drsuapi_DsAttributeValue,
1981                                                        in->num_values);
1982         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1983
1984         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1985         W_ERROR_HAVE_NO_MEMORY(blobs);
1986
1987         for (i=0; i < in->num_values; i++) {
1988                 struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
1989                 enum ndr_err_code ndr_err;
1990                 const DATA_BLOB *sid_blob;
1991                 struct dsdb_dn *dsdb_dn;
1992                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1993                 NTSTATUS status;
1994
1995                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1996
1997                 out->value_ctr.values[i].blob   = &blobs[i];
1998
1999                 dsdb_dn = dsdb_dn_parse(tmp_ctx, ctx->ldb, &in->values[i], attr->syntax->ldap_oid);
2000
2001                 if (!dsdb_dn) {
2002                         talloc_free(tmp_ctx);
2003                         return ntstatus_to_werror(NT_STATUS_INVALID_PARAMETER);
2004                 }
2005
2006                 ZERO_STRUCT(id3);
2007
2008                 status = dsdb_get_extended_dn_guid(dsdb_dn->dn, &id3.guid, "GUID");
2009                 if (!NT_STATUS_IS_OK(status) &&
2010                     !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2011                         talloc_free(tmp_ctx);
2012                         return ntstatus_to_werror(status);
2013                 }
2014
2015                 sid_blob = ldb_dn_get_extended_component(dsdb_dn->dn, "SID");
2016                 if (sid_blob) {
2017
2018                         ndr_err = ndr_pull_struct_blob_all(sid_blob,
2019                                                            tmp_ctx, &id3.sid,
2020                                                            (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
2021                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2022                                 status = ndr_map_error2ntstatus(ndr_err);
2023                                 talloc_free(tmp_ctx);
2024                                 return ntstatus_to_werror(status);
2025                         }
2026                 }
2027
2028                 id3.dn = ldb_dn_get_linearized(dsdb_dn->dn);
2029
2030                 /* get binary stuff */
2031                 id3.binary = dsdb_dn->extra_part;
2032
2033                 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3Binary);
2034                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2035                         status = ndr_map_error2ntstatus(ndr_err);
2036                         talloc_free(tmp_ctx);
2037                         return ntstatus_to_werror(status);
2038                 }
2039                 talloc_free(tmp_ctx);
2040         }
2041
2042         return WERR_OK;
2043 }
2044
2045 static WERROR dsdb_syntax_DN_BINARY_validate_ldb(const struct dsdb_syntax_ctx *ctx,
2046                                                  const struct dsdb_attribute *attr,
2047                                                  const struct ldb_message_element *in)
2048 {
2049         unsigned int i;
2050
2051         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
2052                 return WERR_FOOBAR;
2053         }
2054
2055         for (i=0; i < in->num_values; i++) {
2056                 WERROR status;
2057                 struct dsdb_dn *dsdb_dn;
2058                 TALLOC_CTX *tmp_ctx = talloc_new(ctx->ldb);
2059                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
2060
2061                 status = dsdb_syntax_DN_validate_one_val(ctx,
2062                                                          attr,
2063                                                          &in->values[i],
2064                                                          tmp_ctx, &dsdb_dn);
2065                 if (!W_ERROR_IS_OK(status)) {
2066                         talloc_free(tmp_ctx);
2067                         return status;
2068                 }
2069
2070                 if (dsdb_dn->dn_format != DSDB_BINARY_DN) {
2071                         talloc_free(tmp_ctx);
2072                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
2073                 }
2074
2075                 status = dsdb_syntax_DATA_BLOB_validate_one_val(ctx,
2076                                                                 attr,
2077                                                                 &dsdb_dn->extra_part);
2078                 if (!W_ERROR_IS_OK(status)) {
2079                         talloc_free(tmp_ctx);
2080                         return status;
2081                 }
2082
2083                 talloc_free(tmp_ctx);
2084         }
2085
2086         return WERR_OK;
2087 }
2088
2089 static WERROR dsdb_syntax_DN_STRING_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
2090                                                    const struct dsdb_attribute *attr,
2091                                                    const struct drsuapi_DsReplicaAttribute *in,
2092                                                    TALLOC_CTX *mem_ctx,
2093                                                    struct ldb_message_element *out)
2094 {
2095         return dsdb_syntax_DN_BINARY_drsuapi_to_ldb(ctx,
2096                                                     attr,
2097                                                     in,
2098                                                     mem_ctx,
2099                                                     out);
2100 }
2101
2102 static WERROR dsdb_syntax_DN_STRING_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
2103                                                    const struct dsdb_attribute *attr,
2104                                                    const struct ldb_message_element *in,
2105                                                    TALLOC_CTX *mem_ctx,
2106                                                    struct drsuapi_DsReplicaAttribute *out)
2107 {
2108         return dsdb_syntax_DN_BINARY_ldb_to_drsuapi(ctx,
2109                                                     attr,
2110                                                     in,
2111                                                     mem_ctx,
2112                                                     out);
2113 }
2114
2115 static WERROR dsdb_syntax_DN_STRING_validate_ldb(const struct dsdb_syntax_ctx *ctx,
2116                                                  const struct dsdb_attribute *attr,
2117                                                  const struct ldb_message_element *in)
2118 {
2119         unsigned int i;
2120
2121         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
2122                 return WERR_FOOBAR;
2123         }
2124
2125         for (i=0; i < in->num_values; i++) {
2126                 WERROR status;
2127                 struct dsdb_dn *dsdb_dn;
2128                 TALLOC_CTX *tmp_ctx = talloc_new(ctx->ldb);
2129                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
2130
2131                 status = dsdb_syntax_DN_validate_one_val(ctx,
2132                                                          attr,
2133                                                          &in->values[i],
2134                                                          tmp_ctx, &dsdb_dn);
2135                 if (!W_ERROR_IS_OK(status)) {
2136                         talloc_free(tmp_ctx);
2137                         return status;
2138                 }
2139
2140                 if (dsdb_dn->dn_format != DSDB_STRING_DN) {
2141                         talloc_free(tmp_ctx);
2142                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
2143                 }
2144
2145                 status = dsdb_syntax_UNICODE_validate_one_val(ctx,
2146                                                               attr,
2147                                                               &dsdb_dn->extra_part);
2148                 if (!W_ERROR_IS_OK(status)) {
2149                         talloc_free(tmp_ctx);
2150                         return status;
2151                 }
2152
2153                 talloc_free(tmp_ctx);
2154         }
2155
2156         return WERR_OK;
2157 }
2158
2159 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
2160                                                               const struct dsdb_attribute *attr,
2161                                                               const struct drsuapi_DsReplicaAttribute *in,
2162                                                               TALLOC_CTX *mem_ctx,
2163                                                               struct ldb_message_element *out)
2164 {
2165         unsigned int i;
2166
2167         out->flags      = 0;
2168         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
2169         W_ERROR_HAVE_NO_MEMORY(out->name);
2170
2171         out->num_values = in->value_ctr.num_values;
2172         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
2173         W_ERROR_HAVE_NO_MEMORY(out->values);
2174
2175         for (i=0; i < out->num_values; i++) {
2176                 size_t len;
2177                 char *str;
2178
2179                 if (in->value_ctr.values[i].blob == NULL) {
2180                         return WERR_FOOBAR;
2181                 }
2182
2183                 if (in->value_ctr.values[i].blob->length < 4) {
2184                         return WERR_FOOBAR;
2185                 }
2186
2187                 len = IVAL(in->value_ctr.values[i].blob->data, 0);
2188
2189                 if (len != in->value_ctr.values[i].blob->length) {
2190                         return WERR_FOOBAR;
2191                 }
2192
2193                 if (!convert_string_talloc(out->values, CH_UTF16, CH_UNIX,
2194                                            in->value_ctr.values[i].blob->data+4,
2195                                            in->value_ctr.values[i].blob->length-4,
2196                                            (void **)&str, NULL, false)) {
2197                         return WERR_FOOBAR;
2198                 }
2199
2200                 out->values[i] = data_blob_string_const(str);
2201         }
2202
2203         return WERR_OK;
2204 }
2205
2206 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
2207                                                               const struct dsdb_attribute *attr,
2208                                                               const struct ldb_message_element *in,
2209                                                               TALLOC_CTX *mem_ctx,
2210                                                               struct drsuapi_DsReplicaAttribute *out)
2211 {
2212         unsigned int i;
2213         DATA_BLOB *blobs;
2214
2215         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
2216                 return WERR_FOOBAR;
2217         }
2218
2219         out->attid                      = dsdb_attribute_get_attid(attr,
2220                                                                    ctx->is_schema_nc);
2221         out->value_ctr.num_values       = in->num_values;
2222         out->value_ctr.values           = talloc_array(mem_ctx,
2223                                                        struct drsuapi_DsAttributeValue,
2224                                                        in->num_values);
2225         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
2226
2227         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
2228         W_ERROR_HAVE_NO_MEMORY(blobs);
2229
2230         for (i=0; i < in->num_values; i++) {
2231                 uint8_t *data;
2232                 size_t ret;
2233
2234                 out->value_ctr.values[i].blob   = &blobs[i];
2235
2236                 if (!convert_string_talloc(blobs, CH_UNIX, CH_UTF16,
2237                                            in->values[i].data,
2238                                            in->values[i].length,
2239                                            (void **)&data, &ret, false)) {
2240                         return WERR_FOOBAR;
2241                 }
2242
2243                 blobs[i] = data_blob_talloc(blobs, NULL, 4 + ret);
2244                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
2245
2246                 SIVAL(blobs[i].data, 0, 4 + ret);
2247
2248                 if (ret > 0) {
2249                         memcpy(blobs[i].data + 4, data, ret);
2250                         talloc_free(data);
2251                 }
2252         }
2253
2254         return WERR_OK;
2255 }
2256
2257 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_validate_ldb(const struct dsdb_syntax_ctx *ctx,
2258                                                             const struct dsdb_attribute *attr,
2259                                                             const struct ldb_message_element *in)
2260 {
2261         return dsdb_syntax_UNICODE_validate_ldb(ctx,
2262                                                 attr,
2263                                                 in);
2264 }
2265
2266 #define OMOBJECTCLASS(val) { .length = sizeof(val) - 1, .data = discard_const_p(uint8_t, val) }
2267
2268 static const struct dsdb_syntax dsdb_syntaxes[] = {
2269         {
2270                 .name                   = "Boolean",
2271                 .ldap_oid               = LDB_SYNTAX_BOOLEAN,
2272                 .oMSyntax               = 1,
2273                 .attributeSyntax_oid    = "2.5.5.8",
2274                 .drsuapi_to_ldb         = dsdb_syntax_BOOL_drsuapi_to_ldb,
2275                 .ldb_to_drsuapi         = dsdb_syntax_BOOL_ldb_to_drsuapi,
2276                 .validate_ldb           = dsdb_syntax_BOOL_validate_ldb,
2277                 .equality               = "booleanMatch",
2278                 .comment                = "Boolean"
2279         },{
2280                 .name                   = "Integer",
2281                 .ldap_oid               = LDB_SYNTAX_INTEGER,
2282                 .oMSyntax               = 2,
2283                 .attributeSyntax_oid    = "2.5.5.9",
2284                 .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
2285                 .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
2286                 .validate_ldb           = dsdb_syntax_INT32_validate_ldb,
2287                 .equality               = "integerMatch",
2288                 .comment                = "Integer",
2289                 .ldb_syntax             = LDB_SYNTAX_SAMBA_INT32
2290         },{
2291                 .name                   = "String(Octet)",
2292                 .ldap_oid               = LDB_SYNTAX_OCTET_STRING,
2293                 .oMSyntax               = 4,
2294                 .attributeSyntax_oid    = "2.5.5.10",
2295                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2296                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2297                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2298                 .equality               = "octetStringMatch",
2299                 .comment                = "Octet String",
2300         },{
2301                 .name                   = "String(Sid)",
2302                 .ldap_oid               = LDB_SYNTAX_OCTET_STRING,
2303                 .oMSyntax               = 4,
2304                 .attributeSyntax_oid    = "2.5.5.17",
2305                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2306                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2307                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2308                 .equality               = "octetStringMatch",
2309                 .comment                = "Octet String - Security Identifier (SID)",
2310                 .ldb_syntax             = LDB_SYNTAX_SAMBA_SID
2311         },{
2312                 .name                   = "String(Object-Identifier)",
2313                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.38",
2314                 .oMSyntax               = 6,
2315                 .attributeSyntax_oid    = "2.5.5.2",
2316                 .drsuapi_to_ldb         = dsdb_syntax_OID_drsuapi_to_ldb,
2317                 .ldb_to_drsuapi         = dsdb_syntax_OID_ldb_to_drsuapi,
2318                 .validate_ldb           = dsdb_syntax_OID_validate_ldb,
2319                 .equality               = "caseIgnoreMatch", /* Would use "objectIdentifierMatch" but most are ldap attribute/class names */
2320                 .comment                = "OID String",
2321                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING
2322         },{
2323                 .name                   = "Enumeration",
2324                 .ldap_oid               = LDB_SYNTAX_INTEGER,
2325                 .oMSyntax               = 10,
2326                 .attributeSyntax_oid    = "2.5.5.9",
2327                 .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
2328                 .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
2329                 .validate_ldb           = dsdb_syntax_INT32_validate_ldb,
2330                 .ldb_syntax             = LDB_SYNTAX_SAMBA_INT32
2331         },{
2332         /* not used in w2k3 forest */
2333                 .name                   = "String(Numeric)",
2334                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.36",
2335                 .oMSyntax               = 18,
2336                 .attributeSyntax_oid    = "2.5.5.6",
2337                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2338                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2339                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2340                 .equality               = "numericStringMatch",
2341                 .substring              = "numericStringSubstringsMatch",
2342                 .comment                = "Numeric String",
2343                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
2344         },{
2345                 .name                   = "String(Printable)",
2346                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.44",
2347                 .oMSyntax               = 19,
2348                 .attributeSyntax_oid    = "2.5.5.5",
2349                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2350                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2351                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2352                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
2353         },{
2354                 .name                   = "String(Teletex)",
2355                 .ldap_oid               = "1.2.840.113556.1.4.905",
2356                 .oMSyntax               = 20,
2357                 .attributeSyntax_oid    = "2.5.5.4",
2358                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2359                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2360                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2361                 .equality               = "caseIgnoreMatch",
2362                 .substring              = "caseIgnoreSubstringsMatch",
2363                 .comment                = "Case Insensitive String",
2364                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
2365         },{
2366                 .name                   = "String(IA5)",
2367                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.26",
2368                 .oMSyntax               = 22,
2369                 .attributeSyntax_oid    = "2.5.5.5",
2370                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2371                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2372                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2373                 .equality               = "caseExactIA5Match",
2374                 .comment                = "Printable String",
2375                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
2376         },{
2377                 .name                   = "String(UTC-Time)",
2378                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.53",
2379                 .oMSyntax               = 23,
2380                 .attributeSyntax_oid    = "2.5.5.11",
2381                 .drsuapi_to_ldb         = dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb,
2382                 .ldb_to_drsuapi         = dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi,
2383                 .validate_ldb           = dsdb_syntax_NTTIME_UTC_validate_ldb,
2384                 .equality               = "generalizedTimeMatch",
2385                 .comment                = "UTC Time",
2386         },{
2387                 .name                   = "String(Generalized-Time)",
2388                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.24",
2389                 .oMSyntax               = 24,
2390                 .attributeSyntax_oid    = "2.5.5.11",
2391                 .drsuapi_to_ldb         = dsdb_syntax_NTTIME_drsuapi_to_ldb,
2392                 .ldb_to_drsuapi         = dsdb_syntax_NTTIME_ldb_to_drsuapi,
2393                 .validate_ldb           = dsdb_syntax_NTTIME_validate_ldb,
2394                 .equality               = "generalizedTimeMatch",
2395                 .comment                = "Generalized Time",
2396                 .ldb_syntax             = LDB_SYNTAX_UTC_TIME,
2397         },{
2398         /* not used in w2k3 schema */
2399                 .name                   = "String(Case Sensitive)",
2400                 .ldap_oid               = "1.2.840.113556.1.4.1362",
2401                 .oMSyntax               = 27,
2402                 .attributeSyntax_oid    = "2.5.5.3",
2403                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2404                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2405                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2406                 .equality               = "caseExactMatch",
2407                 .substring              = "caseExactSubstringsMatch",
2408                 /* TODO (kim): according to LDAP rfc we should be using same comparison
2409                  * as Directory String (LDB_SYNTAX_DIRECTORY_STRING), but case sensitive.
2410                  * But according to ms docs binary compare should do the job:
2411                  * http://msdn.microsoft.com/en-us/library/cc223200(v=PROT.10).aspx */
2412                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
2413         },{
2414                 .name                   = "String(Unicode)",
2415                 .ldap_oid               = LDB_SYNTAX_DIRECTORY_STRING,
2416                 .oMSyntax               = 64,
2417                 .attributeSyntax_oid    = "2.5.5.12",
2418                 .drsuapi_to_ldb         = dsdb_syntax_UNICODE_drsuapi_to_ldb,
2419                 .ldb_to_drsuapi         = dsdb_syntax_UNICODE_ldb_to_drsuapi,
2420                 .validate_ldb           = dsdb_syntax_UNICODE_validate_ldb,
2421                 .equality               = "caseIgnoreMatch",
2422                 .substring              = "caseIgnoreSubstringsMatch",
2423                 .comment                = "Directory String",
2424         },{
2425                 .name                   = "Interval/LargeInteger",
2426                 .ldap_oid               = "1.2.840.113556.1.4.906",
2427                 .oMSyntax               = 65,
2428                 .attributeSyntax_oid    = "2.5.5.16",
2429                 .drsuapi_to_ldb         = dsdb_syntax_INT64_drsuapi_to_ldb,
2430                 .ldb_to_drsuapi         = dsdb_syntax_INT64_ldb_to_drsuapi,
2431                 .validate_ldb           = dsdb_syntax_INT64_validate_ldb,
2432                 .equality               = "integerMatch",
2433                 .comment                = "Large Integer",
2434                 .ldb_syntax             = LDB_SYNTAX_INTEGER,
2435         },{
2436                 .name                   = "String(NT-Sec-Desc)",
2437                 .ldap_oid               = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
2438                 .oMSyntax               = 66,
2439                 .attributeSyntax_oid    = "2.5.5.15",
2440                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2441                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2442                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2443         },{
2444                 .name                   = "Object(DS-DN)",
2445                 .ldap_oid               = LDB_SYNTAX_DN,
2446                 .oMSyntax               = 127,
2447                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x4a"),
2448                 .attributeSyntax_oid    = "2.5.5.1",
2449                 .drsuapi_to_ldb         = dsdb_syntax_DN_drsuapi_to_ldb,
2450                 .ldb_to_drsuapi         = dsdb_syntax_DN_ldb_to_drsuapi,
2451                 .validate_ldb           = dsdb_syntax_DN_validate_ldb,
2452                 .equality               = "distinguishedNameMatch",
2453                 .comment                = "Object(DS-DN) == a DN",
2454         },{
2455                 .name                   = "Object(DN-Binary)",
2456                 .ldap_oid               = DSDB_SYNTAX_BINARY_DN,
2457                 .oMSyntax               = 127,
2458                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0b"),
2459                 .attributeSyntax_oid    = "2.5.5.7",
2460                 .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
2461                 .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
2462                 .validate_ldb           = dsdb_syntax_DN_BINARY_validate_ldb,
2463                 .equality               = "octetStringMatch",
2464                 .comment                = "OctetString: Binary+DN",
2465         },{
2466         /* not used in w2k3 schema, but used in Exchange schema*/
2467                 .name                   = "Object(OR-Name)",
2468                 .ldap_oid               = DSDB_SYNTAX_OR_NAME,
2469                 .oMSyntax               = 127,
2470                 .oMObjectClass          = OMOBJECTCLASS("\x56\x06\x01\x02\x05\x0b\x1D"),
2471                 .attributeSyntax_oid    = "2.5.5.7",
2472                 .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
2473                 .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
2474                 .validate_ldb           = dsdb_syntax_DN_BINARY_validate_ldb,
2475                 .equality               = "caseIgnoreMatch",
2476                 .ldb_syntax             = LDB_SYNTAX_DN,
2477         },{
2478         /*
2479          * TODO: verify if DATA_BLOB is correct here...!
2480          *
2481          *       repsFrom and repsTo are the only attributes using
2482          *       this attribute syntax, but they're not replicated...
2483          */
2484                 .name                   = "Object(Replica-Link)",
2485                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.40",
2486                 .oMSyntax               = 127,
2487                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x06"),
2488                 .attributeSyntax_oid    = "2.5.5.10",
2489                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2490                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2491                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2492         },{
2493                 .name                   = "Object(Presentation-Address)",
2494                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.43",
2495                 .oMSyntax               = 127,
2496                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x5c"),
2497                 .attributeSyntax_oid    = "2.5.5.13",
2498                 .drsuapi_to_ldb         = dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb,
2499                 .ldb_to_drsuapi         = dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi,
2500                 .validate_ldb           = dsdb_syntax_PRESENTATION_ADDRESS_validate_ldb,
2501                 .comment                = "Presentation Address",
2502                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
2503         },{
2504         /* not used in w2k3 schema */
2505                 .name                   = "Object(Access-Point)",
2506                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.2",
2507                 .oMSyntax               = 127,
2508                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x3e"),
2509                 .attributeSyntax_oid    = "2.5.5.14",
2510                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
2511                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
2512                 .validate_ldb           = dsdb_syntax_FOOBAR_validate_ldb,
2513                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
2514         },{
2515         /* not used in w2k3 schema */
2516                 .name                   = "Object(DN-String)",
2517                 .ldap_oid               = DSDB_SYNTAX_STRING_DN,
2518                 .oMSyntax               = 127,
2519                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0c"),
2520                 .attributeSyntax_oid    = "2.5.5.14",
2521                 .drsuapi_to_ldb         = dsdb_syntax_DN_STRING_drsuapi_to_ldb,
2522                 .ldb_to_drsuapi         = dsdb_syntax_DN_STRING_ldb_to_drsuapi,
2523                 .validate_ldb           = dsdb_syntax_DN_STRING_validate_ldb,
2524                 .equality               = "octetStringMatch",
2525                 .comment                = "OctetString: String+DN",
2526         }
2527 };
2528
2529 const struct dsdb_syntax *find_syntax_map_by_ad_oid(const char *ad_oid)
2530 {
2531         unsigned int i;
2532         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
2533                 if (strcasecmp(ad_oid, dsdb_syntaxes[i].attributeSyntax_oid) == 0) {
2534                         return &dsdb_syntaxes[i];
2535                 }
2536         }
2537         return NULL;
2538 }
2539
2540 const struct dsdb_syntax *find_syntax_map_by_ad_syntax(int oMSyntax)
2541 {
2542         unsigned int i;
2543         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
2544                 if (oMSyntax == dsdb_syntaxes[i].oMSyntax) {
2545                         return &dsdb_syntaxes[i];
2546                 }
2547         }
2548         return NULL;
2549 }
2550
2551 const struct dsdb_syntax *find_syntax_map_by_standard_oid(const char *standard_oid)
2552 {
2553         unsigned int i;
2554         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
2555                 if (strcasecmp(standard_oid, dsdb_syntaxes[i].ldap_oid) == 0) {
2556                         return &dsdb_syntaxes[i];
2557                 }
2558         }
2559         return NULL;
2560 }
2561
2562 const struct dsdb_syntax *dsdb_syntax_for_attribute(const struct dsdb_attribute *attr)
2563 {
2564         unsigned int i;
2565
2566         for (i=0; i < ARRAY_SIZE(dsdb_syntaxes); i++) {
2567                 if (attr->oMSyntax != dsdb_syntaxes[i].oMSyntax) continue;
2568
2569                 if (attr->oMObjectClass.length != dsdb_syntaxes[i].oMObjectClass.length) continue;
2570
2571                 if (attr->oMObjectClass.length) {
2572                         int ret;
2573                         ret = memcmp(attr->oMObjectClass.data,
2574                                      dsdb_syntaxes[i].oMObjectClass.data,
2575                                      attr->oMObjectClass.length);
2576                         if (ret != 0) continue;
2577                 }
2578
2579                 if (strcmp(attr->attributeSyntax_oid, dsdb_syntaxes[i].attributeSyntax_oid) != 0) continue;
2580
2581                 return &dsdb_syntaxes[i];
2582         }
2583
2584         return NULL;
2585 }
2586
2587 WERROR dsdb_attribute_drsuapi_to_ldb(struct ldb_context *ldb,
2588                                      const struct dsdb_schema *schema,
2589                                      const struct drsuapi_DsReplicaAttribute *in,
2590                                      TALLOC_CTX *mem_ctx,
2591                                      struct ldb_message_element *out)
2592 {
2593         const struct dsdb_attribute *sa;
2594         struct dsdb_syntax_ctx syntax_ctx;
2595
2596         sa = dsdb_attribute_by_attributeID_id(schema, in->attid);
2597         if (!sa) {
2598                 return WERR_FOOBAR;
2599         }
2600
2601         /* use default syntax conversion context */
2602         dsdb_syntax_ctx_init(&syntax_ctx, ldb, schema);
2603
2604         return sa->syntax->drsuapi_to_ldb(&syntax_ctx, sa, in, mem_ctx, out);
2605 }
2606
2607 WERROR dsdb_attribute_ldb_to_drsuapi(struct ldb_context *ldb,
2608                                      const struct dsdb_schema *schema,
2609                                      const struct ldb_message_element *in,
2610                                      TALLOC_CTX *mem_ctx,
2611                                      struct drsuapi_DsReplicaAttribute *out)
2612 {
2613         const struct dsdb_attribute *sa;
2614         struct dsdb_syntax_ctx syntax_ctx;
2615
2616         sa = dsdb_attribute_by_lDAPDisplayName(schema, in->name);
2617         if (!sa) {
2618                 return WERR_FOOBAR;
2619         }
2620
2621         /* use default syntax conversion context */
2622         dsdb_syntax_ctx_init(&syntax_ctx, ldb, schema);
2623
2624         return sa->syntax->ldb_to_drsuapi(&syntax_ctx, sa, in, mem_ctx, out);
2625 }
2626