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