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