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