sd-schema: order DRS classes on the wire in reverse order
[mat/samba.git] / source4 / dsdb / schema / schema_syntax.c
1 /* 
2    Unix SMB/CIFS mplementation.
3    DSDB schema syntaxes
4    
5    Copyright (C) Stefan Metzmacher <metze@samba.org> 2006
6    Copyright (C) Simo Sorce 2005
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21    
22 */
23 #include "includes.h"
24 #include "dsdb/samdb/samdb.h"
25 #include "librpc/gen_ndr/ndr_drsuapi.h"
26 #include "librpc/gen_ndr/ndr_security.h"
27 #include "librpc/gen_ndr/ndr_misc.h"
28 #include "lib/ldb/include/ldb.h"
29 #include "lib/ldb/include/ldb_errors.h"
30 #include "system/time.h"
31 #include "../lib/util/charset/charset.h"
32 #include "librpc/ndr/libndr.h"
33
34 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                 /* We've to use "strtoll" here to have the intended overflows.
238                  * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
239                 v = (int32_t) strtoll((char *)in->values[i].data, NULL, 0);
240
241                 SIVALS(blobs[i].data, 0, v);
242         }
243
244         return WERR_OK;
245 }
246
247 static WERROR dsdb_syntax_INT64_drsuapi_to_ldb(struct ldb_context *ldb, 
248                                                const struct dsdb_schema *schema,
249                                                const struct dsdb_attribute *attr,
250                                                const struct drsuapi_DsReplicaAttribute *in,
251                                                TALLOC_CTX *mem_ctx,
252                                                struct ldb_message_element *out)
253 {
254         uint32_t i;
255
256         out->flags      = 0;
257         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
258         W_ERROR_HAVE_NO_MEMORY(out->name);
259
260         out->num_values = in->value_ctr.num_values;
261         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
262         W_ERROR_HAVE_NO_MEMORY(out->values);
263
264         for (i=0; i < out->num_values; i++) {
265                 int64_t v;
266                 char *str;
267
268                 if (in->value_ctr.values[i].blob == NULL) {
269                         return WERR_FOOBAR;
270                 }
271
272                 if (in->value_ctr.values[i].blob->length != 8) {
273                         return WERR_FOOBAR;
274                 }
275
276                 v = BVALS(in->value_ctr.values[i].blob->data, 0);
277
278                 str = talloc_asprintf(out->values, "%lld", (long long int)v);
279                 W_ERROR_HAVE_NO_MEMORY(str);
280
281                 out->values[i] = data_blob_string_const(str);
282         }
283
284         return WERR_OK;
285 }
286
287 static WERROR dsdb_syntax_INT64_ldb_to_drsuapi(struct ldb_context *ldb, 
288                                                const struct dsdb_schema *schema,
289                                                const struct dsdb_attribute *attr,
290                                                const struct ldb_message_element *in,
291                                                TALLOC_CTX *mem_ctx,
292                                                struct drsuapi_DsReplicaAttribute *out)
293 {
294         uint32_t i;
295         DATA_BLOB *blobs;
296
297         if (attr->attributeID_id == 0xFFFFFFFF) {
298                 return WERR_FOOBAR;
299         }
300
301         out->attid                      = attr->attributeID_id;
302         out->value_ctr.num_values       = in->num_values;
303         out->value_ctr.values           = talloc_array(mem_ctx,
304                                                        struct drsuapi_DsAttributeValue,
305                                                        in->num_values);
306         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
307
308         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
309         W_ERROR_HAVE_NO_MEMORY(blobs);
310
311         for (i=0; i < in->num_values; i++) {
312                 int64_t v;
313
314                 out->value_ctr.values[i].blob   = &blobs[i];
315
316                 blobs[i] = data_blob_talloc(blobs, NULL, 8);
317                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
318
319                 v = strtoll((const char *)in->values[i].data, NULL, 10);
320
321                 SBVALS(blobs[i].data, 0, v);
322         }
323
324         return WERR_OK;
325 }
326
327 static WERROR dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb(struct ldb_context *ldb, 
328                                                     const struct dsdb_schema *schema,
329                                                     const struct dsdb_attribute *attr,
330                                                     const struct drsuapi_DsReplicaAttribute *in,
331                                                     TALLOC_CTX *mem_ctx,
332                                                     struct ldb_message_element *out)
333 {
334         uint32_t i;
335
336         out->flags      = 0;
337         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
338         W_ERROR_HAVE_NO_MEMORY(out->name);
339
340         out->num_values = in->value_ctr.num_values;
341         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
342         W_ERROR_HAVE_NO_MEMORY(out->values);
343
344         for (i=0; i < out->num_values; i++) {
345                 NTTIME v;
346                 time_t t;
347                 char *str;
348
349                 if (in->value_ctr.values[i].blob == NULL) {
350                         return WERR_FOOBAR;
351                 }
352
353                 if (in->value_ctr.values[i].blob->length != 8) {
354                         return WERR_FOOBAR;
355                 }
356
357                 v = BVAL(in->value_ctr.values[i].blob->data, 0);
358                 v *= 10000000;
359                 t = nt_time_to_unix(v);
360
361                 /* 
362                  * NOTE: On a w2k3 server you can set a GeneralizedTime string
363                  *       via LDAP, but you get back an UTCTime string,
364                  *       but via DRSUAPI you get back the NTTIME_1sec value
365                  *       that represents the GeneralizedTime value!
366                  *
367                  *       So if we store the UTCTime string in our ldb
368                  *       we'll loose information!
369                  */
370                 str = ldb_timestring_utc(out->values, t); 
371                 W_ERROR_HAVE_NO_MEMORY(str);
372                 out->values[i] = data_blob_string_const(str);
373         }
374
375         return WERR_OK;
376 }
377
378 static WERROR dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi(struct ldb_context *ldb, 
379                                                     const struct dsdb_schema *schema,
380                                                     const struct dsdb_attribute *attr,
381                                                     const struct ldb_message_element *in,
382                                                     TALLOC_CTX *mem_ctx,
383                                                     struct drsuapi_DsReplicaAttribute *out)
384 {
385         uint32_t i;
386         DATA_BLOB *blobs;
387
388         if (attr->attributeID_id == 0xFFFFFFFF) {
389                 return WERR_FOOBAR;
390         }
391
392         out->attid                      = attr->attributeID_id;
393         out->value_ctr.num_values       = in->num_values;
394         out->value_ctr.values           = talloc_array(mem_ctx,
395                                                        struct drsuapi_DsAttributeValue,
396                                                        in->num_values);
397         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
398
399         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
400         W_ERROR_HAVE_NO_MEMORY(blobs);
401
402         for (i=0; i < in->num_values; i++) {
403                 NTTIME v;
404                 time_t t;
405
406                 out->value_ctr.values[i].blob   = &blobs[i];
407
408                 blobs[i] = data_blob_talloc(blobs, NULL, 8);
409                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
410
411                 t = ldb_string_utc_to_time((const char *)in->values[i].data);
412                 unix_to_nt_time(&v, t);
413                 v /= 10000000;
414
415                 SBVAL(blobs[i].data, 0, v);
416         }
417
418         return WERR_OK;
419 }
420
421 static WERROR dsdb_syntax_NTTIME_drsuapi_to_ldb(struct ldb_context *ldb, 
422                                                 const struct dsdb_schema *schema,
423                                                 const struct dsdb_attribute *attr,
424                                                 const struct drsuapi_DsReplicaAttribute *in,
425                                                 TALLOC_CTX *mem_ctx,
426                                                 struct ldb_message_element *out)
427 {
428         uint32_t i;
429
430         out->flags      = 0;
431         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
432         W_ERROR_HAVE_NO_MEMORY(out->name);
433
434         out->num_values = in->value_ctr.num_values;
435         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
436         W_ERROR_HAVE_NO_MEMORY(out->values);
437
438         for (i=0; i < out->num_values; i++) {
439                 NTTIME v;
440                 time_t t;
441                 char *str;
442
443                 if (in->value_ctr.values[i].blob == NULL) {
444                         return WERR_FOOBAR;
445                 }
446
447                 if (in->value_ctr.values[i].blob->length != 8) {
448                         return WERR_FOOBAR;
449                 }
450
451                 v = BVAL(in->value_ctr.values[i].blob->data, 0);
452                 v *= 10000000;
453                 t = nt_time_to_unix(v);
454
455                 str = ldb_timestring(out->values, t); 
456                 W_ERROR_HAVE_NO_MEMORY(str);
457
458                 out->values[i] = data_blob_string_const(str);
459         }
460
461         return WERR_OK;
462 }
463
464 static WERROR dsdb_syntax_NTTIME_ldb_to_drsuapi(struct ldb_context *ldb, 
465                                                 const struct dsdb_schema *schema,
466                                                 const struct dsdb_attribute *attr,
467                                                 const struct ldb_message_element *in,
468                                                 TALLOC_CTX *mem_ctx,
469                                                 struct drsuapi_DsReplicaAttribute *out)
470 {
471         uint32_t i;
472         DATA_BLOB *blobs;
473
474         if (attr->attributeID_id == 0xFFFFFFFF) {
475                 return WERR_FOOBAR;
476         }
477
478         out->attid                      = attr->attributeID_id;
479         out->value_ctr.num_values       = in->num_values;
480         out->value_ctr.values           = talloc_array(mem_ctx,
481                                                        struct drsuapi_DsAttributeValue,
482                                                        in->num_values);
483         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
484
485         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
486         W_ERROR_HAVE_NO_MEMORY(blobs);
487
488         for (i=0; i < in->num_values; i++) {
489                 NTTIME v;
490                 time_t t;
491
492                 out->value_ctr.values[i].blob   = &blobs[i];
493
494                 blobs[i] = data_blob_talloc(blobs, NULL, 8);
495                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
496
497                 t = ldb_string_to_time((const char *)in->values[i].data);
498                 unix_to_nt_time(&v, t);
499                 v /= 10000000;
500
501                 SBVAL(blobs[i].data, 0, v);
502         }
503
504         return WERR_OK;
505 }
506
507 static WERROR dsdb_syntax_DATA_BLOB_drsuapi_to_ldb(struct ldb_context *ldb, 
508                                                    const struct dsdb_schema *schema,
509                                                    const struct dsdb_attribute *attr,
510                                                    const struct drsuapi_DsReplicaAttribute *in,
511                                                    TALLOC_CTX *mem_ctx,
512                                                    struct ldb_message_element *out)
513 {
514         uint32_t i;
515
516         out->flags      = 0;
517         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
518         W_ERROR_HAVE_NO_MEMORY(out->name);
519
520         out->num_values = in->value_ctr.num_values;
521         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
522         W_ERROR_HAVE_NO_MEMORY(out->values);
523
524         for (i=0; i < out->num_values; i++) {
525                 if (in->value_ctr.values[i].blob == NULL) {
526                         return WERR_FOOBAR;
527                 }
528
529                 if (in->value_ctr.values[i].blob->length == 0) {
530                         return WERR_FOOBAR;
531                 }
532
533                 out->values[i] = data_blob_dup_talloc(out->values,
534                                                       in->value_ctr.values[i].blob);
535                 W_ERROR_HAVE_NO_MEMORY(out->values[i].data);
536         }
537
538         return WERR_OK;
539 }
540
541 static WERROR dsdb_syntax_DATA_BLOB_ldb_to_drsuapi(struct ldb_context *ldb, 
542                                                    const struct dsdb_schema *schema,
543                                                    const struct dsdb_attribute *attr,
544                                                    const struct ldb_message_element *in,
545                                                    TALLOC_CTX *mem_ctx,
546                                                    struct drsuapi_DsReplicaAttribute *out)
547 {
548         uint32_t i;
549         DATA_BLOB *blobs;
550
551         if (attr->attributeID_id == 0xFFFFFFFF) {
552                 return WERR_FOOBAR;
553         }
554
555         out->attid                      = attr->attributeID_id;
556         out->value_ctr.num_values       = in->num_values;
557         out->value_ctr.values           = talloc_array(mem_ctx,
558                                                        struct drsuapi_DsAttributeValue,
559                                                        in->num_values);
560         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
561
562         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
563         W_ERROR_HAVE_NO_MEMORY(blobs);
564
565         for (i=0; i < in->num_values; i++) {
566                 out->value_ctr.values[i].blob   = &blobs[i];
567
568                 blobs[i] = data_blob_dup_talloc(blobs, &in->values[i]);
569                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
570         }
571
572         return WERR_OK;
573 }
574
575 static WERROR _dsdb_syntax_OID_obj_drsuapi_to_ldb(struct ldb_context *ldb, 
576                                                   const struct dsdb_schema *schema,
577                                                   const struct dsdb_attribute *attr,
578                                                   const struct drsuapi_DsReplicaAttribute *in,
579                                                   TALLOC_CTX *mem_ctx,
580                                                   struct ldb_message_element *out)
581 {
582         uint32_t i;
583
584         out->flags      = 0;
585         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
586         W_ERROR_HAVE_NO_MEMORY(out->name);
587
588         out->num_values = in->value_ctr.num_values;
589         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
590         W_ERROR_HAVE_NO_MEMORY(out->values);
591
592         for (i=0; i < out->num_values; i++) {
593                 uint32_t v;
594                 const struct dsdb_class *c;
595                 const char *str;
596
597                 if (in->value_ctr.values[i].blob == NULL) {
598                         return WERR_FOOBAR;
599                 }
600
601                 if (in->value_ctr.values[i].blob->length != 4) {
602                         return WERR_FOOBAR;
603                 }
604
605                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
606
607                 c = dsdb_class_by_governsID_id(schema, v);
608                 if (!c) {
609                         return WERR_FOOBAR;
610                 }
611
612                 str = talloc_strdup(out->values, c->lDAPDisplayName);
613                 W_ERROR_HAVE_NO_MEMORY(str);
614
615                 /* the values need to be reversed */
616                 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
617         }
618
619         return WERR_OK;
620 }
621
622 static WERROR _dsdb_syntax_OID_attr_drsuapi_to_ldb(struct ldb_context *ldb, 
623                                                    const struct dsdb_schema *schema,
624                                                    const struct dsdb_attribute *attr,
625                                                    const struct drsuapi_DsReplicaAttribute *in,
626                                                    TALLOC_CTX *mem_ctx,
627                                                    struct ldb_message_element *out)
628 {
629         uint32_t i;
630
631         out->flags      = 0;
632         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
633         W_ERROR_HAVE_NO_MEMORY(out->name);
634
635         out->num_values = in->value_ctr.num_values;
636         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
637         W_ERROR_HAVE_NO_MEMORY(out->values);
638
639         for (i=0; i < out->num_values; i++) {
640                 uint32_t v;
641                 const struct dsdb_attribute *a;
642                 const char *str;
643
644                 if (in->value_ctr.values[i].blob == NULL) {
645                         return WERR_FOOBAR;
646                 }
647
648                 if (in->value_ctr.values[i].blob->length != 4) {
649                         return WERR_FOOBAR;
650                 }
651
652                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
653
654                 a = dsdb_attribute_by_attributeID_id(schema, v);
655                 if (!a) {
656                         return WERR_FOOBAR;
657                 }
658
659                 str = talloc_strdup(out->values, a->lDAPDisplayName);
660                 W_ERROR_HAVE_NO_MEMORY(str);
661
662                 /* the values need to be reversed */
663                 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
664         }
665
666         return WERR_OK;
667 }
668
669 static WERROR _dsdb_syntax_OID_oid_drsuapi_to_ldb(struct ldb_context *ldb, 
670                                                   const struct dsdb_schema *schema,
671                                                   const struct dsdb_attribute *attr,
672                                                   const struct drsuapi_DsReplicaAttribute *in,
673                                                   TALLOC_CTX *mem_ctx,
674                                                   struct ldb_message_element *out)
675 {
676         uint32_t i;
677
678         out->flags      = 0;
679         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
680         W_ERROR_HAVE_NO_MEMORY(out->name);
681
682         out->num_values = in->value_ctr.num_values;
683         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
684         W_ERROR_HAVE_NO_MEMORY(out->values);
685
686         for (i=0; i < out->num_values; i++) {
687                 uint32_t attid;
688                 WERROR status;
689                 const char *oid;
690
691                 if (in->value_ctr.values[i].blob == NULL) {
692                         return WERR_FOOBAR;
693                 }
694
695                 if (in->value_ctr.values[i].blob->length != 4) {
696                         return WERR_FOOBAR;
697                 }
698
699                 attid = IVAL(in->value_ctr.values[i].blob->data, 0);
700
701                 status = dsdb_schema_pfm_oid_from_attid(schema->prefixmap, attid, out->values, &oid);
702                 W_ERROR_NOT_OK_RETURN(status);
703
704                 out->values[i] = data_blob_string_const(oid);
705         }
706
707         return WERR_OK;
708 }
709
710 static WERROR _dsdb_syntax_OID_obj_ldb_to_drsuapi(struct ldb_context *ldb,
711                                                   const struct dsdb_schema *schema,
712                                                   const struct dsdb_attribute *attr,
713                                                   const struct ldb_message_element *in,
714                                                   TALLOC_CTX *mem_ctx,
715                                                   struct drsuapi_DsReplicaAttribute *out)
716 {
717         uint32_t i;
718         DATA_BLOB *blobs;
719
720         out->attid= attr->attributeID_id;
721         out->value_ctr.num_values= in->num_values;
722         out->value_ctr.values= talloc_array(mem_ctx,
723                                             struct drsuapi_DsAttributeValue,
724                                             in->num_values);
725         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
726
727         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
728         W_ERROR_HAVE_NO_MEMORY(blobs);
729
730         for (i=0; i < in->num_values; i++) {
731                 const struct dsdb_class *obj_class;
732
733                 out->value_ctr.values[i].blob= &blobs[i];
734
735                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
736                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
737
738                 /* in DRS windows puts the classes in the opposite
739                    order to the order used in ldap */
740                 obj_class = dsdb_class_by_lDAPDisplayName(schema,
741                                                           (const char *)in->values[(in->num_values-1)-i].data);
742                 if (!obj_class) {
743                         return WERR_FOOBAR;
744                 }
745                 SIVAL(blobs[i].data, 0, obj_class->governsID_id);
746         }
747
748
749         return WERR_OK;
750 }
751
752 static WERROR _dsdb_syntax_OID_attr_ldb_to_drsuapi(struct ldb_context *ldb,
753                                                    const struct dsdb_schema *schema,
754                                                    const struct dsdb_attribute *attr,
755                                                    const struct ldb_message_element *in,
756                                                    TALLOC_CTX *mem_ctx,
757                                                    struct drsuapi_DsReplicaAttribute *out)
758 {
759         uint32_t i;
760         DATA_BLOB *blobs;
761
762         out->attid= attr->attributeID_id;
763         out->value_ctr.num_values= in->num_values;
764         out->value_ctr.values= talloc_array(mem_ctx,
765                                             struct drsuapi_DsAttributeValue,
766                                             in->num_values);
767         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
768
769         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
770         W_ERROR_HAVE_NO_MEMORY(blobs);
771
772         for (i=0; i < in->num_values; i++) {
773                 const struct dsdb_attribute *obj_attr;
774
775                 out->value_ctr.values[i].blob= &blobs[i];
776
777                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
778                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
779
780                 obj_attr = dsdb_attribute_by_lDAPDisplayName(schema, (const char *)in->values[i].data);
781                 if (!obj_attr) {
782                         return WERR_FOOBAR;
783                 }
784                 SIVAL(blobs[i].data, 0, obj_attr->attributeID_id);
785         }
786
787
788         return WERR_OK;
789 }
790
791 static WERROR _dsdb_syntax_OID_oid_ldb_to_drsuapi(struct ldb_context *ldb,
792                                                   const struct dsdb_schema *schema,
793                                                   const struct dsdb_attribute *attr,
794                                                   const struct ldb_message_element *in,
795                                                   TALLOC_CTX *mem_ctx,
796                                                   struct drsuapi_DsReplicaAttribute *out)
797 {
798         uint32_t i;
799         DATA_BLOB *blobs;
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                 uint32_t attid;
813                 WERROR status;
814
815                 out->value_ctr.values[i].blob= &blobs[i];
816
817                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
818                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
819
820                 status = dsdb_schema_pfm_make_attid(schema->prefixmap,
821                                                     (const char *)in->values[i].data,
822                                                     &attid);
823                 W_ERROR_NOT_OK_RETURN(status);
824
825                 SIVAL(blobs[i].data, 0, attid);
826         }
827
828         return WERR_OK;
829 }
830
831 static WERROR dsdb_syntax_OID_drsuapi_to_ldb(struct ldb_context *ldb, 
832                                              const struct dsdb_schema *schema,
833                                              const struct dsdb_attribute *attr,
834                                              const struct drsuapi_DsReplicaAttribute *in,
835                                              TALLOC_CTX *mem_ctx,
836                                              struct ldb_message_element *out)
837 {
838         uint32_t i;
839
840         switch (attr->attributeID_id) {
841         case DRSUAPI_ATTRIBUTE_objectClass:
842         case DRSUAPI_ATTRIBUTE_subClassOf:
843         case DRSUAPI_ATTRIBUTE_auxiliaryClass:
844         case DRSUAPI_ATTRIBUTE_systemPossSuperiors:
845         case DRSUAPI_ATTRIBUTE_possSuperiors:
846                 return _dsdb_syntax_OID_obj_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
847         case DRSUAPI_ATTRIBUTE_systemMustContain:
848         case DRSUAPI_ATTRIBUTE_systemMayContain:        
849         case DRSUAPI_ATTRIBUTE_mustContain:
850         case DRSUAPI_ATTRIBUTE_mayContain:
851                 return _dsdb_syntax_OID_attr_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
852         case DRSUAPI_ATTRIBUTE_governsID:
853         case DRSUAPI_ATTRIBUTE_attributeID:
854         case DRSUAPI_ATTRIBUTE_attributeSyntax:
855                 return _dsdb_syntax_OID_oid_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
856         }
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                 uint32_t v;
868                 const char *name;
869                 char *str;
870
871                 if (in->value_ctr.values[i].blob == NULL) {
872                         return WERR_FOOBAR;
873                 }
874
875                 if (in->value_ctr.values[i].blob->length != 4) {
876                         return WERR_FOOBAR;
877                 }
878
879                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
880
881                 name = dsdb_lDAPDisplayName_by_id(schema, v);
882                 if (!name) {
883                         return WERR_FOOBAR;
884                 }
885
886                 str = talloc_strdup(out->values, name);
887                 W_ERROR_HAVE_NO_MEMORY(str);
888
889                 out->values[i] = data_blob_string_const(str);
890         }
891
892         return WERR_OK;
893 }
894
895 static WERROR dsdb_syntax_OID_ldb_to_drsuapi(struct ldb_context *ldb, 
896                                              const struct dsdb_schema *schema,
897                                              const struct dsdb_attribute *attr,
898                                              const struct ldb_message_element *in,
899                                              TALLOC_CTX *mem_ctx,
900                                              struct drsuapi_DsReplicaAttribute *out)
901 {
902         uint32_t i;
903         DATA_BLOB *blobs;
904
905         if (attr->attributeID_id == 0xFFFFFFFF) {
906                 return WERR_FOOBAR;
907         }
908
909         switch (attr->attributeID_id) {
910         case DRSUAPI_ATTRIBUTE_objectClass:
911         case DRSUAPI_ATTRIBUTE_subClassOf:
912         case DRSUAPI_ATTRIBUTE_auxiliaryClass:
913         case DRSUAPI_ATTRIBUTE_systemPossSuperiors:
914         case DRSUAPI_ATTRIBUTE_possSuperiors:
915                 return _dsdb_syntax_OID_obj_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
916         case DRSUAPI_ATTRIBUTE_systemMustContain:
917         case DRSUAPI_ATTRIBUTE_systemMayContain:        
918         case DRSUAPI_ATTRIBUTE_mustContain:
919         case DRSUAPI_ATTRIBUTE_mayContain:
920                 return _dsdb_syntax_OID_attr_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
921         case DRSUAPI_ATTRIBUTE_governsID:
922         case DRSUAPI_ATTRIBUTE_attributeID:
923         case DRSUAPI_ATTRIBUTE_attributeSyntax:
924                 return _dsdb_syntax_OID_oid_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
925         }
926
927         out->attid                      = attr->attributeID_id;
928         out->value_ctr.num_values       = in->num_values;
929         out->value_ctr.values           = talloc_array(mem_ctx,
930                                                        struct drsuapi_DsAttributeValue,
931                                                        in->num_values);
932         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
933
934         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
935         W_ERROR_HAVE_NO_MEMORY(blobs);
936
937         for (i=0; i < in->num_values; i++) {
938                 uint32_t v;
939
940                 out->value_ctr.values[i].blob   = &blobs[i];
941
942                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
943                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
944
945                 v = strtol((const char *)in->values[i].data, NULL, 10);
946
947                 SIVAL(blobs[i].data, 0, v);
948         }
949
950         return WERR_OK;
951 }
952
953 static WERROR dsdb_syntax_UNICODE_drsuapi_to_ldb(struct ldb_context *ldb, 
954                                                  const struct dsdb_schema *schema,
955                                                  const struct dsdb_attribute *attr,
956                                                  const struct drsuapi_DsReplicaAttribute *in,
957                                                  TALLOC_CTX *mem_ctx,
958                                                  struct ldb_message_element *out)
959 {
960         uint32_t i;
961
962         out->flags      = 0;
963         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
964         W_ERROR_HAVE_NO_MEMORY(out->name);
965
966         out->num_values = in->value_ctr.num_values;
967         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
968         W_ERROR_HAVE_NO_MEMORY(out->values);
969
970         for (i=0; i < out->num_values; i++) {
971                 char *str;
972
973                 if (in->value_ctr.values[i].blob == NULL) {
974                         return WERR_FOOBAR;
975                 }
976
977                 if (in->value_ctr.values[i].blob->length == 0) {
978                         return WERR_FOOBAR;
979                 }
980
981                 if (!convert_string_talloc_convenience(out->values, 
982                                                 schema->iconv_convenience, 
983                                                                         CH_UTF16, CH_UNIX,
984                                             in->value_ctr.values[i].blob->data,
985                                             in->value_ctr.values[i].blob->length,
986                                             (void **)&str, NULL, false)) {
987                         return WERR_FOOBAR;
988                 }
989
990                 out->values[i] = data_blob_string_const(str);
991         }
992
993         return WERR_OK;
994 }
995
996 static WERROR dsdb_syntax_UNICODE_ldb_to_drsuapi(struct ldb_context *ldb, 
997                                                  const struct dsdb_schema *schema,
998                                                  const struct dsdb_attribute *attr,
999                                                  const struct ldb_message_element *in,
1000                                                  TALLOC_CTX *mem_ctx,
1001                                                  struct drsuapi_DsReplicaAttribute *out)
1002 {
1003         uint32_t i;
1004         DATA_BLOB *blobs;
1005
1006         if (attr->attributeID_id == 0xFFFFFFFF) {
1007                 return WERR_FOOBAR;
1008         }
1009
1010         out->attid                      = attr->attributeID_id;
1011         out->value_ctr.num_values       = in->num_values;
1012         out->value_ctr.values           = talloc_array(mem_ctx,
1013                                                        struct drsuapi_DsAttributeValue,
1014                                                        in->num_values);
1015         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1016
1017         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1018         W_ERROR_HAVE_NO_MEMORY(blobs);
1019
1020         for (i=0; i < in->num_values; i++) {
1021                 out->value_ctr.values[i].blob   = &blobs[i];
1022
1023                 if (!convert_string_talloc_convenience(blobs,
1024                         schema->iconv_convenience, CH_UNIX, CH_UTF16,
1025                         in->values[i].data, in->values[i].length,
1026                         (void **)&blobs[i].data, &blobs[i].length, false)) {
1027                                 return WERR_FOOBAR;
1028                 }
1029         }
1030
1031         return WERR_OK;
1032 }
1033
1034
1035 WERROR dsdb_syntax_one_DN_drsuapi_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, 
1036                                          const struct dsdb_syntax *syntax, 
1037                                          struct smb_iconv_convenience *iconv_convenience,
1038                                          const DATA_BLOB *in, DATA_BLOB *out)
1039 {
1040         struct drsuapi_DsReplicaObjectIdentifier3 id3;
1041         enum ndr_err_code ndr_err;
1042         DATA_BLOB guid_blob;
1043         struct ldb_dn *dn;
1044         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1045         int ret;
1046         NTSTATUS status;
1047
1048         if (!tmp_ctx) {
1049                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1050         }
1051         
1052         if (in == NULL) {
1053                 talloc_free(tmp_ctx);
1054                 return WERR_FOOBAR;
1055         }
1056         
1057         if (in->length == 0) {
1058                 talloc_free(tmp_ctx);
1059                 return WERR_FOOBAR;
1060         }
1061         
1062         
1063         /* windows sometimes sends an extra two pad bytes here */
1064         ndr_err = ndr_pull_struct_blob(in,
1065                                        tmp_ctx, iconv_convenience, &id3,
1066                                        (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3);
1067         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1068                 status = ndr_map_error2ntstatus(ndr_err);
1069                 talloc_free(tmp_ctx);
1070                 return ntstatus_to_werror(status);
1071         }
1072         
1073         dn = ldb_dn_new(tmp_ctx, ldb, id3.dn);
1074         if (!dn) {
1075                 talloc_free(tmp_ctx);
1076                 /* If this fails, it must be out of memory, as it does not do much parsing */
1077                 W_ERROR_HAVE_NO_MEMORY(dn);
1078         }
1079
1080         status = GUID_to_ndr_blob(&id3.guid, tmp_ctx, &guid_blob);
1081         if (!NT_STATUS_IS_OK(status)) {
1082                 talloc_free(tmp_ctx);
1083                 return ntstatus_to_werror(status);
1084         }
1085         
1086         ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
1087         if (ret != LDB_SUCCESS) {
1088                 talloc_free(tmp_ctx);
1089                 return WERR_FOOBAR;
1090         }
1091         
1092         talloc_free(guid_blob.data);
1093         
1094         if (id3.__ndr_size_sid) {
1095                 DATA_BLOB sid_blob;
1096                 ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, iconv_convenience, &id3.sid,
1097                                                (ndr_push_flags_fn_t)ndr_push_dom_sid);
1098                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1099                         status = ndr_map_error2ntstatus(ndr_err);
1100                         talloc_free(tmp_ctx);
1101                         return ntstatus_to_werror(status);
1102                 }
1103                 
1104                 ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
1105                 if (ret != LDB_SUCCESS) {
1106                         talloc_free(tmp_ctx);
1107                         return WERR_FOOBAR;
1108                 }
1109         }
1110         
1111         *out = data_blob_string_const(ldb_dn_get_extended_linearized(mem_ctx, dn, 1));
1112         talloc_free(tmp_ctx);
1113         return WERR_OK;
1114 }
1115
1116 static WERROR dsdb_syntax_DN_drsuapi_to_ldb(struct ldb_context *ldb, 
1117                                             const struct dsdb_schema *schema,
1118                                             const struct dsdb_attribute *attr,
1119                                             const struct drsuapi_DsReplicaAttribute *in,
1120                                             TALLOC_CTX *mem_ctx,
1121                                             struct ldb_message_element *out)
1122 {
1123         uint32_t i;
1124
1125         out->flags      = 0;
1126         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1127         W_ERROR_HAVE_NO_MEMORY(out->name);
1128
1129         out->num_values = in->value_ctr.num_values;
1130         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1131         W_ERROR_HAVE_NO_MEMORY(out->values);
1132
1133         for (i=0; i < out->num_values; i++) {
1134                 WERROR status = dsdb_syntax_one_DN_drsuapi_to_ldb(out->values, ldb, attr->syntax, 
1135                                                                   schema->iconv_convenience, 
1136                                                                   in->value_ctr.values[i].blob, 
1137                                                                   &out->values[i]);
1138                 if (!W_ERROR_IS_OK(status)) {
1139                         return status;
1140                 }
1141                                                   
1142         }
1143
1144         return WERR_OK;
1145 }
1146
1147 static WERROR dsdb_syntax_DN_ldb_to_drsuapi(struct ldb_context *ldb, 
1148                                             const struct dsdb_schema *schema,
1149                                             const struct dsdb_attribute *attr,
1150                                             const struct ldb_message_element *in,
1151                                             TALLOC_CTX *mem_ctx,
1152                                             struct drsuapi_DsReplicaAttribute *out)
1153 {
1154         uint32_t i;
1155         DATA_BLOB *blobs;
1156
1157         if (attr->attributeID_id == 0xFFFFFFFF) {
1158                 return WERR_FOOBAR;
1159         }
1160
1161         out->attid                      = attr->attributeID_id;
1162         out->value_ctr.num_values       = in->num_values;
1163         out->value_ctr.values           = talloc_array(mem_ctx,
1164                                                        struct drsuapi_DsAttributeValue,
1165                                                        in->num_values);
1166         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1167
1168         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1169         W_ERROR_HAVE_NO_MEMORY(blobs);
1170
1171         for (i=0; i < in->num_values; i++) {
1172                 struct drsuapi_DsReplicaObjectIdentifier3 id3;
1173                 enum ndr_err_code ndr_err;
1174                 const DATA_BLOB *sid_blob;
1175                 struct ldb_dn *dn;
1176                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1177                 NTSTATUS status;
1178
1179                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1180
1181                 out->value_ctr.values[i].blob   = &blobs[i];
1182
1183                 dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &in->values[i]);
1184
1185                 W_ERROR_HAVE_NO_MEMORY(dn);
1186
1187                 ZERO_STRUCT(id3);
1188
1189                 status = dsdb_get_extended_dn_guid(dn, &id3.guid, "GUID");
1190                 if (!NT_STATUS_IS_OK(status) &&
1191                     !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1192                         talloc_free(tmp_ctx);
1193                         return ntstatus_to_werror(status);
1194                 }
1195
1196                 sid_blob = ldb_dn_get_extended_component(dn, "SID");
1197                 if (sid_blob) {
1198                         
1199                         ndr_err = ndr_pull_struct_blob_all(sid_blob, 
1200                                                            tmp_ctx, schema->iconv_convenience, &id3.sid,
1201                                                            (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1202                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1203                                 status = ndr_map_error2ntstatus(ndr_err);
1204                                 talloc_free(tmp_ctx);
1205                                 return ntstatus_to_werror(status);
1206                         }
1207                 }
1208
1209                 id3.dn = ldb_dn_get_linearized(dn);
1210
1211                 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
1212                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1213                         status = ndr_map_error2ntstatus(ndr_err);
1214                         talloc_free(tmp_ctx);
1215                         return ntstatus_to_werror(status);
1216                 }
1217                 talloc_free(tmp_ctx);
1218         }
1219
1220         return WERR_OK;
1221 }
1222
1223
1224
1225 static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(struct ldb_context *ldb, 
1226                                                    const struct dsdb_schema *schema,
1227                                                    const struct dsdb_attribute *attr,
1228                                                    const struct drsuapi_DsReplicaAttribute *in,
1229                                                    TALLOC_CTX *mem_ctx,
1230                                                    struct ldb_message_element *out)
1231 {
1232         uint32_t i;
1233         int ret;
1234
1235         out->flags      = 0;
1236         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1237         W_ERROR_HAVE_NO_MEMORY(out->name);
1238
1239         out->num_values = in->value_ctr.num_values;
1240         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1241         W_ERROR_HAVE_NO_MEMORY(out->values);
1242
1243         for (i=0; i < out->num_values; i++) {
1244                 struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
1245                 enum ndr_err_code ndr_err;
1246                 DATA_BLOB guid_blob;
1247                 struct ldb_dn *dn;
1248                 struct dsdb_dn *dsdb_dn;
1249                 NTSTATUS status;
1250                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1251                 if (!tmp_ctx) {
1252                         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1253                 }
1254
1255                 if (in->value_ctr.values[i].blob == NULL) {
1256                         talloc_free(tmp_ctx);
1257                         return WERR_FOOBAR;
1258                 }
1259
1260                 if (in->value_ctr.values[i].blob->length == 0) {
1261                         talloc_free(tmp_ctx);
1262                         return WERR_FOOBAR;
1263                 }
1264
1265                 
1266                 /* windows sometimes sends an extra two pad bytes here */
1267                 ndr_err = ndr_pull_struct_blob(in->value_ctr.values[i].blob,
1268                                                tmp_ctx, schema->iconv_convenience, &id3,
1269                                                (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3Binary);
1270                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1271                         status = ndr_map_error2ntstatus(ndr_err);
1272                         talloc_free(tmp_ctx);
1273                         return ntstatus_to_werror(status);
1274                 }
1275
1276                 dn = ldb_dn_new(tmp_ctx, ldb, id3.dn);
1277                 if (!dn) {
1278                         talloc_free(tmp_ctx);
1279                         /* If this fails, it must be out of memory, as it does not do much parsing */
1280                         W_ERROR_HAVE_NO_MEMORY(dn);
1281                 }
1282
1283                 status = GUID_to_ndr_blob(&id3.guid, tmp_ctx, &guid_blob);
1284                 if (!NT_STATUS_IS_OK(status)) {
1285                         talloc_free(tmp_ctx);
1286                         return ntstatus_to_werror(status);
1287                 }
1288
1289                 ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
1290                 if (ret != LDB_SUCCESS) {
1291                         talloc_free(tmp_ctx);
1292                         return WERR_FOOBAR;
1293                 }
1294
1295                 talloc_free(guid_blob.data);
1296
1297                 if (id3.__ndr_size_sid) {
1298                         DATA_BLOB sid_blob;
1299                         ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, schema->iconv_convenience, &id3.sid,
1300                                                        (ndr_push_flags_fn_t)ndr_push_dom_sid);
1301                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1302                                 status = ndr_map_error2ntstatus(ndr_err);
1303                                 talloc_free(tmp_ctx);
1304                                 return ntstatus_to_werror(status);
1305                         }
1306
1307                         ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
1308                         if (ret != LDB_SUCCESS) {
1309                                 talloc_free(tmp_ctx);
1310                                 return WERR_FOOBAR;
1311                         }
1312                 }
1313
1314                 /* set binary stuff */
1315                 dsdb_dn = dsdb_dn_construct(tmp_ctx, dn, id3.binary, attr->syntax->ldap_oid);
1316                 if (!dsdb_dn) {
1317                         /* If this fails, it must be out of memory, we know the ldap_oid is valid */
1318                         talloc_free(tmp_ctx);
1319                         W_ERROR_HAVE_NO_MEMORY(dsdb_dn);
1320                 }
1321                 out->values[i] = data_blob_string_const(dsdb_dn_get_extended_linearized(out->values, dsdb_dn, 1));
1322                 talloc_free(tmp_ctx);
1323         }
1324
1325         return WERR_OK;
1326 }
1327
1328 static WERROR dsdb_syntax_DN_BINARY_ldb_to_drsuapi(struct ldb_context *ldb, 
1329                                                    const struct dsdb_schema *schema,
1330                                                    const struct dsdb_attribute *attr,
1331                                                    const struct ldb_message_element *in,
1332                                                    TALLOC_CTX *mem_ctx,
1333                                                    struct drsuapi_DsReplicaAttribute *out)
1334 {
1335         uint32_t i;
1336         DATA_BLOB *blobs;
1337
1338         if (attr->attributeID_id == 0xFFFFFFFF) {
1339                 return WERR_FOOBAR;
1340         }
1341
1342         out->attid                      = attr->attributeID_id;
1343         out->value_ctr.num_values       = in->num_values;
1344         out->value_ctr.values           = talloc_array(mem_ctx,
1345                                                        struct drsuapi_DsAttributeValue,
1346                                                        in->num_values);
1347         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1348
1349         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1350         W_ERROR_HAVE_NO_MEMORY(blobs);
1351
1352         for (i=0; i < in->num_values; i++) {
1353                 struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
1354                 enum ndr_err_code ndr_err;
1355                 const DATA_BLOB *sid_blob;
1356                 struct dsdb_dn *dsdb_dn;
1357                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1358                 NTSTATUS status;
1359
1360                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1361
1362                 out->value_ctr.values[i].blob   = &blobs[i];
1363
1364                 dsdb_dn = dsdb_dn_parse(tmp_ctx, ldb, &in->values[i], attr->syntax->ldap_oid);
1365
1366                 if (!dsdb_dn) {
1367                         talloc_free(tmp_ctx);
1368                         return ntstatus_to_werror(NT_STATUS_INVALID_PARAMETER);
1369                 }
1370
1371                 ZERO_STRUCT(id3);
1372
1373                 status = dsdb_get_extended_dn_guid(dsdb_dn->dn, &id3.guid, "GUID");
1374                 if (!NT_STATUS_IS_OK(status) &&
1375                     !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1376                         talloc_free(tmp_ctx);
1377                         return ntstatus_to_werror(status);
1378                 }
1379
1380                 sid_blob = ldb_dn_get_extended_component(dsdb_dn->dn, "SID");
1381                 if (sid_blob) {
1382                         
1383                         ndr_err = ndr_pull_struct_blob_all(sid_blob, 
1384                                                            tmp_ctx, schema->iconv_convenience, &id3.sid,
1385                                                            (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1386                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1387                                 status = ndr_map_error2ntstatus(ndr_err);
1388                                 talloc_free(tmp_ctx);
1389                                 return ntstatus_to_werror(status);
1390                         }
1391                 }
1392
1393                 id3.dn = ldb_dn_get_linearized(dsdb_dn->dn);
1394
1395                 /* get binary stuff */
1396                 id3.binary = dsdb_dn->extra_part;
1397
1398                 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3Binary);
1399                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1400                         status = ndr_map_error2ntstatus(ndr_err);
1401                         talloc_free(tmp_ctx);
1402                         return ntstatus_to_werror(status);
1403                 }
1404                 talloc_free(tmp_ctx);
1405         }
1406
1407         return WERR_OK;
1408 }
1409
1410
1411
1412 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb(struct ldb_context *ldb, 
1413                                                               const struct dsdb_schema *schema,
1414                                                               const struct dsdb_attribute *attr,
1415                                                               const struct drsuapi_DsReplicaAttribute *in,
1416                                                               TALLOC_CTX *mem_ctx,
1417                                                               struct ldb_message_element *out)
1418 {
1419         uint32_t i;
1420
1421         out->flags      = 0;
1422         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1423         W_ERROR_HAVE_NO_MEMORY(out->name);
1424
1425         out->num_values = in->value_ctr.num_values;
1426         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1427         W_ERROR_HAVE_NO_MEMORY(out->values);
1428
1429         for (i=0; i < out->num_values; i++) {
1430                 uint32_t len;
1431                 char *str;
1432
1433                 if (in->value_ctr.values[i].blob == NULL) {
1434                         return WERR_FOOBAR;
1435                 }
1436
1437                 if (in->value_ctr.values[i].blob->length < 4) {
1438                         return WERR_FOOBAR;
1439                 }
1440
1441                 len = IVAL(in->value_ctr.values[i].blob->data, 0);
1442
1443                 if (len != in->value_ctr.values[i].blob->length) {
1444                         return WERR_FOOBAR;
1445                 }
1446
1447                 if (!convert_string_talloc_convenience(out->values, schema->iconv_convenience, CH_UTF16, CH_UNIX,
1448                                             in->value_ctr.values[i].blob->data+4,
1449                                             in->value_ctr.values[i].blob->length-4,
1450                                             (void **)&str, NULL, false)) {
1451                         return WERR_FOOBAR;
1452                 }
1453
1454                 out->values[i] = data_blob_string_const(str);
1455         }
1456
1457         return WERR_OK;
1458 }
1459
1460 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi(struct ldb_context *ldb, 
1461                                                               const struct dsdb_schema *schema,
1462                                                               const struct dsdb_attribute *attr,
1463                                                               const struct ldb_message_element *in,
1464                                                               TALLOC_CTX *mem_ctx,
1465                                                               struct drsuapi_DsReplicaAttribute *out)
1466 {
1467         uint32_t i;
1468         DATA_BLOB *blobs;
1469
1470         if (attr->attributeID_id == 0xFFFFFFFF) {
1471                 return WERR_FOOBAR;
1472         }
1473
1474         out->attid                      = attr->attributeID_id;
1475         out->value_ctr.num_values       = in->num_values;
1476         out->value_ctr.values           = talloc_array(mem_ctx,
1477                                                        struct drsuapi_DsAttributeValue,
1478                                                        in->num_values);
1479         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1480
1481         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1482         W_ERROR_HAVE_NO_MEMORY(blobs);
1483
1484         for (i=0; i < in->num_values; i++) {
1485                 uint8_t *data;
1486                 size_t ret;
1487
1488                 out->value_ctr.values[i].blob   = &blobs[i];
1489
1490                 if (!convert_string_talloc_convenience(blobs, schema->iconv_convenience, CH_UNIX, CH_UTF16,
1491                                             in->values[i].data,
1492                                             in->values[i].length,
1493                                             (void **)&data, &ret, false)) {
1494                         return WERR_FOOBAR;
1495                 }
1496
1497                 blobs[i] = data_blob_talloc(blobs, NULL, 4 + ret);
1498                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1499
1500                 SIVAL(blobs[i].data, 0, 4 + ret);
1501
1502                 if (ret > 0) {
1503                         memcpy(blobs[i].data + 4, data, ret);
1504                         talloc_free(data);
1505                 }
1506         }
1507
1508         return WERR_OK;
1509 }
1510
1511 #define OMOBJECTCLASS(val) { .length = sizeof(val) - 1, .data = discard_const_p(uint8_t, val) }
1512
1513 static const struct dsdb_syntax dsdb_syntaxes[] = {
1514         {
1515                 .name                   = "Boolean",
1516                 .ldap_oid               = LDB_SYNTAX_BOOLEAN,
1517                 .oMSyntax               = 1,
1518                 .attributeSyntax_oid    = "2.5.5.8",
1519                 .drsuapi_to_ldb         = dsdb_syntax_BOOL_drsuapi_to_ldb,
1520                 .ldb_to_drsuapi         = dsdb_syntax_BOOL_ldb_to_drsuapi,
1521                 .equality               = "booleanMatch",
1522                 .comment                = "Boolean" 
1523         },{
1524                 .name                   = "Integer",
1525                 .ldap_oid               = LDB_SYNTAX_INTEGER,
1526                 .oMSyntax               = 2,
1527                 .attributeSyntax_oid    = "2.5.5.9",
1528                 .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
1529                 .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
1530                 .equality               = "integerMatch",
1531                 .comment                = "Integer",
1532                 .ldb_syntax             = LDB_SYNTAX_SAMBA_INT32
1533         },{
1534                 .name                   = "String(Octet)",
1535                 .ldap_oid               = LDB_SYNTAX_OCTET_STRING,
1536                 .oMSyntax               = 4,
1537                 .attributeSyntax_oid    = "2.5.5.10",
1538                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1539                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1540                 .equality               = "octetStringMatch",
1541                 .comment                = "Octet String",
1542         },{
1543                 .name                   = "String(Sid)",
1544                 .ldap_oid               = LDB_SYNTAX_OCTET_STRING,
1545                 .oMSyntax               = 4,
1546                 .attributeSyntax_oid    = "2.5.5.17",
1547                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1548                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1549                 .equality               = "octetStringMatch",
1550                 .comment                = "Octet String - Security Identifier (SID)",
1551                 .ldb_syntax             = LDB_SYNTAX_SAMBA_SID
1552         },{
1553                 .name                   = "String(Object-Identifier)",
1554                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.38",
1555                 .oMSyntax               = 6,
1556                 .attributeSyntax_oid    = "2.5.5.2",
1557                 .drsuapi_to_ldb         = dsdb_syntax_OID_drsuapi_to_ldb,
1558                 .ldb_to_drsuapi         = dsdb_syntax_OID_ldb_to_drsuapi,
1559                 .equality               = "caseIgnoreMatch", /* Would use "objectIdentifierMatch" but most are ldap attribute/class names */
1560                 .comment                = "OID String",
1561                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING
1562         },{
1563                 .name                   = "Enumeration",
1564                 .ldap_oid               = LDB_SYNTAX_INTEGER,
1565                 .oMSyntax               = 10,
1566                 .attributeSyntax_oid    = "2.5.5.9",
1567                 .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
1568                 .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
1569                 .ldb_syntax             = LDB_SYNTAX_SAMBA_INT32
1570         },{
1571         /* not used in w2k3 forest */
1572                 .name                   = "String(Numeric)",
1573                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.36",
1574                 .oMSyntax               = 18,
1575                 .attributeSyntax_oid    = "2.5.5.6",
1576                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1577                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1578                 .equality               = "numericStringMatch",
1579                 .substring              = "numericStringSubstringsMatch",
1580                 .comment                = "Numeric String",
1581                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1582         },{
1583                 .name                   = "String(Printable)",
1584                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.44",
1585                 .oMSyntax               = 19,
1586                 .attributeSyntax_oid    = "2.5.5.5",
1587                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1588                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1589                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
1590         },{
1591                 .name                   = "String(Teletex)",
1592                 .ldap_oid               = "1.2.840.113556.1.4.905",
1593                 .oMSyntax               = 20,
1594                 .attributeSyntax_oid    = "2.5.5.4",
1595                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1596                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1597                 .equality               = "caseIgnoreMatch",
1598                 .substring              = "caseIgnoreSubstringsMatch",
1599                 .comment                = "Case Insensitive String",
1600                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1601         },{
1602                 .name                   = "String(IA5)",
1603                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.26",
1604                 .oMSyntax               = 22,
1605                 .attributeSyntax_oid    = "2.5.5.5",
1606                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1607                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1608                 .equality               = "caseExactIA5Match",
1609                 .comment                = "Printable String",
1610                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
1611         },{
1612                 .name                   = "String(UTC-Time)",
1613                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.53",
1614                 .oMSyntax               = 23,
1615                 .attributeSyntax_oid    = "2.5.5.11",
1616                 .drsuapi_to_ldb         = dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb,
1617                 .ldb_to_drsuapi         = dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi,
1618                 .equality               = "generalizedTimeMatch",
1619                 .comment                = "UTC Time",
1620         },{
1621                 .name                   = "String(Generalized-Time)",
1622                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.24",
1623                 .oMSyntax               = 24,
1624                 .attributeSyntax_oid    = "2.5.5.11",
1625                 .drsuapi_to_ldb         = dsdb_syntax_NTTIME_drsuapi_to_ldb,
1626                 .ldb_to_drsuapi         = dsdb_syntax_NTTIME_ldb_to_drsuapi,
1627                 .equality               = "generalizedTimeMatch",
1628                 .comment                = "Generalized Time",
1629                 .ldb_syntax             = LDB_SYNTAX_UTC_TIME,
1630         },{
1631         /* not used in w2k3 schema */
1632                 .name                   = "String(Case Sensitive)",
1633                 .ldap_oid               = "1.2.840.113556.1.4.1362",
1634                 .oMSyntax               = 27,
1635                 .attributeSyntax_oid    = "2.5.5.3",
1636                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1637                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1638         },{
1639                 .name                   = "String(Unicode)",
1640                 .ldap_oid               = LDB_SYNTAX_DIRECTORY_STRING,
1641                 .oMSyntax               = 64,
1642                 .attributeSyntax_oid    = "2.5.5.12",
1643                 .drsuapi_to_ldb         = dsdb_syntax_UNICODE_drsuapi_to_ldb,
1644                 .ldb_to_drsuapi         = dsdb_syntax_UNICODE_ldb_to_drsuapi,
1645                 .equality               = "caseIgnoreMatch",
1646                 .substring              = "caseIgnoreSubstringsMatch",
1647                 .comment                = "Directory String",
1648         },{
1649                 .name                   = "Interval/LargeInteger",
1650                 .ldap_oid               = "1.2.840.113556.1.4.906",
1651                 .oMSyntax               = 65,
1652                 .attributeSyntax_oid    = "2.5.5.16",
1653                 .drsuapi_to_ldb         = dsdb_syntax_INT64_drsuapi_to_ldb,
1654                 .ldb_to_drsuapi         = dsdb_syntax_INT64_ldb_to_drsuapi,
1655                 .equality               = "integerMatch",
1656                 .comment                = "Large Integer",
1657                 .ldb_syntax             = LDB_SYNTAX_INTEGER,
1658         },{
1659                 .name                   = "String(NT-Sec-Desc)",
1660                 .ldap_oid               = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1661                 .oMSyntax               = 66,
1662                 .attributeSyntax_oid    = "2.5.5.15",
1663                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1664                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1665         },{
1666                 .name                   = "Object(DS-DN)",
1667                 .ldap_oid               = LDB_SYNTAX_DN,
1668                 .oMSyntax               = 127,
1669                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x4a"),
1670                 .attributeSyntax_oid    = "2.5.5.1",
1671                 .drsuapi_to_ldb         = dsdb_syntax_DN_drsuapi_to_ldb,
1672                 .ldb_to_drsuapi         = dsdb_syntax_DN_ldb_to_drsuapi,
1673                 .equality               = "distinguishedNameMatch",
1674                 .comment                = "Object(DS-DN) == a DN",
1675         },{
1676                 .name                   = "Object(DN-Binary)",
1677                 .ldap_oid               = DSDB_SYNTAX_BINARY_DN,
1678                 .oMSyntax               = 127,
1679                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0b"),
1680                 .attributeSyntax_oid    = "2.5.5.7",
1681                 .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
1682                 .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
1683                 .equality               = "octetStringMatch",
1684                 .comment                = "OctetString: Binary+DN",
1685         },{
1686         /* not used in w2k3 schema, but used in Exchange schema*/
1687                 .name                   = "Object(OR-Name)",
1688                 .ldap_oid               = DSDB_SYNTAX_OR_NAME,
1689                 .oMSyntax               = 127,
1690                 .oMObjectClass          = OMOBJECTCLASS("\x56\x06\x01\x02\x05\x0b\x1D"),
1691                 .attributeSyntax_oid    = "2.5.5.7",
1692                 .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
1693                 .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
1694                 .equality               = "caseIgnoreMatch",
1695                 .ldb_syntax             = LDB_SYNTAX_DN,
1696         },{
1697         /* 
1698          * TODO: verify if DATA_BLOB is correct here...!
1699          *
1700          *       repsFrom and repsTo are the only attributes using
1701          *       this attribute syntax, but they're not replicated... 
1702          */
1703                 .name                   = "Object(Replica-Link)",
1704                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.40",
1705                 .oMSyntax               = 127,
1706                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x06"),
1707                 .attributeSyntax_oid    = "2.5.5.10",
1708                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1709                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1710         },{
1711                 .name                   = "Object(Presentation-Address)",
1712                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.43",
1713                 .oMSyntax               = 127,
1714                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x5c"),
1715                 .attributeSyntax_oid    = "2.5.5.13",
1716                 .drsuapi_to_ldb         = dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb,
1717                 .ldb_to_drsuapi         = dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi,
1718                 .comment                = "Presentation Address",
1719                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1720         },{
1721         /* not used in w2k3 schema */
1722                 .name                   = "Object(Access-Point)",
1723                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.2",
1724                 .oMSyntax               = 127,
1725                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x3e"),
1726                 .attributeSyntax_oid    = "2.5.5.14",
1727                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1728                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1729                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1730         },{
1731         /* not used in w2k3 schema */
1732                 .name                   = "Object(DN-String)",
1733                 .ldap_oid               = DSDB_SYNTAX_STRING_DN,
1734                 .oMSyntax               = 127,
1735                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0c"),
1736                 .attributeSyntax_oid    = "2.5.5.14",
1737                 .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
1738                 .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
1739                 .equality               = "octetStringMatch",
1740                 .comment                = "OctetString: String+DN",
1741         }
1742 };
1743
1744 const struct dsdb_syntax *find_syntax_map_by_ad_oid(const char *ad_oid) 
1745 {
1746         int i;
1747         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1748                 if (strcasecmp(ad_oid, dsdb_syntaxes[i].attributeSyntax_oid) == 0) {
1749                         return &dsdb_syntaxes[i];
1750                 }
1751         }
1752         return NULL;
1753 }
1754
1755 const struct dsdb_syntax *find_syntax_map_by_ad_syntax(int oMSyntax) 
1756 {
1757         int i;
1758         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1759                 if (oMSyntax == dsdb_syntaxes[i].oMSyntax) {
1760                         return &dsdb_syntaxes[i];
1761                 }
1762         }
1763         return NULL;
1764 }
1765
1766 const struct dsdb_syntax *find_syntax_map_by_standard_oid(const char *standard_oid) 
1767 {
1768         int i;
1769         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1770                 if (strcasecmp(standard_oid, dsdb_syntaxes[i].ldap_oid) == 0) {
1771                         return &dsdb_syntaxes[i];
1772                 }
1773         }
1774         return NULL;
1775 }
1776 const struct dsdb_syntax *dsdb_syntax_for_attribute(const struct dsdb_attribute *attr)
1777 {
1778         uint32_t i;
1779
1780         for (i=0; i < ARRAY_SIZE(dsdb_syntaxes); i++) {
1781                 if (attr->oMSyntax != dsdb_syntaxes[i].oMSyntax) continue;
1782
1783                 if (attr->oMObjectClass.length != dsdb_syntaxes[i].oMObjectClass.length) continue;
1784
1785                 if (attr->oMObjectClass.length) {
1786                         int ret;
1787                         ret = memcmp(attr->oMObjectClass.data,
1788                                      dsdb_syntaxes[i].oMObjectClass.data,
1789                                      attr->oMObjectClass.length);
1790                         if (ret != 0) continue;
1791                 }
1792
1793                 if (strcmp(attr->attributeSyntax_oid, dsdb_syntaxes[i].attributeSyntax_oid) != 0) continue;
1794
1795                 return &dsdb_syntaxes[i];
1796         }
1797
1798         return NULL;
1799 }
1800
1801 WERROR dsdb_attribute_drsuapi_to_ldb(struct ldb_context *ldb, 
1802                                      const struct dsdb_schema *schema,
1803                                      const struct drsuapi_DsReplicaAttribute *in,
1804                                      TALLOC_CTX *mem_ctx,
1805                                      struct ldb_message_element *out)
1806 {
1807         const struct dsdb_attribute *sa;
1808
1809         sa = dsdb_attribute_by_attributeID_id(schema, in->attid);
1810         if (!sa) {
1811                 return WERR_FOOBAR;
1812         }
1813
1814         return sa->syntax->drsuapi_to_ldb(ldb, schema, sa, in, mem_ctx, out);
1815 }
1816
1817 WERROR dsdb_attribute_ldb_to_drsuapi(struct ldb_context *ldb, 
1818                                      const struct dsdb_schema *schema,
1819                                      const struct ldb_message_element *in,
1820                                      TALLOC_CTX *mem_ctx,
1821                                      struct drsuapi_DsReplicaAttribute *out)
1822 {
1823         const struct dsdb_attribute *sa;
1824
1825         sa = dsdb_attribute_by_lDAPDisplayName(schema, in->name);
1826         if (!sa) {
1827                 return WERR_FOOBAR;
1828         }
1829
1830         return sa->syntax->ldb_to_drsuapi(ldb, schema, sa, in, mem_ctx, out);
1831 }