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