Don't treat the DN+binary syntax as a DN.
[kai/samba.git] / source4 / dsdb / schema / schema_syntax.c
1 /* 
2    Unix SMB/CIFS mplementation.
3    DSDB schema syntaxes
4    
5    Copyright (C) Stefan Metzmacher <metze@samba.org> 2006
6    Copyright (C) Simo Sorce 2005
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21    
22 */
23 #include "includes.h"
24 #include "dsdb/samdb/samdb.h"
25 #include "librpc/gen_ndr/ndr_drsuapi.h"
26 #include "lib/ldb/include/ldb.h"
27 #include "system/time.h"
28 #include "../lib/util/charset/charset.h"
29 #include "librpc/ndr/libndr.h"
30
31 static WERROR dsdb_syntax_FOOBAR_drsuapi_to_ldb(const struct dsdb_schema *schema,
32                                                 const struct dsdb_attribute *attr,
33                                                 const struct drsuapi_DsReplicaAttribute *in,
34                                                 TALLOC_CTX *mem_ctx,
35                                                 struct ldb_message_element *out)
36 {
37         uint32_t i;
38
39         out->flags      = 0;
40         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
41         W_ERROR_HAVE_NO_MEMORY(out->name);
42
43         out->num_values = in->value_ctr.num_values;
44         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
45         W_ERROR_HAVE_NO_MEMORY(out->values);
46
47         for (i=0; i < out->num_values; i++) {
48                 char *str;
49
50                 if (in->value_ctr.values[i].blob == NULL) {
51                         return WERR_FOOBAR;
52                 }
53
54                 str = talloc_asprintf(out->values, "%s: not implemented",
55                                       attr->syntax->name);
56                 W_ERROR_HAVE_NO_MEMORY(str);
57
58                 out->values[i] = data_blob_string_const(str);
59         }
60
61         return WERR_OK;
62 }
63
64 static WERROR dsdb_syntax_FOOBAR_ldb_to_drsuapi(const struct dsdb_schema *schema,
65                                                 const struct dsdb_attribute *attr,
66                                                 const struct ldb_message_element *in,
67                                                 TALLOC_CTX *mem_ctx,
68                                                 struct drsuapi_DsReplicaAttribute *out)
69 {
70         return WERR_FOOBAR;
71 }
72
73 static WERROR dsdb_syntax_BOOL_drsuapi_to_ldb(const struct dsdb_schema *schema,
74                                               const struct dsdb_attribute *attr,
75                                               const struct drsuapi_DsReplicaAttribute *in,
76                                               TALLOC_CTX *mem_ctx,
77                                               struct ldb_message_element *out)
78 {
79         uint32_t i;
80
81         out->flags      = 0;
82         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
83         W_ERROR_HAVE_NO_MEMORY(out->name);
84
85         out->num_values = in->value_ctr.num_values;
86         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
87         W_ERROR_HAVE_NO_MEMORY(out->values);
88
89         for (i=0; i < out->num_values; i++) {
90                 uint32_t v;
91                 char *str;
92
93                 if (in->value_ctr.values[i].blob == NULL) {
94                         return WERR_FOOBAR;
95                 }
96
97                 if (in->value_ctr.values[i].blob->length != 4) {
98                         return WERR_FOOBAR;
99                 }
100
101                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
102
103                 if (v != 0) {
104                         str = talloc_strdup(out->values, "TRUE");
105                         W_ERROR_HAVE_NO_MEMORY(str);
106                 } else {
107                         str = talloc_strdup(out->values, "FALSE");
108                         W_ERROR_HAVE_NO_MEMORY(str);
109                 }
110
111                 out->values[i] = data_blob_string_const(str);
112         }
113
114         return WERR_OK;
115 }
116
117 static WERROR dsdb_syntax_BOOL_ldb_to_drsuapi(const struct dsdb_schema *schema,
118                                               const struct dsdb_attribute *attr,
119                                               const struct ldb_message_element *in,
120                                               TALLOC_CTX *mem_ctx,
121                                               struct drsuapi_DsReplicaAttribute *out)
122 {
123         uint32_t i;
124         DATA_BLOB *blobs;
125
126         if (attr->attributeID_id == 0xFFFFFFFF) {
127                 return WERR_FOOBAR;
128         }
129
130         out->attid                      = attr->attributeID_id;
131         out->value_ctr.num_values       = in->num_values;
132         out->value_ctr.values           = talloc_array(mem_ctx,
133                                                        struct drsuapi_DsAttributeValue,
134                                                        in->num_values);
135         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
136
137         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
138         W_ERROR_HAVE_NO_MEMORY(blobs);
139
140         for (i=0; i < in->num_values; i++) {
141                 out->value_ctr.values[i].blob   = &blobs[i];
142
143                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
144                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
145
146                 if (strcmp("TRUE", (const char *)in->values[i].data) == 0) {
147                         SIVAL(blobs[i].data, 0, 0x00000001);
148                 } else if (strcmp("FALSE", (const char *)in->values[i].data) == 0) {
149                         SIVAL(blobs[i].data, 0, 0x00000000);
150                 } else {
151                         return WERR_FOOBAR;
152                 }
153         }
154
155         return WERR_OK;
156 }
157
158 static WERROR dsdb_syntax_INT32_drsuapi_to_ldb(const struct dsdb_schema *schema,
159                                                const struct dsdb_attribute *attr,
160                                                const struct drsuapi_DsReplicaAttribute *in,
161                                                TALLOC_CTX *mem_ctx,
162                                                struct ldb_message_element *out)
163 {
164         uint32_t i;
165
166         out->flags      = 0;
167         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
168         W_ERROR_HAVE_NO_MEMORY(out->name);
169
170         out->num_values = in->value_ctr.num_values;
171         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
172         W_ERROR_HAVE_NO_MEMORY(out->values);
173
174         for (i=0; i < out->num_values; i++) {
175                 int32_t v;
176                 char *str;
177
178                 if (in->value_ctr.values[i].blob == NULL) {
179                         return WERR_FOOBAR;
180                 }
181
182                 if (in->value_ctr.values[i].blob->length != 4) {
183                         return WERR_FOOBAR;
184                 }
185
186                 v = IVALS(in->value_ctr.values[i].blob->data, 0);
187
188                 str = talloc_asprintf(out->values, "%d", v);
189                 W_ERROR_HAVE_NO_MEMORY(str);
190
191                 out->values[i] = data_blob_string_const(str);
192         }
193
194         return WERR_OK;
195 }
196
197 static WERROR dsdb_syntax_INT32_ldb_to_drsuapi(const struct dsdb_schema *schema,
198                                                const struct dsdb_attribute *attr,
199                                                const struct ldb_message_element *in,
200                                                TALLOC_CTX *mem_ctx,
201                                                struct drsuapi_DsReplicaAttribute *out)
202 {
203         uint32_t i;
204         DATA_BLOB *blobs;
205
206         if (attr->attributeID_id == 0xFFFFFFFF) {
207                 return WERR_FOOBAR;
208         }
209
210         out->attid                      = attr->attributeID_id;
211         out->value_ctr.num_values       = in->num_values;
212         out->value_ctr.values           = talloc_array(mem_ctx,
213                                                        struct drsuapi_DsAttributeValue,
214                                                        in->num_values);
215         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
216
217         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
218         W_ERROR_HAVE_NO_MEMORY(blobs);
219
220         for (i=0; i < in->num_values; i++) {
221                 int32_t v;
222
223                 out->value_ctr.values[i].blob   = &blobs[i];
224
225                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
226                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
227
228                 v = strtol((const char *)in->values[i].data, NULL, 10);
229
230                 SIVALS(blobs[i].data, 0, v);
231         }
232
233         return WERR_OK;
234 }
235
236 static WERROR dsdb_syntax_INT64_drsuapi_to_ldb(const struct dsdb_schema *schema,
237                                                const struct dsdb_attribute *attr,
238                                                const struct drsuapi_DsReplicaAttribute *in,
239                                                TALLOC_CTX *mem_ctx,
240                                                struct ldb_message_element *out)
241 {
242         uint32_t i;
243
244         out->flags      = 0;
245         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
246         W_ERROR_HAVE_NO_MEMORY(out->name);
247
248         out->num_values = in->value_ctr.num_values;
249         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
250         W_ERROR_HAVE_NO_MEMORY(out->values);
251
252         for (i=0; i < out->num_values; i++) {
253                 int64_t v;
254                 char *str;
255
256                 if (in->value_ctr.values[i].blob == NULL) {
257                         return WERR_FOOBAR;
258                 }
259
260                 if (in->value_ctr.values[i].blob->length != 8) {
261                         return WERR_FOOBAR;
262                 }
263
264                 v = BVALS(in->value_ctr.values[i].blob->data, 0);
265
266                 str = talloc_asprintf(out->values, "%lld", (long long int)v);
267                 W_ERROR_HAVE_NO_MEMORY(str);
268
269                 out->values[i] = data_blob_string_const(str);
270         }
271
272         return WERR_OK;
273 }
274
275 static WERROR dsdb_syntax_INT64_ldb_to_drsuapi(const struct dsdb_schema *schema,
276                                                const struct dsdb_attribute *attr,
277                                                const struct ldb_message_element *in,
278                                                TALLOC_CTX *mem_ctx,
279                                                struct drsuapi_DsReplicaAttribute *out)
280 {
281         uint32_t i;
282         DATA_BLOB *blobs;
283
284         if (attr->attributeID_id == 0xFFFFFFFF) {
285                 return WERR_FOOBAR;
286         }
287
288         out->attid                      = attr->attributeID_id;
289         out->value_ctr.num_values       = in->num_values;
290         out->value_ctr.values           = talloc_array(mem_ctx,
291                                                        struct drsuapi_DsAttributeValue,
292                                                        in->num_values);
293         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
294
295         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
296         W_ERROR_HAVE_NO_MEMORY(blobs);
297
298         for (i=0; i < in->num_values; i++) {
299                 int64_t v;
300
301                 out->value_ctr.values[i].blob   = &blobs[i];
302
303                 blobs[i] = data_blob_talloc(blobs, NULL, 8);
304                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
305
306                 v = strtoll((const char *)in->values[i].data, NULL, 10);
307
308                 SBVALS(blobs[i].data, 0, v);
309         }
310
311         return WERR_OK;
312 }
313
314 static WERROR dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb(const struct dsdb_schema *schema,
315                                                     const struct dsdb_attribute *attr,
316                                                     const struct drsuapi_DsReplicaAttribute *in,
317                                                     TALLOC_CTX *mem_ctx,
318                                                     struct ldb_message_element *out)
319 {
320         uint32_t i;
321
322         out->flags      = 0;
323         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
324         W_ERROR_HAVE_NO_MEMORY(out->name);
325
326         out->num_values = in->value_ctr.num_values;
327         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
328         W_ERROR_HAVE_NO_MEMORY(out->values);
329
330         for (i=0; i < out->num_values; i++) {
331                 NTTIME v;
332                 time_t t;
333                 char *str;
334
335                 if (in->value_ctr.values[i].blob == NULL) {
336                         return WERR_FOOBAR;
337                 }
338
339                 if (in->value_ctr.values[i].blob->length != 8) {
340                         return WERR_FOOBAR;
341                 }
342
343                 v = BVAL(in->value_ctr.values[i].blob->data, 0);
344                 v *= 10000000;
345                 t = nt_time_to_unix(v);
346
347                 /* 
348                  * NOTE: On a w2k3 server you can set a GeneralizedTime string
349                  *       via LDAP, but you get back an UTCTime string,
350                  *       but via DRSUAPI you get back the NTTIME_1sec value
351                  *       that represents the GeneralizedTime value!
352                  *
353                  *       So if we store the UTCTime string in our ldb
354                  *       we'll loose information!
355                  */
356                 str = ldb_timestring_utc(out->values, t); 
357                 W_ERROR_HAVE_NO_MEMORY(str);
358                 out->values[i] = data_blob_string_const(str);
359         }
360
361         return WERR_OK;
362 }
363
364 static WERROR dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi(const struct dsdb_schema *schema,
365                                                     const struct dsdb_attribute *attr,
366                                                     const struct ldb_message_element *in,
367                                                     TALLOC_CTX *mem_ctx,
368                                                     struct drsuapi_DsReplicaAttribute *out)
369 {
370         uint32_t i;
371         DATA_BLOB *blobs;
372
373         if (attr->attributeID_id == 0xFFFFFFFF) {
374                 return WERR_FOOBAR;
375         }
376
377         out->attid                      = attr->attributeID_id;
378         out->value_ctr.num_values       = in->num_values;
379         out->value_ctr.values           = talloc_array(mem_ctx,
380                                                        struct drsuapi_DsAttributeValue,
381                                                        in->num_values);
382         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
383
384         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
385         W_ERROR_HAVE_NO_MEMORY(blobs);
386
387         for (i=0; i < in->num_values; i++) {
388                 NTTIME v;
389                 time_t t;
390
391                 out->value_ctr.values[i].blob   = &blobs[i];
392
393                 blobs[i] = data_blob_talloc(blobs, NULL, 8);
394                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
395
396                 t = ldb_string_utc_to_time((const char *)in->values[i].data);
397                 unix_to_nt_time(&v, t);
398                 v /= 10000000;
399
400                 SBVAL(blobs[i].data, 0, v);
401         }
402
403         return WERR_OK;
404 }
405
406 static WERROR dsdb_syntax_NTTIME_drsuapi_to_ldb(const struct dsdb_schema *schema,
407                                                 const struct dsdb_attribute *attr,
408                                                 const struct drsuapi_DsReplicaAttribute *in,
409                                                 TALLOC_CTX *mem_ctx,
410                                                 struct ldb_message_element *out)
411 {
412         uint32_t i;
413
414         out->flags      = 0;
415         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
416         W_ERROR_HAVE_NO_MEMORY(out->name);
417
418         out->num_values = in->value_ctr.num_values;
419         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
420         W_ERROR_HAVE_NO_MEMORY(out->values);
421
422         for (i=0; i < out->num_values; i++) {
423                 NTTIME v;
424                 time_t t;
425                 char *str;
426
427                 if (in->value_ctr.values[i].blob == NULL) {
428                         return WERR_FOOBAR;
429                 }
430
431                 if (in->value_ctr.values[i].blob->length != 8) {
432                         return WERR_FOOBAR;
433                 }
434
435                 v = BVAL(in->value_ctr.values[i].blob->data, 0);
436                 v *= 10000000;
437                 t = nt_time_to_unix(v);
438
439                 str = ldb_timestring(out->values, t); 
440                 W_ERROR_HAVE_NO_MEMORY(str);
441
442                 out->values[i] = data_blob_string_const(str);
443         }
444
445         return WERR_OK;
446 }
447
448 static WERROR dsdb_syntax_NTTIME_ldb_to_drsuapi(const struct dsdb_schema *schema,
449                                                 const struct dsdb_attribute *attr,
450                                                 const struct ldb_message_element *in,
451                                                 TALLOC_CTX *mem_ctx,
452                                                 struct drsuapi_DsReplicaAttribute *out)
453 {
454         uint32_t i;
455         DATA_BLOB *blobs;
456
457         if (attr->attributeID_id == 0xFFFFFFFF) {
458                 return WERR_FOOBAR;
459         }
460
461         out->attid                      = attr->attributeID_id;
462         out->value_ctr.num_values       = in->num_values;
463         out->value_ctr.values           = talloc_array(mem_ctx,
464                                                        struct drsuapi_DsAttributeValue,
465                                                        in->num_values);
466         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
467
468         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
469         W_ERROR_HAVE_NO_MEMORY(blobs);
470
471         for (i=0; i < in->num_values; i++) {
472                 NTTIME v;
473                 time_t t;
474
475                 out->value_ctr.values[i].blob   = &blobs[i];
476
477                 blobs[i] = data_blob_talloc(blobs, NULL, 8);
478                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
479
480                 t = ldb_string_to_time((const char *)in->values[i].data);
481                 unix_to_nt_time(&v, t);
482                 v /= 10000000;
483
484                 SBVAL(blobs[i].data, 0, v);
485         }
486
487         return WERR_OK;
488 }
489
490 static WERROR dsdb_syntax_DATA_BLOB_drsuapi_to_ldb(const struct dsdb_schema *schema,
491                                                    const struct dsdb_attribute *attr,
492                                                    const struct drsuapi_DsReplicaAttribute *in,
493                                                    TALLOC_CTX *mem_ctx,
494                                                    struct ldb_message_element *out)
495 {
496         uint32_t i;
497
498         out->flags      = 0;
499         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
500         W_ERROR_HAVE_NO_MEMORY(out->name);
501
502         out->num_values = in->value_ctr.num_values;
503         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
504         W_ERROR_HAVE_NO_MEMORY(out->values);
505
506         for (i=0; i < out->num_values; i++) {
507                 if (in->value_ctr.values[i].blob == NULL) {
508                         return WERR_FOOBAR;
509                 }
510
511                 if (in->value_ctr.values[i].blob->length == 0) {
512                         return WERR_FOOBAR;
513                 }
514
515                 out->values[i] = data_blob_dup_talloc(out->values,
516                                                       in->value_ctr.values[i].blob);
517                 W_ERROR_HAVE_NO_MEMORY(out->values[i].data);
518         }
519
520         return WERR_OK;
521 }
522
523 static WERROR dsdb_syntax_DATA_BLOB_ldb_to_drsuapi(const struct dsdb_schema *schema,
524                                                    const struct dsdb_attribute *attr,
525                                                    const struct ldb_message_element *in,
526                                                    TALLOC_CTX *mem_ctx,
527                                                    struct drsuapi_DsReplicaAttribute *out)
528 {
529         uint32_t i;
530         DATA_BLOB *blobs;
531
532         if (attr->attributeID_id == 0xFFFFFFFF) {
533                 return WERR_FOOBAR;
534         }
535
536         out->attid                      = attr->attributeID_id;
537         out->value_ctr.num_values       = in->num_values;
538         out->value_ctr.values           = talloc_array(mem_ctx,
539                                                        struct drsuapi_DsAttributeValue,
540                                                        in->num_values);
541         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
542
543         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
544         W_ERROR_HAVE_NO_MEMORY(blobs);
545
546         for (i=0; i < in->num_values; i++) {
547                 out->value_ctr.values[i].blob   = &blobs[i];
548
549                 blobs[i] = data_blob_dup_talloc(blobs, &in->values[i]);
550                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
551         }
552
553         return WERR_OK;
554 }
555
556 static WERROR _dsdb_syntax_OID_obj_drsuapi_to_ldb(const struct dsdb_schema *schema,
557                                                   const struct dsdb_attribute *attr,
558                                                   const struct drsuapi_DsReplicaAttribute *in,
559                                                   TALLOC_CTX *mem_ctx,
560                                                   struct ldb_message_element *out)
561 {
562         uint32_t i;
563
564         out->flags      = 0;
565         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
566         W_ERROR_HAVE_NO_MEMORY(out->name);
567
568         out->num_values = in->value_ctr.num_values;
569         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
570         W_ERROR_HAVE_NO_MEMORY(out->values);
571
572         for (i=0; i < out->num_values; i++) {
573                 uint32_t v;
574                 const struct dsdb_class *c;
575                 const char *str;
576
577                 if (in->value_ctr.values[i].blob == NULL) {
578                         return WERR_FOOBAR;
579                 }
580
581                 if (in->value_ctr.values[i].blob->length != 4) {
582                         return WERR_FOOBAR;
583                 }
584
585                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
586
587                 c = dsdb_class_by_governsID_id(schema, v);
588                 if (!c) {
589                         return WERR_FOOBAR;
590                 }
591
592                 str = talloc_strdup(out->values, c->lDAPDisplayName);
593                 W_ERROR_HAVE_NO_MEMORY(str);
594
595                 /* the values need to be reversed */
596                 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
597         }
598
599         return WERR_OK;
600 }
601
602 static WERROR _dsdb_syntax_OID_oid_drsuapi_to_ldb(const struct dsdb_schema *schema,
603                                                   const struct dsdb_attribute *attr,
604                                                   const struct drsuapi_DsReplicaAttribute *in,
605                                                   TALLOC_CTX *mem_ctx,
606                                                   struct ldb_message_element *out)
607 {
608         uint32_t i;
609
610         out->flags      = 0;
611         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
612         W_ERROR_HAVE_NO_MEMORY(out->name);
613
614         out->num_values = in->value_ctr.num_values;
615         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
616         W_ERROR_HAVE_NO_MEMORY(out->values);
617
618         for (i=0; i < out->num_values; i++) {
619                 uint32_t v;
620                 WERROR status;
621                 const char *str;
622
623                 if (in->value_ctr.values[i].blob == NULL) {
624                         return WERR_FOOBAR;
625                 }
626
627                 if (in->value_ctr.values[i].blob->length != 4) {
628                         return WERR_FOOBAR;
629                 }
630
631                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
632
633                 status = dsdb_map_int2oid(schema, v, out->values, &str);
634                 W_ERROR_NOT_OK_RETURN(status);
635
636                 out->values[i] = data_blob_string_const(str);
637         }
638
639         return WERR_OK;
640 }
641
642 static WERROR dsdb_syntax_OID_drsuapi_to_ldb(const struct dsdb_schema *schema,
643                                              const struct dsdb_attribute *attr,
644                                              const struct drsuapi_DsReplicaAttribute *in,
645                                              TALLOC_CTX *mem_ctx,
646                                              struct ldb_message_element *out)
647 {
648         uint32_t i;
649
650         switch (attr->attributeID_id) {
651         case DRSUAPI_ATTRIBUTE_objectClass:
652                 return _dsdb_syntax_OID_obj_drsuapi_to_ldb(schema, attr, in, mem_ctx, out);
653         case DRSUAPI_ATTRIBUTE_governsID:
654         case DRSUAPI_ATTRIBUTE_attributeID:
655         case DRSUAPI_ATTRIBUTE_attributeSyntax:
656                 return _dsdb_syntax_OID_oid_drsuapi_to_ldb(schema, attr, in, mem_ctx, out);
657         }
658
659         out->flags      = 0;
660         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
661         W_ERROR_HAVE_NO_MEMORY(out->name);
662
663         out->num_values = in->value_ctr.num_values;
664         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
665         W_ERROR_HAVE_NO_MEMORY(out->values);
666
667         for (i=0; i < out->num_values; i++) {
668                 uint32_t v;
669                 const char *name;
670                 char *str;
671
672                 if (in->value_ctr.values[i].blob == NULL) {
673                         return WERR_FOOBAR;
674                 }
675
676                 if (in->value_ctr.values[i].blob->length != 4) {
677                         return WERR_FOOBAR;
678                 }
679
680                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
681
682                 name = dsdb_lDAPDisplayName_by_id(schema, v);
683                 if (!name) {
684                         return WERR_FOOBAR;
685                 }
686
687                 str = talloc_strdup(out->values, name);
688                 W_ERROR_HAVE_NO_MEMORY(str);
689
690                 out->values[i] = data_blob_string_const(str);
691         }
692
693         return WERR_OK;
694 }
695
696 static WERROR dsdb_syntax_OID_ldb_to_drsuapi(const struct dsdb_schema *schema,
697                                              const struct dsdb_attribute *attr,
698                                              const struct ldb_message_element *in,
699                                              TALLOC_CTX *mem_ctx,
700                                              struct drsuapi_DsReplicaAttribute *out)
701 {
702         uint32_t i;
703         DATA_BLOB *blobs;
704
705         if (attr->attributeID_id == 0xFFFFFFFF) {
706                 return WERR_FOOBAR;
707         }
708
709         switch (attr->attributeID_id) {
710         case DRSUAPI_ATTRIBUTE_objectClass:
711         case DRSUAPI_ATTRIBUTE_governsID:
712         case DRSUAPI_ATTRIBUTE_attributeID:
713         case DRSUAPI_ATTRIBUTE_attributeSyntax:
714                 return dsdb_syntax_FOOBAR_ldb_to_drsuapi(schema, attr, in, mem_ctx, out);
715         }
716
717         out->attid                      = attr->attributeID_id;
718         out->value_ctr.num_values       = in->num_values;
719         out->value_ctr.values           = talloc_array(mem_ctx,
720                                                        struct drsuapi_DsAttributeValue,
721                                                        in->num_values);
722         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
723
724         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
725         W_ERROR_HAVE_NO_MEMORY(blobs);
726
727         for (i=0; i < in->num_values; i++) {
728                 uint32_t v;
729
730                 out->value_ctr.values[i].blob   = &blobs[i];
731
732                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
733                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
734
735                 v = strtol((const char *)in->values[i].data, NULL, 10);
736
737                 SIVAL(blobs[i].data, 0, v);
738         }
739
740         return WERR_OK;
741 }
742
743 static WERROR dsdb_syntax_UNICODE_drsuapi_to_ldb(const struct dsdb_schema *schema,
744                                                  const struct dsdb_attribute *attr,
745                                                  const struct drsuapi_DsReplicaAttribute *in,
746                                                  TALLOC_CTX *mem_ctx,
747                                                  struct ldb_message_element *out)
748 {
749         uint32_t i;
750
751         out->flags      = 0;
752         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
753         W_ERROR_HAVE_NO_MEMORY(out->name);
754
755         out->num_values = in->value_ctr.num_values;
756         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
757         W_ERROR_HAVE_NO_MEMORY(out->values);
758
759         for (i=0; i < out->num_values; i++) {
760                 ssize_t ret;
761                 char *str;
762
763                 if (in->value_ctr.values[i].blob == NULL) {
764                         return WERR_FOOBAR;
765                 }
766
767                 if (in->value_ctr.values[i].blob->length == 0) {
768                         return WERR_FOOBAR;
769                 }
770
771                 ret = convert_string_talloc_convenience(out->values, 
772                                                 schema->iconv_convenience, 
773                                                                         CH_UTF16, CH_UNIX,
774                                             in->value_ctr.values[i].blob->data,
775                                             in->value_ctr.values[i].blob->length,
776                                             (void **)&str);
777                 if (ret == -1) {
778                         return WERR_FOOBAR;
779                 }
780
781                 out->values[i] = data_blob_string_const(str);
782         }
783
784         return WERR_OK;
785 }
786
787 static WERROR dsdb_syntax_UNICODE_ldb_to_drsuapi(const struct dsdb_schema *schema,
788                                                  const struct dsdb_attribute *attr,
789                                                  const struct ldb_message_element *in,
790                                                  TALLOC_CTX *mem_ctx,
791                                                  struct drsuapi_DsReplicaAttribute *out)
792 {
793         uint32_t i;
794         DATA_BLOB *blobs;
795
796         if (attr->attributeID_id == 0xFFFFFFFF) {
797                 return WERR_FOOBAR;
798         }
799
800         out->attid                      = attr->attributeID_id;
801         out->value_ctr.num_values       = in->num_values;
802         out->value_ctr.values           = talloc_array(mem_ctx,
803                                                        struct drsuapi_DsAttributeValue,
804                                                        in->num_values);
805         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
806
807         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
808         W_ERROR_HAVE_NO_MEMORY(blobs);
809
810         for (i=0; i < in->num_values; i++) {
811                 ssize_t ret;
812
813                 out->value_ctr.values[i].blob   = &blobs[i];
814
815                 ret = convert_string_talloc_convenience(blobs, schema->iconv_convenience, CH_UNIX, CH_UTF16,
816                                             in->values[i].data,
817                                             in->values[i].length,
818                                             (void **)&blobs[i].data);
819                 if (ret == -1) {
820                         return WERR_FOOBAR;
821                 }
822                 blobs[i].length = ret;
823         }
824
825         return WERR_OK;
826 }
827
828 static WERROR dsdb_syntax_DN_drsuapi_to_ldb(const struct dsdb_schema *schema,
829                                             const struct dsdb_attribute *attr,
830                                             const struct drsuapi_DsReplicaAttribute *in,
831                                             TALLOC_CTX *mem_ctx,
832                                             struct ldb_message_element *out)
833 {
834         uint32_t i;
835
836         out->flags      = 0;
837         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
838         W_ERROR_HAVE_NO_MEMORY(out->name);
839
840         out->num_values = in->value_ctr.num_values;
841         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
842         W_ERROR_HAVE_NO_MEMORY(out->values);
843
844         for (i=0; i < out->num_values; i++) {
845                 struct drsuapi_DsReplicaObjectIdentifier3 id3;
846                 enum ndr_err_code ndr_err;
847
848                 if (in->value_ctr.values[i].blob == NULL) {
849                         return WERR_FOOBAR;
850                 }
851
852                 if (in->value_ctr.values[i].blob->length == 0) {
853                         return WERR_FOOBAR;
854                 }
855
856                 ndr_err = ndr_pull_struct_blob_all(in->value_ctr.values[i].blob,
857                                                    out->values, schema->iconv_convenience, &id3,
858                                                    (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3);
859                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
860                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
861                         return ntstatus_to_werror(status);
862                 }
863
864                 /* TODO: handle id3.guid and id3.sid */
865                 out->values[i] = data_blob_string_const(id3.dn);
866         }
867
868         return WERR_OK;
869 }
870
871 static WERROR dsdb_syntax_DN_ldb_to_drsuapi(const struct dsdb_schema *schema,
872                                             const struct dsdb_attribute *attr,
873                                             const struct ldb_message_element *in,
874                                             TALLOC_CTX *mem_ctx,
875                                             struct drsuapi_DsReplicaAttribute *out)
876 {
877         uint32_t i;
878         DATA_BLOB *blobs;
879
880         if (attr->attributeID_id == 0xFFFFFFFF) {
881                 return WERR_FOOBAR;
882         }
883
884         out->attid                      = attr->attributeID_id;
885         out->value_ctr.num_values       = in->num_values;
886         out->value_ctr.values           = talloc_array(mem_ctx,
887                                                        struct drsuapi_DsAttributeValue,
888                                                        in->num_values);
889         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
890
891         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
892         W_ERROR_HAVE_NO_MEMORY(blobs);
893
894         for (i=0; i < in->num_values; i++) {
895                 struct drsuapi_DsReplicaObjectIdentifier3 id3;
896                 enum ndr_err_code ndr_err;
897
898                 out->value_ctr.values[i].blob   = &blobs[i];
899
900                 /* TODO: handle id3.guid and id3.sid */
901                 ZERO_STRUCT(id3);
902                 id3.dn = (const char *)in->values[i].data;
903
904                 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
905                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
906                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
907                         return ntstatus_to_werror(status);
908                 }
909         }
910
911         return WERR_OK;
912 }
913
914 static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(const struct dsdb_schema *schema,
915                                                    const struct dsdb_attribute *attr,
916                                                    const struct drsuapi_DsReplicaAttribute *in,
917                                                    TALLOC_CTX *mem_ctx,
918                                                    struct ldb_message_element *out)
919 {
920         uint32_t i;
921
922         out->flags      = 0;
923         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
924         W_ERROR_HAVE_NO_MEMORY(out->name);
925
926         out->num_values = in->value_ctr.num_values;
927         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
928         W_ERROR_HAVE_NO_MEMORY(out->values);
929
930         for (i=0; i < out->num_values; i++) {
931                 struct drsuapi_DsReplicaObjectIdentifier3Binary id3b;
932                 char *binary;
933                 char *str;
934                 enum ndr_err_code ndr_err;
935
936                 if (in->value_ctr.values[i].blob == NULL) {
937                         return WERR_FOOBAR;
938                 }
939
940                 if (in->value_ctr.values[i].blob->length == 0) {
941                         return WERR_FOOBAR;
942                 }
943
944                 ndr_err = ndr_pull_struct_blob_all(in->value_ctr.values[i].blob,
945                                                    out->values, schema->iconv_convenience, &id3b,
946                                                    (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3Binary);
947                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
948                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
949                         return ntstatus_to_werror(status);
950                 }
951
952                 /* TODO: handle id3.guid and id3.sid */
953                 binary = data_blob_hex_string(out->values, &id3b.binary);
954                 W_ERROR_HAVE_NO_MEMORY(binary);
955
956                 str = talloc_asprintf(out->values, "B:%u:%s:%s",
957                                       (unsigned int)(id3b.binary.length * 2), /* because of 2 hex chars per byte */
958                                       binary,
959                                       id3b.dn);
960                 W_ERROR_HAVE_NO_MEMORY(str);
961
962                 /* TODO: handle id3.guid and id3.sid */
963                 out->values[i] = data_blob_string_const(str);
964         }
965
966         return WERR_OK;
967 }
968
969 static WERROR dsdb_syntax_DN_BINARY_ldb_to_drsuapi(const struct dsdb_schema *schema,
970                                                    const struct dsdb_attribute *attr,
971                                                    const struct ldb_message_element *in,
972                                                    TALLOC_CTX *mem_ctx,
973                                                    struct drsuapi_DsReplicaAttribute *out)
974 {
975         uint32_t i;
976         DATA_BLOB *blobs;
977
978         if (attr->attributeID_id == 0xFFFFFFFF) {
979                 return WERR_FOOBAR;
980         }
981
982         out->attid                      = attr->attributeID_id;
983         out->value_ctr.num_values       = in->num_values;
984         out->value_ctr.values           = talloc_array(mem_ctx,
985                                                        struct drsuapi_DsAttributeValue,
986                                                        in->num_values);
987         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
988
989         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
990         W_ERROR_HAVE_NO_MEMORY(blobs);
991
992         for (i=0; i < in->num_values; i++) {
993                 struct drsuapi_DsReplicaObjectIdentifier3Binary id3b;
994                 enum ndr_err_code ndr_err;
995
996                 out->value_ctr.values[i].blob   = &blobs[i];
997
998                 /* TODO: handle id3b.guid and id3b.sid, id3.binary */
999                 ZERO_STRUCT(id3b);
1000                 id3b.dn         = (const char *)in->values[i].data;
1001                 id3b.binary     = data_blob(NULL, 0);
1002
1003                 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3b,
1004                                                (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3Binary);
1005                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1006                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1007                         return ntstatus_to_werror(status);
1008                 }
1009         }
1010
1011         return WERR_OK;
1012 }
1013
1014 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb(const struct dsdb_schema *schema,
1015                                                               const struct dsdb_attribute *attr,
1016                                                               const struct drsuapi_DsReplicaAttribute *in,
1017                                                               TALLOC_CTX *mem_ctx,
1018                                                               struct ldb_message_element *out)
1019 {
1020         uint32_t i;
1021
1022         out->flags      = 0;
1023         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1024         W_ERROR_HAVE_NO_MEMORY(out->name);
1025
1026         out->num_values = in->value_ctr.num_values;
1027         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1028         W_ERROR_HAVE_NO_MEMORY(out->values);
1029
1030         for (i=0; i < out->num_values; i++) {
1031                 uint32_t len;
1032                 ssize_t ret;
1033                 char *str;
1034
1035                 if (in->value_ctr.values[i].blob == NULL) {
1036                         return WERR_FOOBAR;
1037                 }
1038
1039                 if (in->value_ctr.values[i].blob->length < 4) {
1040                         return WERR_FOOBAR;
1041                 }
1042
1043                 len = IVAL(in->value_ctr.values[i].blob->data, 0);
1044
1045                 if (len != in->value_ctr.values[i].blob->length) {
1046                         return WERR_FOOBAR;
1047                 }
1048
1049                 ret = convert_string_talloc_convenience(out->values, schema->iconv_convenience, CH_UTF16, CH_UNIX,
1050                                             in->value_ctr.values[i].blob->data+4,
1051                                             in->value_ctr.values[i].blob->length-4,
1052                                             (void **)&str);
1053                 if (ret == -1) {
1054                         return WERR_FOOBAR;
1055                 }
1056
1057                 out->values[i] = data_blob_string_const(str);
1058         }
1059
1060         return WERR_OK;
1061 }
1062
1063 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi(const struct dsdb_schema *schema,
1064                                                               const struct dsdb_attribute *attr,
1065                                                               const struct ldb_message_element *in,
1066                                                               TALLOC_CTX *mem_ctx,
1067                                                               struct drsuapi_DsReplicaAttribute *out)
1068 {
1069         uint32_t i;
1070         DATA_BLOB *blobs;
1071
1072         if (attr->attributeID_id == 0xFFFFFFFF) {
1073                 return WERR_FOOBAR;
1074         }
1075
1076         out->attid                      = attr->attributeID_id;
1077         out->value_ctr.num_values       = in->num_values;
1078         out->value_ctr.values           = talloc_array(mem_ctx,
1079                                                        struct drsuapi_DsAttributeValue,
1080                                                        in->num_values);
1081         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1082
1083         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1084         W_ERROR_HAVE_NO_MEMORY(blobs);
1085
1086         for (i=0; i < in->num_values; i++) {
1087                 uint8_t *data;
1088                 ssize_t ret;
1089
1090                 out->value_ctr.values[i].blob   = &blobs[i];
1091
1092                 ret = convert_string_talloc_convenience(blobs, schema->iconv_convenience, CH_UNIX, CH_UTF16,
1093                                             in->values[i].data,
1094                                             in->values[i].length,
1095                                             (void **)&data);
1096                 if (ret == -1) {
1097                         return WERR_FOOBAR;
1098                 }
1099
1100                 blobs[i] = data_blob_talloc(blobs, NULL, 4 + ret);
1101                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1102
1103                 SIVAL(blobs[i].data, 0, 4 + ret);
1104
1105                 if (ret > 0) {
1106                         memcpy(blobs[i].data + 4, data, ret);
1107                         talloc_free(data);
1108                 }
1109         }
1110
1111         return WERR_OK;
1112 }
1113
1114 #define OMOBJECTCLASS(val) { .length = sizeof(val) - 1, .data = discard_const_p(uint8_t, val) }
1115
1116 static const struct dsdb_syntax dsdb_syntaxes[] = {
1117         {
1118                 .name                   = "Boolean",
1119                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.7",
1120                 .oMSyntax               = 1,
1121                 .attributeSyntax_oid    = "2.5.5.8",
1122                 .drsuapi_to_ldb         = dsdb_syntax_BOOL_drsuapi_to_ldb,
1123                 .ldb_to_drsuapi         = dsdb_syntax_BOOL_ldb_to_drsuapi,
1124                 .equality               = "booleanMatch",
1125                 .comment                = "Boolean" 
1126         },{
1127                 .name                   = "Integer",
1128                 .ldap_oid               = LDB_SYNTAX_INTEGER,
1129                 .oMSyntax               = 2,
1130                 .attributeSyntax_oid    = "2.5.5.9",
1131                 .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
1132                 .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
1133                 .equality               = "integerMatch",
1134                 .comment                = "Integer",
1135         },{
1136                 .name                   = "String(Octet)",
1137                 .ldap_oid               = LDB_SYNTAX_OCTET_STRING,
1138                 .oMSyntax               = 4,
1139                 .attributeSyntax_oid    = "2.5.5.10",
1140                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1141                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1142                 .equality               = "octetStringMatch",
1143                 .comment                = "Octet String",
1144         },{
1145                 .name                   = "String(Sid)",
1146                 .ldap_oid               = LDB_SYNTAX_OCTET_STRING,
1147                 .oMSyntax               = 4,
1148                 .attributeSyntax_oid    = "2.5.5.17",
1149                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1150                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1151                 .equality               = "octetStringMatch",
1152                 .comment                = "Octet String - Security Identifier (SID)",
1153                 .ldb_syntax             = LDB_SYNTAX_SAMBA_SID
1154         },{
1155                 .name                   = "String(Object-Identifier)",
1156                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.38",
1157                 .oMSyntax               = 6,
1158                 .attributeSyntax_oid    = "2.5.5.2",
1159                 .drsuapi_to_ldb         = dsdb_syntax_OID_drsuapi_to_ldb,
1160                 .ldb_to_drsuapi         = dsdb_syntax_OID_ldb_to_drsuapi,
1161                 .equality               = "caseIgnoreMatch", /* Would use "objectIdentifierMatch" but most are ldap attribute/class names */
1162                 .comment                = "OID String",
1163                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING
1164         },{
1165                 .name                   = "Enumeration",
1166                 .ldap_oid               = LDB_SYNTAX_INTEGER,
1167                 .oMSyntax               = 10,
1168                 .attributeSyntax_oid    = "2.5.5.9",
1169                 .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
1170                 .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
1171         },{
1172         /* not used in w2k3 forest */
1173                 .name                   = "String(Numeric)",
1174                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.36",
1175                 .oMSyntax               = 18,
1176                 .attributeSyntax_oid    = "2.5.5.6",
1177                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1178                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1179                 .equality               = "numericStringMatch",
1180                 .substring              = "numericStringSubstringsMatch",
1181                 .comment                = "Numeric String" 
1182         },{
1183                 .name                   = "String(Printable)",
1184                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.44",
1185                 .oMSyntax               = 19,
1186                 .attributeSyntax_oid    = "2.5.5.5",
1187                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1188                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1189         },{
1190                 .name                   = "String(Teletex)",
1191                 .ldap_oid               = "1.2.840.113556.1.4.905",
1192                 .oMSyntax               = 20,
1193                 .attributeSyntax_oid    = "2.5.5.4",
1194                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1195                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1196                 .equality               = "caseIgnoreMatch",
1197                 .substring              = "caseIgnoreSubstringsMatch",
1198                 .comment                = "Case Insensitive String",
1199                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1200         },{
1201                 .name                   = "String(IA5)",
1202                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.26",
1203                 .oMSyntax               = 22,
1204                 .attributeSyntax_oid    = "2.5.5.5",
1205                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1206                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1207                 .equality               = "caseExactIA5Match",
1208                 .comment                = "Printable String"
1209         },{
1210                 .name                   = "String(UTC-Time)",
1211                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.53",
1212                 .oMSyntax               = 23,
1213                 .attributeSyntax_oid    = "2.5.5.11",
1214                 .drsuapi_to_ldb         = dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb,
1215                 .ldb_to_drsuapi         = dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi,
1216                 .equality               = "generalizedTimeMatch",
1217                 .comment                = "UTC Time",
1218         },{
1219                 .name                   = "String(Generalized-Time)",
1220                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.24",
1221                 .oMSyntax               = 24,
1222                 .attributeSyntax_oid    = "2.5.5.11",
1223                 .drsuapi_to_ldb         = dsdb_syntax_NTTIME_drsuapi_to_ldb,
1224                 .ldb_to_drsuapi         = dsdb_syntax_NTTIME_ldb_to_drsuapi,
1225                 .equality               = "generalizedTimeMatch",
1226                 .comment                = "Generalized Time",
1227                 .ldb_syntax             = LDB_SYNTAX_UTC_TIME,
1228         },{
1229         /* not used in w2k3 schema */
1230                 .name                   = "String(Case Sensitive)",
1231                 .ldap_oid               = "1.2.840.113556.1.4.1362",
1232                 .oMSyntax               = 27,
1233                 .attributeSyntax_oid    = "2.5.5.3",
1234                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1235                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1236         },{
1237                 .name                   = "String(Unicode)",
1238                 .ldap_oid               = LDB_SYNTAX_DIRECTORY_STRING,
1239                 .oMSyntax               = 64,
1240                 .attributeSyntax_oid    = "2.5.5.12",
1241                 .drsuapi_to_ldb         = dsdb_syntax_UNICODE_drsuapi_to_ldb,
1242                 .ldb_to_drsuapi         = dsdb_syntax_UNICODE_ldb_to_drsuapi,
1243                 .equality               = "caseIgnoreMatch",
1244                 .substring              = "caseIgnoreSubstringsMatch",
1245                 .comment                = "Directory String",
1246         },{
1247                 .name                   = "Interval/LargeInteger",
1248                 .ldap_oid               = "1.2.840.113556.1.4.906",
1249                 .oMSyntax               = 65,
1250                 .attributeSyntax_oid    = "2.5.5.16",
1251                 .drsuapi_to_ldb         = dsdb_syntax_INT64_drsuapi_to_ldb,
1252                 .ldb_to_drsuapi         = dsdb_syntax_INT64_ldb_to_drsuapi,
1253                 .equality               = "integerMatch",
1254                 .comment                = "Large Integer",
1255                 .ldb_syntax             = LDB_SYNTAX_INTEGER,
1256         },{
1257                 .name                   = "String(NT-Sec-Desc)",
1258                 .ldap_oid               = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1259                 .oMSyntax               = 66,
1260                 .attributeSyntax_oid    = "2.5.5.15",
1261                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1262                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1263         },{
1264                 .name                   = "Object(DS-DN)",
1265                 .ldap_oid               = LDB_SYNTAX_DN,
1266                 .oMSyntax               = 127,
1267                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x4a"),
1268                 .attributeSyntax_oid    = "2.5.5.1",
1269                 .drsuapi_to_ldb         = dsdb_syntax_DN_drsuapi_to_ldb,
1270                 .ldb_to_drsuapi         = dsdb_syntax_DN_ldb_to_drsuapi,
1271                 .equality               = "distinguishedNameMatch",
1272                 .comment                = "Object(DS-DN) == a DN",
1273         },{
1274                 .name                   = "Object(DN-Binary)",
1275                 .ldap_oid               = "1.2.840.113556.1.4.903",
1276                 .oMSyntax               = 127,
1277                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0b"),
1278                 .attributeSyntax_oid    = "2.5.5.7",
1279                 .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
1280                 .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
1281                 .equality               = "octetStringMatch",
1282                 .comment                = "OctetString: Binary+DN",
1283                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
1284         },{
1285         /* not used in w2k3 schema */
1286                 .name                   = "Object(OR-Name)",
1287                 .ldap_oid               = "1.2.840.113556.1.4.1221",
1288                 .oMSyntax               = 127,
1289                 .oMObjectClass          = OMOBJECTCLASS("\x56\x06\x01\x02\x05\x0b\x1D"),
1290                 .attributeSyntax_oid    = "2.5.5.7",
1291                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1292                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1293         },{
1294         /* 
1295          * TODO: verify if DATA_BLOB is correct here...!
1296          *
1297          *       repsFrom and repsTo are the only attributes using
1298          *       this attribute syntax, but they're not replicated... 
1299          */
1300                 .name                   = "Object(Replica-Link)",
1301                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.40",
1302                 .oMSyntax               = 127,
1303                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x06"),
1304                 .attributeSyntax_oid    = "2.5.5.10",
1305                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1306                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1307         },{
1308                 .name                   = "Object(Presentation-Address)",
1309                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.43",
1310                 .oMSyntax               = 127,
1311                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x5c"),
1312                 .attributeSyntax_oid    = "2.5.5.13",
1313                 .drsuapi_to_ldb         = dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb,
1314                 .ldb_to_drsuapi         = dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi,
1315                 .comment                = "Presentation Address" 
1316         },{
1317         /* not used in w2k3 schema */
1318                 .name                   = "Object(Access-Point)",
1319                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.2",
1320                 .oMSyntax               = 127,
1321                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x3e"),
1322                 .attributeSyntax_oid    = "2.5.5.14",
1323                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1324                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1325         },{
1326         /* not used in w2k3 schema */
1327                 .name                   = "Object(DN-String)",
1328                 .ldap_oid               = "1.2.840.113556.1.4.904",
1329                 .oMSyntax               = 127,
1330                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0c"),
1331                 .attributeSyntax_oid    = "2.5.5.14",
1332                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1333                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1334                 .equality               = "distinguishedNameMatch",
1335                 .comment                = "OctetString: String+DN",
1336                 .ldb_syntax             = LDB_SYNTAX_DN,
1337         }
1338 };
1339
1340 const struct dsdb_syntax *find_syntax_map_by_ad_oid(const char *ad_oid) 
1341 {
1342         int i;
1343         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1344                 if (strcasecmp(ad_oid, dsdb_syntaxes[i].attributeSyntax_oid) == 0) {
1345                         return &dsdb_syntaxes[i];
1346                 }
1347         }
1348         return NULL;
1349 }
1350
1351 const struct dsdb_syntax *find_syntax_map_by_ad_syntax(int oMSyntax) 
1352 {
1353         int i;
1354         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1355                 if (oMSyntax == dsdb_syntaxes[i].oMSyntax) {
1356                         return &dsdb_syntaxes[i];
1357                 }
1358         }
1359         return NULL;
1360 }
1361
1362 const struct dsdb_syntax *find_syntax_map_by_standard_oid(const char *standard_oid) 
1363 {
1364         int i;
1365         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1366                 if (strcasecmp(standard_oid, dsdb_syntaxes[i].ldap_oid) == 0) {
1367                         return &dsdb_syntaxes[i];
1368                 }
1369         }
1370         return NULL;
1371 }
1372 const struct dsdb_syntax *dsdb_syntax_for_attribute(const struct dsdb_attribute *attr)
1373 {
1374         uint32_t i;
1375
1376         for (i=0; i < ARRAY_SIZE(dsdb_syntaxes); i++) {
1377                 if (attr->oMSyntax != dsdb_syntaxes[i].oMSyntax) continue;
1378
1379                 if (attr->oMObjectClass.length != dsdb_syntaxes[i].oMObjectClass.length) continue;
1380
1381                 if (attr->oMObjectClass.length) {
1382                         int ret;
1383                         ret = memcmp(attr->oMObjectClass.data,
1384                                      dsdb_syntaxes[i].oMObjectClass.data,
1385                                      attr->oMObjectClass.length);
1386                         if (ret != 0) continue;
1387                 }
1388
1389                 if (strcmp(attr->attributeSyntax_oid, dsdb_syntaxes[i].attributeSyntax_oid) != 0) continue;
1390
1391                 return &dsdb_syntaxes[i];
1392         }
1393
1394         return NULL;
1395 }
1396
1397 WERROR dsdb_attribute_drsuapi_to_ldb(const struct dsdb_schema *schema,
1398                                      const struct drsuapi_DsReplicaAttribute *in,
1399                                      TALLOC_CTX *mem_ctx,
1400                                      struct ldb_message_element *out)
1401 {
1402         const struct dsdb_attribute *sa;
1403
1404         sa = dsdb_attribute_by_attributeID_id(schema, in->attid);
1405         if (!sa) {
1406                 return WERR_FOOBAR;
1407         }
1408
1409         return sa->syntax->drsuapi_to_ldb(schema, sa, in, mem_ctx, out);
1410 }
1411
1412 WERROR dsdb_attribute_ldb_to_drsuapi(const struct dsdb_schema *schema,
1413                                      const struct ldb_message_element *in,
1414                                      TALLOC_CTX *mem_ctx,
1415                                      struct drsuapi_DsReplicaAttribute *out)
1416 {
1417         const struct dsdb_attribute *sa;
1418
1419         sa = dsdb_attribute_by_lDAPDisplayName(schema, in->name);
1420         if (!sa) {
1421                 return WERR_FOOBAR;
1422         }
1423
1424         return sa->syntax->ldb_to_drsuapi(schema, sa, in, mem_ctx, out);
1425 }