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