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