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