s4:dsdb: add validate_update module
[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_INT32_drsuapi_to_ldb(struct ldb_context *ldb, 
186                                                const struct dsdb_schema *schema,
187                                                const struct dsdb_attribute *attr,
188                                                const struct drsuapi_DsReplicaAttribute *in,
189                                                TALLOC_CTX *mem_ctx,
190                                                struct ldb_message_element *out)
191 {
192         uint32_t i;
193
194         out->flags      = 0;
195         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
196         W_ERROR_HAVE_NO_MEMORY(out->name);
197
198         out->num_values = in->value_ctr.num_values;
199         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
200         W_ERROR_HAVE_NO_MEMORY(out->values);
201
202         for (i=0; i < out->num_values; i++) {
203                 int32_t v;
204                 char *str;
205
206                 if (in->value_ctr.values[i].blob == NULL) {
207                         return WERR_FOOBAR;
208                 }
209
210                 if (in->value_ctr.values[i].blob->length != 4) {
211                         return WERR_FOOBAR;
212                 }
213
214                 v = IVALS(in->value_ctr.values[i].blob->data, 0);
215
216                 str = talloc_asprintf(out->values, "%d", v);
217                 W_ERROR_HAVE_NO_MEMORY(str);
218
219                 out->values[i] = data_blob_string_const(str);
220         }
221
222         return WERR_OK;
223 }
224
225 static WERROR dsdb_syntax_INT32_ldb_to_drsuapi(struct ldb_context *ldb, 
226                                                const struct dsdb_schema *schema,
227                                                const struct dsdb_attribute *attr,
228                                                const struct ldb_message_element *in,
229                                                TALLOC_CTX *mem_ctx,
230                                                struct drsuapi_DsReplicaAttribute *out)
231 {
232         uint32_t i;
233         DATA_BLOB *blobs;
234
235         if (attr->attributeID_id == 0xFFFFFFFF) {
236                 return WERR_FOOBAR;
237         }
238
239         out->attid                      = attr->attributeID_id;
240         out->value_ctr.num_values       = in->num_values;
241         out->value_ctr.values           = talloc_array(mem_ctx,
242                                                        struct drsuapi_DsAttributeValue,
243                                                        in->num_values);
244         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
245
246         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
247         W_ERROR_HAVE_NO_MEMORY(blobs);
248
249         for (i=0; i < in->num_values; i++) {
250                 int32_t v;
251
252                 out->value_ctr.values[i].blob   = &blobs[i];
253
254                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
255                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
256
257                 /* We've to use "strtoll" here to have the intended overflows.
258                  * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
259                 v = (int32_t) strtoll((char *)in->values[i].data, NULL, 0);
260
261                 SIVALS(blobs[i].data, 0, v);
262         }
263
264         return WERR_OK;
265 }
266
267 static WERROR dsdb_syntax_INT64_drsuapi_to_ldb(struct ldb_context *ldb, 
268                                                const struct dsdb_schema *schema,
269                                                const struct dsdb_attribute *attr,
270                                                const struct drsuapi_DsReplicaAttribute *in,
271                                                TALLOC_CTX *mem_ctx,
272                                                struct ldb_message_element *out)
273 {
274         uint32_t i;
275
276         out->flags      = 0;
277         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
278         W_ERROR_HAVE_NO_MEMORY(out->name);
279
280         out->num_values = in->value_ctr.num_values;
281         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
282         W_ERROR_HAVE_NO_MEMORY(out->values);
283
284         for (i=0; i < out->num_values; i++) {
285                 int64_t v;
286                 char *str;
287
288                 if (in->value_ctr.values[i].blob == NULL) {
289                         return WERR_FOOBAR;
290                 }
291
292                 if (in->value_ctr.values[i].blob->length != 8) {
293                         return WERR_FOOBAR;
294                 }
295
296                 v = BVALS(in->value_ctr.values[i].blob->data, 0);
297
298                 str = talloc_asprintf(out->values, "%lld", (long long int)v);
299                 W_ERROR_HAVE_NO_MEMORY(str);
300
301                 out->values[i] = data_blob_string_const(str);
302         }
303
304         return WERR_OK;
305 }
306
307 static WERROR dsdb_syntax_INT64_ldb_to_drsuapi(struct ldb_context *ldb, 
308                                                const struct dsdb_schema *schema,
309                                                const struct dsdb_attribute *attr,
310                                                const struct ldb_message_element *in,
311                                                TALLOC_CTX *mem_ctx,
312                                                struct drsuapi_DsReplicaAttribute *out)
313 {
314         uint32_t i;
315         DATA_BLOB *blobs;
316
317         if (attr->attributeID_id == 0xFFFFFFFF) {
318                 return WERR_FOOBAR;
319         }
320
321         out->attid                      = attr->attributeID_id;
322         out->value_ctr.num_values       = in->num_values;
323         out->value_ctr.values           = talloc_array(mem_ctx,
324                                                        struct drsuapi_DsAttributeValue,
325                                                        in->num_values);
326         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
327
328         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
329         W_ERROR_HAVE_NO_MEMORY(blobs);
330
331         for (i=0; i < in->num_values; i++) {
332                 int64_t v;
333
334                 out->value_ctr.values[i].blob   = &blobs[i];
335
336                 blobs[i] = data_blob_talloc(blobs, NULL, 8);
337                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
338
339                 v = strtoll((const char *)in->values[i].data, NULL, 10);
340
341                 SBVALS(blobs[i].data, 0, v);
342         }
343
344         return WERR_OK;
345 }
346
347 static WERROR dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb(struct ldb_context *ldb, 
348                                                     const struct dsdb_schema *schema,
349                                                     const struct dsdb_attribute *attr,
350                                                     const struct drsuapi_DsReplicaAttribute *in,
351                                                     TALLOC_CTX *mem_ctx,
352                                                     struct ldb_message_element *out)
353 {
354         uint32_t i;
355
356         out->flags      = 0;
357         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
358         W_ERROR_HAVE_NO_MEMORY(out->name);
359
360         out->num_values = in->value_ctr.num_values;
361         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
362         W_ERROR_HAVE_NO_MEMORY(out->values);
363
364         for (i=0; i < out->num_values; i++) {
365                 NTTIME v;
366                 time_t t;
367                 char *str;
368
369                 if (in->value_ctr.values[i].blob == NULL) {
370                         return WERR_FOOBAR;
371                 }
372
373                 if (in->value_ctr.values[i].blob->length != 8) {
374                         return WERR_FOOBAR;
375                 }
376
377                 v = BVAL(in->value_ctr.values[i].blob->data, 0);
378                 v *= 10000000;
379                 t = nt_time_to_unix(v);
380
381                 /* 
382                  * NOTE: On a w2k3 server you can set a GeneralizedTime string
383                  *       via LDAP, but you get back an UTCTime string,
384                  *       but via DRSUAPI you get back the NTTIME_1sec value
385                  *       that represents the GeneralizedTime value!
386                  *
387                  *       So if we store the UTCTime string in our ldb
388                  *       we'll loose information!
389                  */
390                 str = ldb_timestring_utc(out->values, t); 
391                 W_ERROR_HAVE_NO_MEMORY(str);
392                 out->values[i] = data_blob_string_const(str);
393         }
394
395         return WERR_OK;
396 }
397
398 static WERROR dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi(struct ldb_context *ldb, 
399                                                     const struct dsdb_schema *schema,
400                                                     const struct dsdb_attribute *attr,
401                                                     const struct ldb_message_element *in,
402                                                     TALLOC_CTX *mem_ctx,
403                                                     struct drsuapi_DsReplicaAttribute *out)
404 {
405         uint32_t i;
406         DATA_BLOB *blobs;
407
408         if (attr->attributeID_id == 0xFFFFFFFF) {
409                 return WERR_FOOBAR;
410         }
411
412         out->attid                      = attr->attributeID_id;
413         out->value_ctr.num_values       = in->num_values;
414         out->value_ctr.values           = talloc_array(mem_ctx,
415                                                        struct drsuapi_DsAttributeValue,
416                                                        in->num_values);
417         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
418
419         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
420         W_ERROR_HAVE_NO_MEMORY(blobs);
421
422         for (i=0; i < in->num_values; i++) {
423                 NTTIME v;
424                 time_t t;
425
426                 out->value_ctr.values[i].blob   = &blobs[i];
427
428                 blobs[i] = data_blob_talloc(blobs, NULL, 8);
429                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
430
431                 t = ldb_string_utc_to_time((const char *)in->values[i].data);
432                 unix_to_nt_time(&v, t);
433                 v /= 10000000;
434
435                 SBVAL(blobs[i].data, 0, v);
436         }
437
438         return WERR_OK;
439 }
440
441 static WERROR dsdb_syntax_NTTIME_drsuapi_to_ldb(struct ldb_context *ldb, 
442                                                 const struct dsdb_schema *schema,
443                                                 const struct dsdb_attribute *attr,
444                                                 const struct drsuapi_DsReplicaAttribute *in,
445                                                 TALLOC_CTX *mem_ctx,
446                                                 struct ldb_message_element *out)
447 {
448         uint32_t i;
449
450         out->flags      = 0;
451         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
452         W_ERROR_HAVE_NO_MEMORY(out->name);
453
454         out->num_values = in->value_ctr.num_values;
455         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
456         W_ERROR_HAVE_NO_MEMORY(out->values);
457
458         for (i=0; i < out->num_values; i++) {
459                 NTTIME v;
460                 time_t t;
461                 char *str;
462
463                 if (in->value_ctr.values[i].blob == NULL) {
464                         return WERR_FOOBAR;
465                 }
466
467                 if (in->value_ctr.values[i].blob->length != 8) {
468                         return WERR_FOOBAR;
469                 }
470
471                 v = BVAL(in->value_ctr.values[i].blob->data, 0);
472                 v *= 10000000;
473                 t = nt_time_to_unix(v);
474
475                 str = ldb_timestring(out->values, t); 
476                 W_ERROR_HAVE_NO_MEMORY(str);
477
478                 out->values[i] = data_blob_string_const(str);
479         }
480
481         return WERR_OK;
482 }
483
484 static WERROR dsdb_syntax_NTTIME_ldb_to_drsuapi(struct ldb_context *ldb, 
485                                                 const struct dsdb_schema *schema,
486                                                 const struct dsdb_attribute *attr,
487                                                 const struct ldb_message_element *in,
488                                                 TALLOC_CTX *mem_ctx,
489                                                 struct drsuapi_DsReplicaAttribute *out)
490 {
491         uint32_t i;
492         DATA_BLOB *blobs;
493
494         if (attr->attributeID_id == 0xFFFFFFFF) {
495                 return WERR_FOOBAR;
496         }
497
498         out->attid                      = attr->attributeID_id;
499         out->value_ctr.num_values       = in->num_values;
500         out->value_ctr.values           = talloc_array(mem_ctx,
501                                                        struct drsuapi_DsAttributeValue,
502                                                        in->num_values);
503         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
504
505         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
506         W_ERROR_HAVE_NO_MEMORY(blobs);
507
508         for (i=0; i < in->num_values; i++) {
509                 NTTIME v;
510                 time_t t;
511                 int ret;
512
513                 out->value_ctr.values[i].blob   = &blobs[i];
514
515                 blobs[i] = data_blob_talloc(blobs, NULL, 8);
516                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
517
518                 ret = ldb_val_to_time(&in->values[i], &t);
519                 if (ret != LDB_SUCCESS) {
520                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
521                 }
522                 unix_to_nt_time(&v, t);
523                 v /= 10000000;
524
525                 SBVAL(blobs[i].data, 0, v);
526         }
527
528         return WERR_OK;
529 }
530
531 static WERROR dsdb_syntax_DATA_BLOB_drsuapi_to_ldb(struct ldb_context *ldb, 
532                                                    const struct dsdb_schema *schema,
533                                                    const struct dsdb_attribute *attr,
534                                                    const struct drsuapi_DsReplicaAttribute *in,
535                                                    TALLOC_CTX *mem_ctx,
536                                                    struct ldb_message_element *out)
537 {
538         uint32_t i;
539
540         out->flags      = 0;
541         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
542         W_ERROR_HAVE_NO_MEMORY(out->name);
543
544         out->num_values = in->value_ctr.num_values;
545         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
546         W_ERROR_HAVE_NO_MEMORY(out->values);
547
548         for (i=0; i < out->num_values; i++) {
549                 if (in->value_ctr.values[i].blob == NULL) {
550                         return WERR_FOOBAR;
551                 }
552
553                 if (in->value_ctr.values[i].blob->length == 0) {
554                         return WERR_FOOBAR;
555                 }
556
557                 out->values[i] = data_blob_dup_talloc(out->values,
558                                                       in->value_ctr.values[i].blob);
559                 W_ERROR_HAVE_NO_MEMORY(out->values[i].data);
560         }
561
562         return WERR_OK;
563 }
564
565 static WERROR dsdb_syntax_DATA_BLOB_ldb_to_drsuapi(struct ldb_context *ldb, 
566                                                    const struct dsdb_schema *schema,
567                                                    const struct dsdb_attribute *attr,
568                                                    const struct ldb_message_element *in,
569                                                    TALLOC_CTX *mem_ctx,
570                                                    struct drsuapi_DsReplicaAttribute *out)
571 {
572         uint32_t i;
573         DATA_BLOB *blobs;
574
575         if (attr->attributeID_id == 0xFFFFFFFF) {
576                 return WERR_FOOBAR;
577         }
578
579         out->attid                      = attr->attributeID_id;
580         out->value_ctr.num_values       = in->num_values;
581         out->value_ctr.values           = talloc_array(mem_ctx,
582                                                        struct drsuapi_DsAttributeValue,
583                                                        in->num_values);
584         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
585
586         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
587         W_ERROR_HAVE_NO_MEMORY(blobs);
588
589         for (i=0; i < in->num_values; i++) {
590                 out->value_ctr.values[i].blob   = &blobs[i];
591
592                 blobs[i] = data_blob_dup_talloc(blobs, &in->values[i]);
593                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
594         }
595
596         return WERR_OK;
597 }
598
599 static WERROR _dsdb_syntax_auto_OID_drsuapi_to_ldb(struct ldb_context *ldb,
600                                                    const struct dsdb_schema *schema,
601                                                    const struct dsdb_attribute *attr,
602                                                    const struct drsuapi_DsReplicaAttribute *in,
603                                                    TALLOC_CTX *mem_ctx,
604                                                    struct ldb_message_element *out)
605 {
606         uint32_t i;
607
608         out->flags      = 0;
609         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
610         W_ERROR_HAVE_NO_MEMORY(out->name);
611
612         out->num_values = in->value_ctr.num_values;
613         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
614         W_ERROR_HAVE_NO_MEMORY(out->values);
615
616         for (i=0; i < out->num_values; i++) {
617                 uint32_t v;
618                 const struct dsdb_class *c;
619                 const struct dsdb_attribute *a;
620                 const char *str = NULL;
621
622                 if (in->value_ctr.values[i].blob == NULL) {
623                         return WERR_FOOBAR;
624                 }
625
626                 if (in->value_ctr.values[i].blob->length != 4) {
627                         return WERR_FOOBAR;
628                 }
629
630                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
631
632                 if ((c = dsdb_class_by_governsID_id(schema, v))) {
633                         str = talloc_strdup(out->values, c->lDAPDisplayName);
634                 } else if ((a = dsdb_attribute_by_attributeID_id(schema, v))) {
635                         str = talloc_strdup(out->values, a->lDAPDisplayName);
636                 } else {
637                         WERROR werr;
638                         werr = dsdb_schema_pfm_oid_from_attid(schema->prefixmap, v, out->values, &str);
639                         W_ERROR_NOT_OK_RETURN(werr);
640                 }
641                 W_ERROR_HAVE_NO_MEMORY(str);
642
643                 /* the values need to be reversed */
644                 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
645         }
646
647         return WERR_OK;
648 }
649
650 static WERROR _dsdb_syntax_OID_obj_drsuapi_to_ldb(struct ldb_context *ldb, 
651                                                   const struct dsdb_schema *schema,
652                                                   const struct dsdb_attribute *attr,
653                                                   const struct drsuapi_DsReplicaAttribute *in,
654                                                   TALLOC_CTX *mem_ctx,
655                                                   struct ldb_message_element *out)
656 {
657         uint32_t i;
658
659         out->flags      = 0;
660         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
661         W_ERROR_HAVE_NO_MEMORY(out->name);
662
663         out->num_values = in->value_ctr.num_values;
664         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
665         W_ERROR_HAVE_NO_MEMORY(out->values);
666
667         for (i=0; i < out->num_values; i++) {
668                 uint32_t v;
669                 const struct dsdb_class *c;
670                 const char *str;
671
672                 if (in->value_ctr.values[i].blob == NULL) {
673                         return WERR_FOOBAR;
674                 }
675
676                 if (in->value_ctr.values[i].blob->length != 4) {
677                         return WERR_FOOBAR;
678                 }
679
680                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
681
682                 c = dsdb_class_by_governsID_id(schema, v);
683                 if (!c) {
684                         return WERR_FOOBAR;
685                 }
686
687                 str = talloc_strdup(out->values, c->lDAPDisplayName);
688                 W_ERROR_HAVE_NO_MEMORY(str);
689
690                 /* the values need to be reversed */
691                 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
692         }
693
694         return WERR_OK;
695 }
696
697 static WERROR _dsdb_syntax_OID_attr_drsuapi_to_ldb(struct ldb_context *ldb, 
698                                                    const struct dsdb_schema *schema,
699                                                    const struct dsdb_attribute *attr,
700                                                    const struct drsuapi_DsReplicaAttribute *in,
701                                                    TALLOC_CTX *mem_ctx,
702                                                    struct ldb_message_element *out)
703 {
704         uint32_t i;
705
706         out->flags      = 0;
707         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
708         W_ERROR_HAVE_NO_MEMORY(out->name);
709
710         out->num_values = in->value_ctr.num_values;
711         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
712         W_ERROR_HAVE_NO_MEMORY(out->values);
713
714         for (i=0; i < out->num_values; i++) {
715                 uint32_t v;
716                 const struct dsdb_attribute *a;
717                 const char *str;
718
719                 if (in->value_ctr.values[i].blob == NULL) {
720                         return WERR_FOOBAR;
721                 }
722
723                 if (in->value_ctr.values[i].blob->length != 4) {
724                         return WERR_FOOBAR;
725                 }
726
727                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
728
729                 a = dsdb_attribute_by_attributeID_id(schema, v);
730                 if (!a) {
731                         return WERR_FOOBAR;
732                 }
733
734                 str = talloc_strdup(out->values, a->lDAPDisplayName);
735                 W_ERROR_HAVE_NO_MEMORY(str);
736
737                 /* the values need to be reversed */
738                 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
739         }
740
741         return WERR_OK;
742 }
743
744 static WERROR _dsdb_syntax_OID_oid_drsuapi_to_ldb(struct ldb_context *ldb, 
745                                                   const struct dsdb_schema *schema,
746                                                   const struct dsdb_attribute *attr,
747                                                   const struct drsuapi_DsReplicaAttribute *in,
748                                                   TALLOC_CTX *mem_ctx,
749                                                   struct ldb_message_element *out)
750 {
751         uint32_t i;
752
753         out->flags      = 0;
754         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
755         W_ERROR_HAVE_NO_MEMORY(out->name);
756
757         out->num_values = in->value_ctr.num_values;
758         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
759         W_ERROR_HAVE_NO_MEMORY(out->values);
760
761         for (i=0; i < out->num_values; i++) {
762                 uint32_t attid;
763                 WERROR status;
764                 const char *oid;
765
766                 if (in->value_ctr.values[i].blob == NULL) {
767                         return WERR_FOOBAR;
768                 }
769
770                 if (in->value_ctr.values[i].blob->length != 4) {
771                         return WERR_FOOBAR;
772                 }
773
774                 attid = IVAL(in->value_ctr.values[i].blob->data, 0);
775
776                 status = dsdb_schema_pfm_oid_from_attid(schema->prefixmap, attid, out->values, &oid);
777                 W_ERROR_NOT_OK_RETURN(status);
778
779                 out->values[i] = data_blob_string_const(oid);
780         }
781
782         return WERR_OK;
783 }
784
785 static WERROR _dsdb_syntax_auto_OID_ldb_to_drsuapi(struct ldb_context *ldb,
786                                                    const struct dsdb_schema *schema,
787                                                    const struct dsdb_attribute *attr,
788                                                    const struct ldb_message_element *in,
789                                                    TALLOC_CTX *mem_ctx,
790                                                   struct drsuapi_DsReplicaAttribute *out)
791 {
792         uint32_t i;
793         DATA_BLOB *blobs;
794
795         out->attid= attr->attributeID_id;
796         out->value_ctr.num_values= in->num_values;
797         out->value_ctr.values= talloc_array(mem_ctx,
798                                             struct drsuapi_DsAttributeValue,
799                                             in->num_values);
800         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
801
802         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
803         W_ERROR_HAVE_NO_MEMORY(blobs);
804
805         for (i=0; i < in->num_values; i++) {
806                 const struct dsdb_class *obj_class;
807                 const struct dsdb_attribute *obj_attr;
808                 struct ldb_val *v;
809
810                 out->value_ctr.values[i].blob= &blobs[i];
811
812                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
813                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
814
815                 /* in DRS windows puts the classes in the opposite
816                    order to the order used in ldap */
817                 v = &in->values[(in->num_values-1)-i];
818
819                 if ((obj_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema, v))) {
820                         SIVAL(blobs[i].data, 0, obj_class->governsID_id);
821                 } else if ((obj_attr = dsdb_attribute_by_lDAPDisplayName_ldb_val(schema, v))) {
822                         SIVAL(blobs[i].data, 0, obj_attr->attributeID_id);
823                 } else {
824                         uint32_t attid;
825                         WERROR werr;
826                         werr = dsdb_schema_pfm_make_attid(schema->prefixmap,
827                                                           (const char *)v->data,
828                                                           &attid);
829                         W_ERROR_NOT_OK_RETURN(werr);
830                         SIVAL(blobs[i].data, 0, attid);
831                 }
832
833         }
834
835
836         return WERR_OK;
837 }
838
839 static WERROR _dsdb_syntax_OID_obj_ldb_to_drsuapi(struct ldb_context *ldb,
840                                                   const struct dsdb_schema *schema,
841                                                   const struct dsdb_attribute *attr,
842                                                   const struct ldb_message_element *in,
843                                                   TALLOC_CTX *mem_ctx,
844                                                   struct drsuapi_DsReplicaAttribute *out)
845 {
846         uint32_t i;
847         DATA_BLOB *blobs;
848
849         out->attid= attr->attributeID_id;
850         out->value_ctr.num_values= in->num_values;
851         out->value_ctr.values= talloc_array(mem_ctx,
852                                             struct drsuapi_DsAttributeValue,
853                                             in->num_values);
854         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
855
856         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
857         W_ERROR_HAVE_NO_MEMORY(blobs);
858
859         for (i=0; i < in->num_values; i++) {
860                 const struct dsdb_class *obj_class;
861
862                 out->value_ctr.values[i].blob= &blobs[i];
863
864                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
865                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
866
867                 /* in DRS windows puts the classes in the opposite
868                    order to the order used in ldap */
869                 obj_class = dsdb_class_by_lDAPDisplayName(schema,
870                                                           (const char *)in->values[(in->num_values-1)-i].data);
871                 if (!obj_class) {
872                         return WERR_FOOBAR;
873                 }
874                 SIVAL(blobs[i].data, 0, obj_class->governsID_id);
875         }
876
877
878         return WERR_OK;
879 }
880
881 static WERROR _dsdb_syntax_OID_attr_ldb_to_drsuapi(struct ldb_context *ldb,
882                                                    const struct dsdb_schema *schema,
883                                                    const struct dsdb_attribute *attr,
884                                                    const struct ldb_message_element *in,
885                                                    TALLOC_CTX *mem_ctx,
886                                                    struct drsuapi_DsReplicaAttribute *out)
887 {
888         uint32_t i;
889         DATA_BLOB *blobs;
890
891         out->attid= attr->attributeID_id;
892         out->value_ctr.num_values= in->num_values;
893         out->value_ctr.values= talloc_array(mem_ctx,
894                                             struct drsuapi_DsAttributeValue,
895                                             in->num_values);
896         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
897
898         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
899         W_ERROR_HAVE_NO_MEMORY(blobs);
900
901         for (i=0; i < in->num_values; i++) {
902                 const struct dsdb_attribute *obj_attr;
903
904                 out->value_ctr.values[i].blob= &blobs[i];
905
906                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
907                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
908
909                 obj_attr = dsdb_attribute_by_lDAPDisplayName(schema, (const char *)in->values[i].data);
910                 if (!obj_attr) {
911                         return WERR_FOOBAR;
912                 }
913                 SIVAL(blobs[i].data, 0, obj_attr->attributeID_id);
914         }
915
916
917         return WERR_OK;
918 }
919
920 static WERROR _dsdb_syntax_OID_oid_ldb_to_drsuapi(struct ldb_context *ldb,
921                                                   const struct dsdb_schema *schema,
922                                                   const struct dsdb_attribute *attr,
923                                                   const struct ldb_message_element *in,
924                                                   TALLOC_CTX *mem_ctx,
925                                                   struct drsuapi_DsReplicaAttribute *out)
926 {
927         uint32_t i;
928         DATA_BLOB *blobs;
929
930         out->attid= attr->attributeID_id;
931         out->value_ctr.num_values= in->num_values;
932         out->value_ctr.values= talloc_array(mem_ctx,
933                                             struct drsuapi_DsAttributeValue,
934                                             in->num_values);
935         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
936
937         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
938         W_ERROR_HAVE_NO_MEMORY(blobs);
939
940         for (i=0; i < in->num_values; i++) {
941                 uint32_t attid;
942                 WERROR status;
943
944                 out->value_ctr.values[i].blob= &blobs[i];
945
946                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
947                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
948
949                 status = dsdb_schema_pfm_make_attid(schema->prefixmap,
950                                                     (const char *)in->values[i].data,
951                                                     &attid);
952                 W_ERROR_NOT_OK_RETURN(status);
953
954                 SIVAL(blobs[i].data, 0, attid);
955         }
956
957         return WERR_OK;
958 }
959
960 static WERROR dsdb_syntax_OID_drsuapi_to_ldb(struct ldb_context *ldb, 
961                                              const struct dsdb_schema *schema,
962                                              const struct dsdb_attribute *attr,
963                                              const struct drsuapi_DsReplicaAttribute *in,
964                                              TALLOC_CTX *mem_ctx,
965                                              struct ldb_message_element *out)
966 {
967         switch (attr->attributeID_id) {
968         case DRSUAPI_ATTRIBUTE_objectClass:
969         case DRSUAPI_ATTRIBUTE_subClassOf:
970         case DRSUAPI_ATTRIBUTE_auxiliaryClass:
971         case DRSUAPI_ATTRIBUTE_systemAuxiliaryClass:
972         case DRSUAPI_ATTRIBUTE_systemPossSuperiors:
973         case DRSUAPI_ATTRIBUTE_possSuperiors:
974                 return _dsdb_syntax_OID_obj_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
975         case DRSUAPI_ATTRIBUTE_systemMustContain:
976         case DRSUAPI_ATTRIBUTE_systemMayContain:        
977         case DRSUAPI_ATTRIBUTE_mustContain:
978         case DRSUAPI_ATTRIBUTE_rDNAttId:
979         case DRSUAPI_ATTRIBUTE_transportAddressAttribute:
980         case DRSUAPI_ATTRIBUTE_mayContain:
981                 return _dsdb_syntax_OID_attr_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
982         case DRSUAPI_ATTRIBUTE_governsID:
983         case DRSUAPI_ATTRIBUTE_attributeID:
984         case DRSUAPI_ATTRIBUTE_attributeSyntax:
985                 return _dsdb_syntax_OID_oid_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
986         }
987
988         DEBUG(0,(__location__ ": Unknown handling for attributeID_id for %s\n",
989                  attr->lDAPDisplayName));
990         return _dsdb_syntax_auto_OID_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
991 }
992
993 static WERROR dsdb_syntax_OID_ldb_to_drsuapi(struct ldb_context *ldb, 
994                                              const struct dsdb_schema *schema,
995                                              const struct dsdb_attribute *attr,
996                                              const struct ldb_message_element *in,
997                                              TALLOC_CTX *mem_ctx,
998                                              struct drsuapi_DsReplicaAttribute *out)
999 {
1000         if (attr->attributeID_id == 0xFFFFFFFF) {
1001                 return WERR_FOOBAR;
1002         }
1003
1004         switch (attr->attributeID_id) {
1005         case DRSUAPI_ATTRIBUTE_objectClass:
1006         case DRSUAPI_ATTRIBUTE_subClassOf:
1007         case DRSUAPI_ATTRIBUTE_auxiliaryClass:
1008         case DRSUAPI_ATTRIBUTE_systemAuxiliaryClass:
1009         case DRSUAPI_ATTRIBUTE_systemPossSuperiors:
1010         case DRSUAPI_ATTRIBUTE_possSuperiors:
1011                 return _dsdb_syntax_OID_obj_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
1012         case DRSUAPI_ATTRIBUTE_systemMustContain:
1013         case DRSUAPI_ATTRIBUTE_systemMayContain:        
1014         case DRSUAPI_ATTRIBUTE_mustContain:
1015         case DRSUAPI_ATTRIBUTE_rDNAttId:
1016         case DRSUAPI_ATTRIBUTE_transportAddressAttribute:
1017         case DRSUAPI_ATTRIBUTE_mayContain:
1018                 return _dsdb_syntax_OID_attr_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
1019         case DRSUAPI_ATTRIBUTE_governsID:
1020         case DRSUAPI_ATTRIBUTE_attributeID:
1021         case DRSUAPI_ATTRIBUTE_attributeSyntax:
1022                 return _dsdb_syntax_OID_oid_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
1023         }
1024
1025         DEBUG(0,(__location__ ": Unknown handling for attributeID_id for %s\n",
1026                  attr->lDAPDisplayName));
1027
1028         return _dsdb_syntax_auto_OID_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
1029 }
1030
1031 static WERROR dsdb_syntax_UNICODE_drsuapi_to_ldb(struct ldb_context *ldb, 
1032                                                  const struct dsdb_schema *schema,
1033                                                  const struct dsdb_attribute *attr,
1034                                                  const struct drsuapi_DsReplicaAttribute *in,
1035                                                  TALLOC_CTX *mem_ctx,
1036                                                  struct ldb_message_element *out)
1037 {
1038         uint32_t i;
1039
1040         out->flags      = 0;
1041         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1042         W_ERROR_HAVE_NO_MEMORY(out->name);
1043
1044         out->num_values = in->value_ctr.num_values;
1045         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1046         W_ERROR_HAVE_NO_MEMORY(out->values);
1047
1048         for (i=0; i < out->num_values; i++) {
1049                 char *str;
1050
1051                 if (in->value_ctr.values[i].blob == NULL) {
1052                         return WERR_FOOBAR;
1053                 }
1054
1055                 if (in->value_ctr.values[i].blob->length == 0) {
1056                         return WERR_FOOBAR;
1057                 }
1058
1059                 if (!convert_string_talloc_convenience(out->values, 
1060                                                 schema->iconv_convenience, 
1061                                                                         CH_UTF16, CH_UNIX,
1062                                             in->value_ctr.values[i].blob->data,
1063                                             in->value_ctr.values[i].blob->length,
1064                                             (void **)&str, NULL, false)) {
1065                         return WERR_FOOBAR;
1066                 }
1067
1068                 out->values[i] = data_blob_string_const(str);
1069         }
1070
1071         return WERR_OK;
1072 }
1073
1074 static WERROR dsdb_syntax_UNICODE_ldb_to_drsuapi(struct ldb_context *ldb, 
1075                                                  const struct dsdb_schema *schema,
1076                                                  const struct dsdb_attribute *attr,
1077                                                  const struct ldb_message_element *in,
1078                                                  TALLOC_CTX *mem_ctx,
1079                                                  struct drsuapi_DsReplicaAttribute *out)
1080 {
1081         uint32_t i;
1082         DATA_BLOB *blobs;
1083
1084         if (attr->attributeID_id == 0xFFFFFFFF) {
1085                 return WERR_FOOBAR;
1086         }
1087
1088         out->attid                      = attr->attributeID_id;
1089         out->value_ctr.num_values       = in->num_values;
1090         out->value_ctr.values           = talloc_array(mem_ctx,
1091                                                        struct drsuapi_DsAttributeValue,
1092                                                        in->num_values);
1093         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1094
1095         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1096         W_ERROR_HAVE_NO_MEMORY(blobs);
1097
1098         for (i=0; i < in->num_values; i++) {
1099                 out->value_ctr.values[i].blob   = &blobs[i];
1100
1101                 if (!convert_string_talloc_convenience(blobs,
1102                         schema->iconv_convenience, CH_UNIX, CH_UTF16,
1103                         in->values[i].data, in->values[i].length,
1104                         (void **)&blobs[i].data, &blobs[i].length, false)) {
1105                                 return WERR_FOOBAR;
1106                 }
1107         }
1108
1109         return WERR_OK;
1110 }
1111
1112
1113 WERROR dsdb_syntax_one_DN_drsuapi_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, 
1114                                          const struct dsdb_syntax *syntax, 
1115                                          struct smb_iconv_convenience *iconv_convenience,
1116                                          const DATA_BLOB *in, DATA_BLOB *out)
1117 {
1118         struct drsuapi_DsReplicaObjectIdentifier3 id3;
1119         enum ndr_err_code ndr_err;
1120         DATA_BLOB guid_blob;
1121         struct ldb_dn *dn;
1122         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1123         int ret;
1124         NTSTATUS status;
1125
1126         if (!tmp_ctx) {
1127                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1128         }
1129         
1130         if (in == NULL) {
1131                 talloc_free(tmp_ctx);
1132                 return WERR_FOOBAR;
1133         }
1134         
1135         if (in->length == 0) {
1136                 talloc_free(tmp_ctx);
1137                 return WERR_FOOBAR;
1138         }
1139         
1140         
1141         /* windows sometimes sends an extra two pad bytes here */
1142         ndr_err = ndr_pull_struct_blob(in,
1143                                        tmp_ctx, iconv_convenience, &id3,
1144                                        (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3);
1145         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1146                 status = ndr_map_error2ntstatus(ndr_err);
1147                 talloc_free(tmp_ctx);
1148                 return ntstatus_to_werror(status);
1149         }
1150         
1151         dn = ldb_dn_new(tmp_ctx, ldb, id3.dn);
1152         if (!dn) {
1153                 talloc_free(tmp_ctx);
1154                 /* If this fails, it must be out of memory, as it does not do much parsing */
1155                 W_ERROR_HAVE_NO_MEMORY(dn);
1156         }
1157
1158         if (!GUID_all_zero(&id3.guid)) {
1159                 status = GUID_to_ndr_blob(&id3.guid, tmp_ctx, &guid_blob);
1160                 if (!NT_STATUS_IS_OK(status)) {
1161                         talloc_free(tmp_ctx);
1162                         return ntstatus_to_werror(status);
1163                 }
1164         
1165                 ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
1166                 if (ret != LDB_SUCCESS) {
1167                         talloc_free(tmp_ctx);
1168                         return WERR_FOOBAR;
1169                 }
1170                 talloc_free(guid_blob.data);
1171         }
1172         
1173         if (id3.__ndr_size_sid) {
1174                 DATA_BLOB sid_blob;
1175                 ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, iconv_convenience, &id3.sid,
1176                                                (ndr_push_flags_fn_t)ndr_push_dom_sid);
1177                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1178                         status = ndr_map_error2ntstatus(ndr_err);
1179                         talloc_free(tmp_ctx);
1180                         return ntstatus_to_werror(status);
1181                 }
1182                 
1183                 ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
1184                 if (ret != LDB_SUCCESS) {
1185                         talloc_free(tmp_ctx);
1186                         return WERR_FOOBAR;
1187                 }
1188         }
1189         
1190         *out = data_blob_string_const(ldb_dn_get_extended_linearized(mem_ctx, dn, 1));
1191         talloc_free(tmp_ctx);
1192         return WERR_OK;
1193 }
1194
1195 static WERROR dsdb_syntax_DN_drsuapi_to_ldb(struct ldb_context *ldb, 
1196                                             const struct dsdb_schema *schema,
1197                                             const struct dsdb_attribute *attr,
1198                                             const struct drsuapi_DsReplicaAttribute *in,
1199                                             TALLOC_CTX *mem_ctx,
1200                                             struct ldb_message_element *out)
1201 {
1202         uint32_t i;
1203
1204         out->flags      = 0;
1205         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1206         W_ERROR_HAVE_NO_MEMORY(out->name);
1207
1208         out->num_values = in->value_ctr.num_values;
1209         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1210         W_ERROR_HAVE_NO_MEMORY(out->values);
1211
1212         for (i=0; i < out->num_values; i++) {
1213                 WERROR status = dsdb_syntax_one_DN_drsuapi_to_ldb(out->values, ldb, attr->syntax, 
1214                                                                   schema->iconv_convenience, 
1215                                                                   in->value_ctr.values[i].blob, 
1216                                                                   &out->values[i]);
1217                 if (!W_ERROR_IS_OK(status)) {
1218                         return status;
1219                 }
1220                                                   
1221         }
1222
1223         return WERR_OK;
1224 }
1225
1226 static WERROR dsdb_syntax_DN_ldb_to_drsuapi(struct ldb_context *ldb, 
1227                                             const struct dsdb_schema *schema,
1228                                             const struct dsdb_attribute *attr,
1229                                             const struct ldb_message_element *in,
1230                                             TALLOC_CTX *mem_ctx,
1231                                             struct drsuapi_DsReplicaAttribute *out)
1232 {
1233         uint32_t i;
1234         DATA_BLOB *blobs;
1235
1236         if (attr->attributeID_id == 0xFFFFFFFF) {
1237                 return WERR_FOOBAR;
1238         }
1239
1240         out->attid                      = attr->attributeID_id;
1241         out->value_ctr.num_values       = in->num_values;
1242         out->value_ctr.values           = talloc_array(mem_ctx,
1243                                                        struct drsuapi_DsAttributeValue,
1244                                                        in->num_values);
1245         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1246
1247         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1248         W_ERROR_HAVE_NO_MEMORY(blobs);
1249
1250         for (i=0; i < in->num_values; i++) {
1251                 struct drsuapi_DsReplicaObjectIdentifier3 id3;
1252                 enum ndr_err_code ndr_err;
1253                 const DATA_BLOB *sid_blob;
1254                 struct ldb_dn *dn;
1255                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1256                 NTSTATUS status;
1257
1258                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1259
1260                 out->value_ctr.values[i].blob   = &blobs[i];
1261
1262                 dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &in->values[i]);
1263
1264                 W_ERROR_HAVE_NO_MEMORY(dn);
1265
1266                 ZERO_STRUCT(id3);
1267
1268                 status = dsdb_get_extended_dn_guid(dn, &id3.guid, "GUID");
1269                 if (!NT_STATUS_IS_OK(status) &&
1270                     !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1271                         talloc_free(tmp_ctx);
1272                         return ntstatus_to_werror(status);
1273                 }
1274
1275                 sid_blob = ldb_dn_get_extended_component(dn, "SID");
1276                 if (sid_blob) {
1277                         
1278                         ndr_err = ndr_pull_struct_blob_all(sid_blob, 
1279                                                            tmp_ctx, schema->iconv_convenience, &id3.sid,
1280                                                            (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1281                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1282                                 status = ndr_map_error2ntstatus(ndr_err);
1283                                 talloc_free(tmp_ctx);
1284                                 return ntstatus_to_werror(status);
1285                         }
1286                 }
1287
1288                 id3.dn = ldb_dn_get_linearized(dn);
1289
1290                 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
1291                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1292                         status = ndr_map_error2ntstatus(ndr_err);
1293                         talloc_free(tmp_ctx);
1294                         return ntstatus_to_werror(status);
1295                 }
1296                 talloc_free(tmp_ctx);
1297         }
1298
1299         return WERR_OK;
1300 }
1301
1302
1303
1304 static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(struct ldb_context *ldb, 
1305                                                    const struct dsdb_schema *schema,
1306                                                    const struct dsdb_attribute *attr,
1307                                                    const struct drsuapi_DsReplicaAttribute *in,
1308                                                    TALLOC_CTX *mem_ctx,
1309                                                    struct ldb_message_element *out)
1310 {
1311         uint32_t i;
1312         int ret;
1313
1314         out->flags      = 0;
1315         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1316         W_ERROR_HAVE_NO_MEMORY(out->name);
1317
1318         out->num_values = in->value_ctr.num_values;
1319         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1320         W_ERROR_HAVE_NO_MEMORY(out->values);
1321
1322         for (i=0; i < out->num_values; i++) {
1323                 struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
1324                 enum ndr_err_code ndr_err;
1325                 DATA_BLOB guid_blob;
1326                 struct ldb_dn *dn;
1327                 struct dsdb_dn *dsdb_dn;
1328                 NTSTATUS status;
1329                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1330                 if (!tmp_ctx) {
1331                         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1332                 }
1333
1334                 if (in->value_ctr.values[i].blob == NULL) {
1335                         talloc_free(tmp_ctx);
1336                         return WERR_FOOBAR;
1337                 }
1338
1339                 if (in->value_ctr.values[i].blob->length == 0) {
1340                         talloc_free(tmp_ctx);
1341                         return WERR_FOOBAR;
1342                 }
1343
1344                 
1345                 /* windows sometimes sends an extra two pad bytes here */
1346                 ndr_err = ndr_pull_struct_blob(in->value_ctr.values[i].blob,
1347                                                tmp_ctx, schema->iconv_convenience, &id3,
1348                                                (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3Binary);
1349                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1350                         status = ndr_map_error2ntstatus(ndr_err);
1351                         talloc_free(tmp_ctx);
1352                         return ntstatus_to_werror(status);
1353                 }
1354
1355                 dn = ldb_dn_new(tmp_ctx, ldb, id3.dn);
1356                 if (!dn) {
1357                         talloc_free(tmp_ctx);
1358                         /* If this fails, it must be out of memory, as it does not do much parsing */
1359                         W_ERROR_HAVE_NO_MEMORY(dn);
1360                 }
1361
1362                 status = GUID_to_ndr_blob(&id3.guid, tmp_ctx, &guid_blob);
1363                 if (!NT_STATUS_IS_OK(status)) {
1364                         talloc_free(tmp_ctx);
1365                         return ntstatus_to_werror(status);
1366                 }
1367
1368                 ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
1369                 if (ret != LDB_SUCCESS) {
1370                         talloc_free(tmp_ctx);
1371                         return WERR_FOOBAR;
1372                 }
1373
1374                 talloc_free(guid_blob.data);
1375
1376                 if (id3.__ndr_size_sid) {
1377                         DATA_BLOB sid_blob;
1378                         ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, schema->iconv_convenience, &id3.sid,
1379                                                        (ndr_push_flags_fn_t)ndr_push_dom_sid);
1380                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1381                                 status = ndr_map_error2ntstatus(ndr_err);
1382                                 talloc_free(tmp_ctx);
1383                                 return ntstatus_to_werror(status);
1384                         }
1385
1386                         ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
1387                         if (ret != LDB_SUCCESS) {
1388                                 talloc_free(tmp_ctx);
1389                                 return WERR_FOOBAR;
1390                         }
1391                 }
1392
1393                 /* set binary stuff */
1394                 dsdb_dn = dsdb_dn_construct(tmp_ctx, dn, id3.binary, attr->syntax->ldap_oid);
1395                 if (!dsdb_dn) {
1396                         /* If this fails, it must be out of memory, we know the ldap_oid is valid */
1397                         talloc_free(tmp_ctx);
1398                         W_ERROR_HAVE_NO_MEMORY(dsdb_dn);
1399                 }
1400                 out->values[i] = data_blob_string_const(dsdb_dn_get_extended_linearized(out->values, dsdb_dn, 1));
1401                 talloc_free(tmp_ctx);
1402         }
1403
1404         return WERR_OK;
1405 }
1406
1407 static WERROR dsdb_syntax_DN_BINARY_ldb_to_drsuapi(struct ldb_context *ldb, 
1408                                                    const struct dsdb_schema *schema,
1409                                                    const struct dsdb_attribute *attr,
1410                                                    const struct ldb_message_element *in,
1411                                                    TALLOC_CTX *mem_ctx,
1412                                                    struct drsuapi_DsReplicaAttribute *out)
1413 {
1414         uint32_t i;
1415         DATA_BLOB *blobs;
1416
1417         if (attr->attributeID_id == 0xFFFFFFFF) {
1418                 return WERR_FOOBAR;
1419         }
1420
1421         out->attid                      = attr->attributeID_id;
1422         out->value_ctr.num_values       = in->num_values;
1423         out->value_ctr.values           = talloc_array(mem_ctx,
1424                                                        struct drsuapi_DsAttributeValue,
1425                                                        in->num_values);
1426         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1427
1428         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1429         W_ERROR_HAVE_NO_MEMORY(blobs);
1430
1431         for (i=0; i < in->num_values; i++) {
1432                 struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
1433                 enum ndr_err_code ndr_err;
1434                 const DATA_BLOB *sid_blob;
1435                 struct dsdb_dn *dsdb_dn;
1436                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1437                 NTSTATUS status;
1438
1439                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1440
1441                 out->value_ctr.values[i].blob   = &blobs[i];
1442
1443                 dsdb_dn = dsdb_dn_parse(tmp_ctx, ldb, &in->values[i], attr->syntax->ldap_oid);
1444
1445                 if (!dsdb_dn) {
1446                         talloc_free(tmp_ctx);
1447                         return ntstatus_to_werror(NT_STATUS_INVALID_PARAMETER);
1448                 }
1449
1450                 ZERO_STRUCT(id3);
1451
1452                 status = dsdb_get_extended_dn_guid(dsdb_dn->dn, &id3.guid, "GUID");
1453                 if (!NT_STATUS_IS_OK(status) &&
1454                     !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1455                         talloc_free(tmp_ctx);
1456                         return ntstatus_to_werror(status);
1457                 }
1458
1459                 sid_blob = ldb_dn_get_extended_component(dsdb_dn->dn, "SID");
1460                 if (sid_blob) {
1461                         
1462                         ndr_err = ndr_pull_struct_blob_all(sid_blob, 
1463                                                            tmp_ctx, schema->iconv_convenience, &id3.sid,
1464                                                            (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1465                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1466                                 status = ndr_map_error2ntstatus(ndr_err);
1467                                 talloc_free(tmp_ctx);
1468                                 return ntstatus_to_werror(status);
1469                         }
1470                 }
1471
1472                 id3.dn = ldb_dn_get_linearized(dsdb_dn->dn);
1473
1474                 /* get binary stuff */
1475                 id3.binary = dsdb_dn->extra_part;
1476
1477                 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3Binary);
1478                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1479                         status = ndr_map_error2ntstatus(ndr_err);
1480                         talloc_free(tmp_ctx);
1481                         return ntstatus_to_werror(status);
1482                 }
1483                 talloc_free(tmp_ctx);
1484         }
1485
1486         return WERR_OK;
1487 }
1488
1489 static WERROR dsdb_syntax_DN_STRING_drsuapi_to_ldb(struct ldb_context *ldb,
1490                                                    const struct dsdb_schema *schema,
1491                                                    const struct dsdb_attribute *attr,
1492                                                    const struct drsuapi_DsReplicaAttribute *in,
1493                                                    TALLOC_CTX *mem_ctx,
1494                                                    struct ldb_message_element *out)
1495 {
1496         return dsdb_syntax_DN_BINARY_drsuapi_to_ldb(ldb,
1497                                                     schema,
1498                                                     attr,
1499                                                     in,
1500                                                     mem_ctx,
1501                                                     out);
1502 }
1503
1504 static WERROR dsdb_syntax_DN_STRING_ldb_to_drsuapi(struct ldb_context *ldb,
1505                                                    const struct dsdb_schema *schema,
1506                                                    const struct dsdb_attribute *attr,
1507                                                    const struct ldb_message_element *in,
1508                                                    TALLOC_CTX *mem_ctx,
1509                                                    struct drsuapi_DsReplicaAttribute *out)
1510 {
1511         return dsdb_syntax_DN_BINARY_ldb_to_drsuapi(ldb,
1512                                                     schema,
1513                                                     attr,
1514                                                     in,
1515                                                     mem_ctx,
1516                                                     out);
1517 }
1518
1519 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb(struct ldb_context *ldb, 
1520                                                               const struct dsdb_schema *schema,
1521                                                               const struct dsdb_attribute *attr,
1522                                                               const struct drsuapi_DsReplicaAttribute *in,
1523                                                               TALLOC_CTX *mem_ctx,
1524                                                               struct ldb_message_element *out)
1525 {
1526         uint32_t i;
1527
1528         out->flags      = 0;
1529         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1530         W_ERROR_HAVE_NO_MEMORY(out->name);
1531
1532         out->num_values = in->value_ctr.num_values;
1533         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1534         W_ERROR_HAVE_NO_MEMORY(out->values);
1535
1536         for (i=0; i < out->num_values; i++) {
1537                 uint32_t len;
1538                 char *str;
1539
1540                 if (in->value_ctr.values[i].blob == NULL) {
1541                         return WERR_FOOBAR;
1542                 }
1543
1544                 if (in->value_ctr.values[i].blob->length < 4) {
1545                         return WERR_FOOBAR;
1546                 }
1547
1548                 len = IVAL(in->value_ctr.values[i].blob->data, 0);
1549
1550                 if (len != in->value_ctr.values[i].blob->length) {
1551                         return WERR_FOOBAR;
1552                 }
1553
1554                 if (!convert_string_talloc_convenience(out->values, schema->iconv_convenience, CH_UTF16, CH_UNIX,
1555                                             in->value_ctr.values[i].blob->data+4,
1556                                             in->value_ctr.values[i].blob->length-4,
1557                                             (void **)&str, NULL, false)) {
1558                         return WERR_FOOBAR;
1559                 }
1560
1561                 out->values[i] = data_blob_string_const(str);
1562         }
1563
1564         return WERR_OK;
1565 }
1566
1567 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi(struct ldb_context *ldb, 
1568                                                               const struct dsdb_schema *schema,
1569                                                               const struct dsdb_attribute *attr,
1570                                                               const struct ldb_message_element *in,
1571                                                               TALLOC_CTX *mem_ctx,
1572                                                               struct drsuapi_DsReplicaAttribute *out)
1573 {
1574         uint32_t i;
1575         DATA_BLOB *blobs;
1576
1577         if (attr->attributeID_id == 0xFFFFFFFF) {
1578                 return WERR_FOOBAR;
1579         }
1580
1581         out->attid                      = attr->attributeID_id;
1582         out->value_ctr.num_values       = in->num_values;
1583         out->value_ctr.values           = talloc_array(mem_ctx,
1584                                                        struct drsuapi_DsAttributeValue,
1585                                                        in->num_values);
1586         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1587
1588         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1589         W_ERROR_HAVE_NO_MEMORY(blobs);
1590
1591         for (i=0; i < in->num_values; i++) {
1592                 uint8_t *data;
1593                 size_t ret;
1594
1595                 out->value_ctr.values[i].blob   = &blobs[i];
1596
1597                 if (!convert_string_talloc_convenience(blobs, schema->iconv_convenience, CH_UNIX, CH_UTF16,
1598                                             in->values[i].data,
1599                                             in->values[i].length,
1600                                             (void **)&data, &ret, false)) {
1601                         return WERR_FOOBAR;
1602                 }
1603
1604                 blobs[i] = data_blob_talloc(blobs, NULL, 4 + ret);
1605                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1606
1607                 SIVAL(blobs[i].data, 0, 4 + ret);
1608
1609                 if (ret > 0) {
1610                         memcpy(blobs[i].data + 4, data, ret);
1611                         talloc_free(data);
1612                 }
1613         }
1614
1615         return WERR_OK;
1616 }
1617
1618 #define OMOBJECTCLASS(val) { .length = sizeof(val) - 1, .data = discard_const_p(uint8_t, val) }
1619
1620 static const struct dsdb_syntax dsdb_syntaxes[] = {
1621         {
1622                 .name                   = "Boolean",
1623                 .ldap_oid               = LDB_SYNTAX_BOOLEAN,
1624                 .oMSyntax               = 1,
1625                 .attributeSyntax_oid    = "2.5.5.8",
1626                 .drsuapi_to_ldb         = dsdb_syntax_BOOL_drsuapi_to_ldb,
1627                 .ldb_to_drsuapi         = dsdb_syntax_BOOL_ldb_to_drsuapi,
1628                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1629                 .equality               = "booleanMatch",
1630                 .comment                = "Boolean" 
1631         },{
1632                 .name                   = "Integer",
1633                 .ldap_oid               = LDB_SYNTAX_INTEGER,
1634                 .oMSyntax               = 2,
1635                 .attributeSyntax_oid    = "2.5.5.9",
1636                 .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
1637                 .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
1638                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1639                 .equality               = "integerMatch",
1640                 .comment                = "Integer",
1641                 .ldb_syntax             = LDB_SYNTAX_SAMBA_INT32
1642         },{
1643                 .name                   = "String(Octet)",
1644                 .ldap_oid               = LDB_SYNTAX_OCTET_STRING,
1645                 .oMSyntax               = 4,
1646                 .attributeSyntax_oid    = "2.5.5.10",
1647                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1648                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1649                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1650                 .equality               = "octetStringMatch",
1651                 .comment                = "Octet String",
1652         },{
1653                 .name                   = "String(Sid)",
1654                 .ldap_oid               = LDB_SYNTAX_OCTET_STRING,
1655                 .oMSyntax               = 4,
1656                 .attributeSyntax_oid    = "2.5.5.17",
1657                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1658                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1659                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1660                 .equality               = "octetStringMatch",
1661                 .comment                = "Octet String - Security Identifier (SID)",
1662                 .ldb_syntax             = LDB_SYNTAX_SAMBA_SID
1663         },{
1664                 .name                   = "String(Object-Identifier)",
1665                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.38",
1666                 .oMSyntax               = 6,
1667                 .attributeSyntax_oid    = "2.5.5.2",
1668                 .drsuapi_to_ldb         = dsdb_syntax_OID_drsuapi_to_ldb,
1669                 .ldb_to_drsuapi         = dsdb_syntax_OID_ldb_to_drsuapi,
1670                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1671                 .equality               = "caseIgnoreMatch", /* Would use "objectIdentifierMatch" but most are ldap attribute/class names */
1672                 .comment                = "OID String",
1673                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING
1674         },{
1675                 .name                   = "Enumeration",
1676                 .ldap_oid               = LDB_SYNTAX_INTEGER,
1677                 .oMSyntax               = 10,
1678                 .attributeSyntax_oid    = "2.5.5.9",
1679                 .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
1680                 .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
1681                 .validate_ldb           = dsdb_syntax_INT32_validate_ldb,
1682                 .ldb_syntax             = LDB_SYNTAX_SAMBA_INT32
1683         },{
1684         /* not used in w2k3 forest */
1685                 .name                   = "String(Numeric)",
1686                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.36",
1687                 .oMSyntax               = 18,
1688                 .attributeSyntax_oid    = "2.5.5.6",
1689                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1690                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1691                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1692                 .equality               = "numericStringMatch",
1693                 .substring              = "numericStringSubstringsMatch",
1694                 .comment                = "Numeric String",
1695                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1696         },{
1697                 .name                   = "String(Printable)",
1698                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.44",
1699                 .oMSyntax               = 19,
1700                 .attributeSyntax_oid    = "2.5.5.5",
1701                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1702                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1703                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1704                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
1705         },{
1706                 .name                   = "String(Teletex)",
1707                 .ldap_oid               = "1.2.840.113556.1.4.905",
1708                 .oMSyntax               = 20,
1709                 .attributeSyntax_oid    = "2.5.5.4",
1710                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1711                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1712                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1713                 .equality               = "caseIgnoreMatch",
1714                 .substring              = "caseIgnoreSubstringsMatch",
1715                 .comment                = "Case Insensitive String",
1716                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1717         },{
1718                 .name                   = "String(IA5)",
1719                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.26",
1720                 .oMSyntax               = 22,
1721                 .attributeSyntax_oid    = "2.5.5.5",
1722                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1723                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1724                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1725                 .equality               = "caseExactIA5Match",
1726                 .comment                = "Printable String",
1727                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
1728         },{
1729                 .name                   = "String(UTC-Time)",
1730                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.53",
1731                 .oMSyntax               = 23,
1732                 .attributeSyntax_oid    = "2.5.5.11",
1733                 .drsuapi_to_ldb         = dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb,
1734                 .ldb_to_drsuapi         = dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi,
1735                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1736                 .equality               = "generalizedTimeMatch",
1737                 .comment                = "UTC Time",
1738         },{
1739                 .name                   = "String(Generalized-Time)",
1740                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.24",
1741                 .oMSyntax               = 24,
1742                 .attributeSyntax_oid    = "2.5.5.11",
1743                 .drsuapi_to_ldb         = dsdb_syntax_NTTIME_drsuapi_to_ldb,
1744                 .ldb_to_drsuapi         = dsdb_syntax_NTTIME_ldb_to_drsuapi,
1745                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1746                 .equality               = "generalizedTimeMatch",
1747                 .comment                = "Generalized Time",
1748                 .ldb_syntax             = LDB_SYNTAX_UTC_TIME,
1749         },{
1750         /* not used in w2k3 schema */
1751                 .name                   = "String(Case Sensitive)",
1752                 .ldap_oid               = "1.2.840.113556.1.4.1362",
1753                 .oMSyntax               = 27,
1754                 .attributeSyntax_oid    = "2.5.5.3",
1755                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1756                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1757                 .validate_ldb           = dsdb_syntax_FOOBAR_validate_ldb,
1758         },{
1759                 .name                   = "String(Unicode)",
1760                 .ldap_oid               = LDB_SYNTAX_DIRECTORY_STRING,
1761                 .oMSyntax               = 64,
1762                 .attributeSyntax_oid    = "2.5.5.12",
1763                 .drsuapi_to_ldb         = dsdb_syntax_UNICODE_drsuapi_to_ldb,
1764                 .ldb_to_drsuapi         = dsdb_syntax_UNICODE_ldb_to_drsuapi,
1765                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1766                 .equality               = "caseIgnoreMatch",
1767                 .substring              = "caseIgnoreSubstringsMatch",
1768                 .comment                = "Directory String",
1769         },{
1770                 .name                   = "Interval/LargeInteger",
1771                 .ldap_oid               = "1.2.840.113556.1.4.906",
1772                 .oMSyntax               = 65,
1773                 .attributeSyntax_oid    = "2.5.5.16",
1774                 .drsuapi_to_ldb         = dsdb_syntax_INT64_drsuapi_to_ldb,
1775                 .ldb_to_drsuapi         = dsdb_syntax_INT64_ldb_to_drsuapi,
1776                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1777                 .equality               = "integerMatch",
1778                 .comment                = "Large Integer",
1779                 .ldb_syntax             = LDB_SYNTAX_INTEGER,
1780         },{
1781                 .name                   = "String(NT-Sec-Desc)",
1782                 .ldap_oid               = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1783                 .oMSyntax               = 66,
1784                 .attributeSyntax_oid    = "2.5.5.15",
1785                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1786                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1787                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1788         },{
1789                 .name                   = "Object(DS-DN)",
1790                 .ldap_oid               = LDB_SYNTAX_DN,
1791                 .oMSyntax               = 127,
1792                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x4a"),
1793                 .attributeSyntax_oid    = "2.5.5.1",
1794                 .drsuapi_to_ldb         = dsdb_syntax_DN_drsuapi_to_ldb,
1795                 .ldb_to_drsuapi         = dsdb_syntax_DN_ldb_to_drsuapi,
1796                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1797                 .equality               = "distinguishedNameMatch",
1798                 .comment                = "Object(DS-DN) == a DN",
1799         },{
1800                 .name                   = "Object(DN-Binary)",
1801                 .ldap_oid               = DSDB_SYNTAX_BINARY_DN,
1802                 .oMSyntax               = 127,
1803                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0b"),
1804                 .attributeSyntax_oid    = "2.5.5.7",
1805                 .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
1806                 .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
1807                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1808                 .equality               = "octetStringMatch",
1809                 .comment                = "OctetString: Binary+DN",
1810         },{
1811         /* not used in w2k3 schema, but used in Exchange schema*/
1812                 .name                   = "Object(OR-Name)",
1813                 .ldap_oid               = DSDB_SYNTAX_OR_NAME,
1814                 .oMSyntax               = 127,
1815                 .oMObjectClass          = OMOBJECTCLASS("\x56\x06\x01\x02\x05\x0b\x1D"),
1816                 .attributeSyntax_oid    = "2.5.5.7",
1817                 .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
1818                 .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
1819                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1820                 .equality               = "caseIgnoreMatch",
1821                 .ldb_syntax             = LDB_SYNTAX_DN,
1822         },{
1823         /* 
1824          * TODO: verify if DATA_BLOB is correct here...!
1825          *
1826          *       repsFrom and repsTo are the only attributes using
1827          *       this attribute syntax, but they're not replicated... 
1828          */
1829                 .name                   = "Object(Replica-Link)",
1830                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.40",
1831                 .oMSyntax               = 127,
1832                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x06"),
1833                 .attributeSyntax_oid    = "2.5.5.10",
1834                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1835                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1836                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1837         },{
1838                 .name                   = "Object(Presentation-Address)",
1839                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.43",
1840                 .oMSyntax               = 127,
1841                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x5c"),
1842                 .attributeSyntax_oid    = "2.5.5.13",
1843                 .drsuapi_to_ldb         = dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb,
1844                 .ldb_to_drsuapi         = dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi,
1845                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1846                 .comment                = "Presentation Address",
1847                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1848         },{
1849         /* not used in w2k3 schema */
1850                 .name                   = "Object(Access-Point)",
1851                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.2",
1852                 .oMSyntax               = 127,
1853                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x3e"),
1854                 .attributeSyntax_oid    = "2.5.5.14",
1855                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1856                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1857                 .validate_ldb           = dsdb_syntax_FOOBAR_validate_ldb,
1858                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1859         },{
1860         /* not used in w2k3 schema */
1861                 .name                   = "Object(DN-String)",
1862                 .ldap_oid               = DSDB_SYNTAX_STRING_DN,
1863                 .oMSyntax               = 127,
1864                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0c"),
1865                 .attributeSyntax_oid    = "2.5.5.14",
1866                 .drsuapi_to_ldb         = dsdb_syntax_DN_STRING_drsuapi_to_ldb,
1867                 .ldb_to_drsuapi         = dsdb_syntax_DN_STRING_ldb_to_drsuapi,
1868                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1869                 .equality               = "octetStringMatch",
1870                 .comment                = "OctetString: String+DN",
1871         }
1872 };
1873
1874 const struct dsdb_syntax *find_syntax_map_by_ad_oid(const char *ad_oid) 
1875 {
1876         int i;
1877         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1878                 if (strcasecmp(ad_oid, dsdb_syntaxes[i].attributeSyntax_oid) == 0) {
1879                         return &dsdb_syntaxes[i];
1880                 }
1881         }
1882         return NULL;
1883 }
1884
1885 const struct dsdb_syntax *find_syntax_map_by_ad_syntax(int oMSyntax) 
1886 {
1887         int i;
1888         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1889                 if (oMSyntax == dsdb_syntaxes[i].oMSyntax) {
1890                         return &dsdb_syntaxes[i];
1891                 }
1892         }
1893         return NULL;
1894 }
1895
1896 const struct dsdb_syntax *find_syntax_map_by_standard_oid(const char *standard_oid) 
1897 {
1898         int i;
1899         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1900                 if (strcasecmp(standard_oid, dsdb_syntaxes[i].ldap_oid) == 0) {
1901                         return &dsdb_syntaxes[i];
1902                 }
1903         }
1904         return NULL;
1905 }
1906 const struct dsdb_syntax *dsdb_syntax_for_attribute(const struct dsdb_attribute *attr)
1907 {
1908         uint32_t i;
1909
1910         for (i=0; i < ARRAY_SIZE(dsdb_syntaxes); i++) {
1911                 if (attr->oMSyntax != dsdb_syntaxes[i].oMSyntax) continue;
1912
1913                 if (attr->oMObjectClass.length != dsdb_syntaxes[i].oMObjectClass.length) continue;
1914
1915                 if (attr->oMObjectClass.length) {
1916                         int ret;
1917                         ret = memcmp(attr->oMObjectClass.data,
1918                                      dsdb_syntaxes[i].oMObjectClass.data,
1919                                      attr->oMObjectClass.length);
1920                         if (ret != 0) continue;
1921                 }
1922
1923                 if (strcmp(attr->attributeSyntax_oid, dsdb_syntaxes[i].attributeSyntax_oid) != 0) continue;
1924
1925                 return &dsdb_syntaxes[i];
1926         }
1927
1928         return NULL;
1929 }
1930
1931 WERROR dsdb_attribute_drsuapi_to_ldb(struct ldb_context *ldb, 
1932                                      const struct dsdb_schema *schema,
1933                                      const struct drsuapi_DsReplicaAttribute *in,
1934                                      TALLOC_CTX *mem_ctx,
1935                                      struct ldb_message_element *out)
1936 {
1937         const struct dsdb_attribute *sa;
1938
1939         sa = dsdb_attribute_by_attributeID_id(schema, in->attid);
1940         if (!sa) {
1941                 return WERR_FOOBAR;
1942         }
1943
1944         return sa->syntax->drsuapi_to_ldb(ldb, schema, sa, in, mem_ctx, out);
1945 }
1946
1947 WERROR dsdb_attribute_ldb_to_drsuapi(struct ldb_context *ldb, 
1948                                      const struct dsdb_schema *schema,
1949                                      const struct ldb_message_element *in,
1950                                      TALLOC_CTX *mem_ctx,
1951                                      struct drsuapi_DsReplicaAttribute *out)
1952 {
1953         const struct dsdb_attribute *sa;
1954
1955         sa = dsdb_attribute_by_lDAPDisplayName(schema, in->name);
1956         if (!sa) {
1957                 return WERR_FOOBAR;
1958         }
1959
1960         return sa->syntax->ldb_to_drsuapi(ldb, schema, sa, in, mem_ctx, out);
1961 }
1962
1963 WERROR dsdb_attribute_validate_ldb(struct ldb_context *ldb,
1964                                    const struct dsdb_schema *schema,
1965                                    const struct ldb_message_element *in)
1966 {
1967         const struct dsdb_attribute *sa;
1968
1969         sa = dsdb_attribute_by_lDAPDisplayName(schema, in->name);
1970         if (!sa) {
1971                 return WERR_DS_ATTRIBUTE_TYPE_UNDEFINED;
1972         }
1973
1974         return sa->syntax->validate_ldb(ldb, schema, sa, in);
1975 }