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