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