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