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