s4/schema: Object(OR-Name) syntax handling for DRS calls
[metze/samba/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                 /* 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                 obj_class = dsdb_class_by_lDAPDisplayName(schema, (const char *)in->values[i].data);
739                 if (!obj_class) {
740                         return WERR_FOOBAR;
741                 }
742                 SIVAL(blobs[i].data, 0, obj_class->governsID_id);
743         }
744
745
746         return WERR_OK;
747 }
748
749 static WERROR _dsdb_syntax_OID_attr_ldb_to_drsuapi(struct ldb_context *ldb,
750                                                    const struct dsdb_schema *schema,
751                                                    const struct dsdb_attribute *attr,
752                                                    const struct ldb_message_element *in,
753                                                    TALLOC_CTX *mem_ctx,
754                                                    struct drsuapi_DsReplicaAttribute *out)
755 {
756         uint32_t i;
757         DATA_BLOB *blobs;
758
759         out->attid= attr->attributeID_id;
760         out->value_ctr.num_values= in->num_values;
761         out->value_ctr.values= talloc_array(mem_ctx,
762                                             struct drsuapi_DsAttributeValue,
763                                             in->num_values);
764         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
765
766         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
767         W_ERROR_HAVE_NO_MEMORY(blobs);
768
769         for (i=0; i < in->num_values; i++) {
770                 const struct dsdb_attribute *obj_attr;
771
772                 out->value_ctr.values[i].blob= &blobs[i];
773
774                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
775                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
776
777                 obj_attr = dsdb_attribute_by_lDAPDisplayName(schema, (const char *)in->values[i].data);
778                 if (!obj_attr) {
779                         return WERR_FOOBAR;
780                 }
781                 SIVAL(blobs[i].data, 0, obj_attr->attributeID_id);
782         }
783
784
785         return WERR_OK;
786 }
787
788 static WERROR _dsdb_syntax_OID_oid_ldb_to_drsuapi(struct ldb_context *ldb,
789                                                   const struct dsdb_schema *schema,
790                                                   const struct dsdb_attribute *attr,
791                                                   const struct ldb_message_element *in,
792                                                   TALLOC_CTX *mem_ctx,
793                                                   struct drsuapi_DsReplicaAttribute *out)
794 {
795         uint32_t i;
796         DATA_BLOB *blobs;
797
798         out->attid= attr->attributeID_id;
799         out->value_ctr.num_values= in->num_values;
800         out->value_ctr.values= talloc_array(mem_ctx,
801                                             struct drsuapi_DsAttributeValue,
802                                             in->num_values);
803         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
804
805         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
806         W_ERROR_HAVE_NO_MEMORY(blobs);
807
808         for (i=0; i < in->num_values; i++) {
809                 uint32_t attid;
810                 WERROR status;
811
812                 out->value_ctr.values[i].blob= &blobs[i];
813
814                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
815                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
816
817                 status = dsdb_schema_pfm_make_attid(schema->prefixmap,
818                                                     (const char *)in->values[i].data,
819                                                     &attid);
820                 W_ERROR_NOT_OK_RETURN(status);
821
822                 SIVAL(blobs[i].data, 0, attid);
823         }
824
825         return WERR_OK;
826 }
827
828 static WERROR dsdb_syntax_OID_drsuapi_to_ldb(struct ldb_context *ldb, 
829                                              const struct dsdb_schema *schema,
830                                              const struct dsdb_attribute *attr,
831                                              const struct drsuapi_DsReplicaAttribute *in,
832                                              TALLOC_CTX *mem_ctx,
833                                              struct ldb_message_element *out)
834 {
835         uint32_t i;
836
837         switch (attr->attributeID_id) {
838         case DRSUAPI_ATTRIBUTE_objectClass:
839         case DRSUAPI_ATTRIBUTE_subClassOf:
840         case DRSUAPI_ATTRIBUTE_auxiliaryClass:
841         case DRSUAPI_ATTRIBUTE_systemPossSuperiors:
842         case DRSUAPI_ATTRIBUTE_possSuperiors:
843                 return _dsdb_syntax_OID_obj_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
844         case DRSUAPI_ATTRIBUTE_systemMustContain:
845         case DRSUAPI_ATTRIBUTE_systemMayContain:        
846         case DRSUAPI_ATTRIBUTE_mustContain:
847         case DRSUAPI_ATTRIBUTE_mayContain:
848                 return _dsdb_syntax_OID_attr_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
849         case DRSUAPI_ATTRIBUTE_governsID:
850         case DRSUAPI_ATTRIBUTE_attributeID:
851         case DRSUAPI_ATTRIBUTE_attributeSyntax:
852                 return _dsdb_syntax_OID_oid_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
853         }
854
855         out->flags      = 0;
856         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
857         W_ERROR_HAVE_NO_MEMORY(out->name);
858
859         out->num_values = in->value_ctr.num_values;
860         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
861         W_ERROR_HAVE_NO_MEMORY(out->values);
862
863         for (i=0; i < out->num_values; i++) {
864                 uint32_t v;
865                 const char *name;
866                 char *str;
867
868                 if (in->value_ctr.values[i].blob == NULL) {
869                         return WERR_FOOBAR;
870                 }
871
872                 if (in->value_ctr.values[i].blob->length != 4) {
873                         return WERR_FOOBAR;
874                 }
875
876                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
877
878                 name = dsdb_lDAPDisplayName_by_id(schema, v);
879                 if (!name) {
880                         return WERR_FOOBAR;
881                 }
882
883                 str = talloc_strdup(out->values, name);
884                 W_ERROR_HAVE_NO_MEMORY(str);
885
886                 out->values[i] = data_blob_string_const(str);
887         }
888
889         return WERR_OK;
890 }
891
892 static WERROR dsdb_syntax_OID_ldb_to_drsuapi(struct ldb_context *ldb, 
893                                              const struct dsdb_schema *schema,
894                                              const struct dsdb_attribute *attr,
895                                              const struct ldb_message_element *in,
896                                              TALLOC_CTX *mem_ctx,
897                                              struct drsuapi_DsReplicaAttribute *out)
898 {
899         uint32_t i;
900         DATA_BLOB *blobs;
901
902         if (attr->attributeID_id == 0xFFFFFFFF) {
903                 return WERR_FOOBAR;
904         }
905
906         switch (attr->attributeID_id) {
907         case DRSUAPI_ATTRIBUTE_objectClass:
908         case DRSUAPI_ATTRIBUTE_subClassOf:
909         case DRSUAPI_ATTRIBUTE_auxiliaryClass:
910         case DRSUAPI_ATTRIBUTE_systemPossSuperiors:
911         case DRSUAPI_ATTRIBUTE_possSuperiors:
912                 return _dsdb_syntax_OID_obj_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
913         case DRSUAPI_ATTRIBUTE_systemMustContain:
914         case DRSUAPI_ATTRIBUTE_systemMayContain:        
915         case DRSUAPI_ATTRIBUTE_mustContain:
916         case DRSUAPI_ATTRIBUTE_mayContain:
917                 return _dsdb_syntax_OID_attr_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
918         case DRSUAPI_ATTRIBUTE_governsID:
919         case DRSUAPI_ATTRIBUTE_attributeID:
920         case DRSUAPI_ATTRIBUTE_attributeSyntax:
921                 return _dsdb_syntax_OID_oid_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
922         }
923
924         out->attid                      = attr->attributeID_id;
925         out->value_ctr.num_values       = in->num_values;
926         out->value_ctr.values           = talloc_array(mem_ctx,
927                                                        struct drsuapi_DsAttributeValue,
928                                                        in->num_values);
929         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
930
931         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
932         W_ERROR_HAVE_NO_MEMORY(blobs);
933
934         for (i=0; i < in->num_values; i++) {
935                 uint32_t v;
936
937                 out->value_ctr.values[i].blob   = &blobs[i];
938
939                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
940                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
941
942                 v = strtol((const char *)in->values[i].data, NULL, 10);
943
944                 SIVAL(blobs[i].data, 0, v);
945         }
946
947         return WERR_OK;
948 }
949
950 static WERROR dsdb_syntax_UNICODE_drsuapi_to_ldb(struct ldb_context *ldb, 
951                                                  const struct dsdb_schema *schema,
952                                                  const struct dsdb_attribute *attr,
953                                                  const struct drsuapi_DsReplicaAttribute *in,
954                                                  TALLOC_CTX *mem_ctx,
955                                                  struct ldb_message_element *out)
956 {
957         uint32_t i;
958
959         out->flags      = 0;
960         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
961         W_ERROR_HAVE_NO_MEMORY(out->name);
962
963         out->num_values = in->value_ctr.num_values;
964         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
965         W_ERROR_HAVE_NO_MEMORY(out->values);
966
967         for (i=0; i < out->num_values; i++) {
968                 char *str;
969
970                 if (in->value_ctr.values[i].blob == NULL) {
971                         return WERR_FOOBAR;
972                 }
973
974                 if (in->value_ctr.values[i].blob->length == 0) {
975                         return WERR_FOOBAR;
976                 }
977
978                 if (!convert_string_talloc_convenience(out->values, 
979                                                 schema->iconv_convenience, 
980                                                                         CH_UTF16, CH_UNIX,
981                                             in->value_ctr.values[i].blob->data,
982                                             in->value_ctr.values[i].blob->length,
983                                             (void **)&str, NULL, false)) {
984                         return WERR_FOOBAR;
985                 }
986
987                 out->values[i] = data_blob_string_const(str);
988         }
989
990         return WERR_OK;
991 }
992
993 static WERROR dsdb_syntax_UNICODE_ldb_to_drsuapi(struct ldb_context *ldb, 
994                                                  const struct dsdb_schema *schema,
995                                                  const struct dsdb_attribute *attr,
996                                                  const struct ldb_message_element *in,
997                                                  TALLOC_CTX *mem_ctx,
998                                                  struct drsuapi_DsReplicaAttribute *out)
999 {
1000         uint32_t i;
1001         DATA_BLOB *blobs;
1002
1003         if (attr->attributeID_id == 0xFFFFFFFF) {
1004                 return WERR_FOOBAR;
1005         }
1006
1007         out->attid                      = attr->attributeID_id;
1008         out->value_ctr.num_values       = in->num_values;
1009         out->value_ctr.values           = talloc_array(mem_ctx,
1010                                                        struct drsuapi_DsAttributeValue,
1011                                                        in->num_values);
1012         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1013
1014         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1015         W_ERROR_HAVE_NO_MEMORY(blobs);
1016
1017         for (i=0; i < in->num_values; i++) {
1018                 out->value_ctr.values[i].blob   = &blobs[i];
1019
1020                 if (!convert_string_talloc_convenience(blobs,
1021                         schema->iconv_convenience, CH_UNIX, CH_UTF16,
1022                         in->values[i].data, in->values[i].length,
1023                         (void **)&blobs[i].data, &blobs[i].length, false)) {
1024                                 return WERR_FOOBAR;
1025                 }
1026         }
1027
1028         return WERR_OK;
1029 }
1030
1031
1032 WERROR dsdb_syntax_one_DN_drsuapi_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, 
1033                                          const struct dsdb_syntax *syntax, 
1034                                          struct smb_iconv_convenience *iconv_convenience,
1035                                          const DATA_BLOB *in, DATA_BLOB *out)
1036 {
1037         struct drsuapi_DsReplicaObjectIdentifier3 id3;
1038         enum ndr_err_code ndr_err;
1039         DATA_BLOB guid_blob;
1040         struct ldb_dn *dn;
1041         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1042         int ret;
1043
1044         if (!tmp_ctx) {
1045                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1046         }
1047         
1048         if (in == NULL) {
1049                 talloc_free(tmp_ctx);
1050                 return WERR_FOOBAR;
1051         }
1052         
1053         if (in->length == 0) {
1054                 talloc_free(tmp_ctx);
1055                 return WERR_FOOBAR;
1056         }
1057         
1058         
1059         /* windows sometimes sends an extra two pad bytes here */
1060         ndr_err = ndr_pull_struct_blob(in,
1061                                        tmp_ctx, iconv_convenience, &id3,
1062                                        (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3);
1063         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1064                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1065                 talloc_free(tmp_ctx);
1066                 return ntstatus_to_werror(status);
1067         }
1068         
1069         dn = ldb_dn_new(tmp_ctx, ldb, id3.dn);
1070         if (!dn) {
1071                 talloc_free(tmp_ctx);
1072                 /* If this fails, it must be out of memory, as it does not do much parsing */
1073                 W_ERROR_HAVE_NO_MEMORY(dn);
1074         }
1075         
1076         ndr_err = ndr_push_struct_blob(&guid_blob, tmp_ctx, iconv_convenience, &id3.guid,
1077                                        (ndr_push_flags_fn_t)ndr_push_GUID);
1078         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1079                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1080                 talloc_free(tmp_ctx);
1081                 return ntstatus_to_werror(status);
1082         }
1083         
1084         ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
1085         if (ret != LDB_SUCCESS) {
1086                 talloc_free(tmp_ctx);
1087                 return WERR_FOOBAR;
1088         }
1089         
1090         talloc_free(guid_blob.data);
1091         
1092         if (id3.__ndr_size_sid) {
1093                 DATA_BLOB sid_blob;
1094                 ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, iconv_convenience, &id3.sid,
1095                                                (ndr_push_flags_fn_t)ndr_push_dom_sid);
1096                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1097                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1098                         talloc_free(tmp_ctx);
1099                         return ntstatus_to_werror(status);
1100                 }
1101                 
1102                 ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
1103                 if (ret != LDB_SUCCESS) {
1104                         talloc_free(tmp_ctx);
1105                         return WERR_FOOBAR;
1106                 }
1107         }
1108         
1109         *out = data_blob_string_const(ldb_dn_get_extended_linearized(mem_ctx, dn, 1));
1110         talloc_free(tmp_ctx);
1111         return WERR_OK;
1112 }
1113
1114 static WERROR dsdb_syntax_DN_drsuapi_to_ldb(struct ldb_context *ldb, 
1115                                             const struct dsdb_schema *schema,
1116                                             const struct dsdb_attribute *attr,
1117                                             const struct drsuapi_DsReplicaAttribute *in,
1118                                             TALLOC_CTX *mem_ctx,
1119                                             struct ldb_message_element *out)
1120 {
1121         uint32_t i;
1122
1123         out->flags      = 0;
1124         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1125         W_ERROR_HAVE_NO_MEMORY(out->name);
1126
1127         out->num_values = in->value_ctr.num_values;
1128         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1129         W_ERROR_HAVE_NO_MEMORY(out->values);
1130
1131         for (i=0; i < out->num_values; i++) {
1132                 WERROR status = dsdb_syntax_one_DN_drsuapi_to_ldb(out->values, ldb, attr->syntax, 
1133                                                                   schema->iconv_convenience, 
1134                                                                   in->value_ctr.values[i].blob, 
1135                                                                   &out->values[i]);
1136                 if (!W_ERROR_IS_OK(status)) {
1137                         return status;
1138                 }
1139                                                   
1140         }
1141
1142         return WERR_OK;
1143 }
1144
1145 static WERROR dsdb_syntax_DN_ldb_to_drsuapi(struct ldb_context *ldb, 
1146                                             const struct dsdb_schema *schema,
1147                                             const struct dsdb_attribute *attr,
1148                                             const struct ldb_message_element *in,
1149                                             TALLOC_CTX *mem_ctx,
1150                                             struct drsuapi_DsReplicaAttribute *out)
1151 {
1152         uint32_t i;
1153         DATA_BLOB *blobs;
1154
1155         if (attr->attributeID_id == 0xFFFFFFFF) {
1156                 return WERR_FOOBAR;
1157         }
1158
1159         out->attid                      = attr->attributeID_id;
1160         out->value_ctr.num_values       = in->num_values;
1161         out->value_ctr.values           = talloc_array(mem_ctx,
1162                                                        struct drsuapi_DsAttributeValue,
1163                                                        in->num_values);
1164         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1165
1166         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1167         W_ERROR_HAVE_NO_MEMORY(blobs);
1168
1169         for (i=0; i < in->num_values; i++) {
1170                 struct drsuapi_DsReplicaObjectIdentifier3 id3;
1171                 enum ndr_err_code ndr_err;
1172                 const DATA_BLOB *guid_blob, *sid_blob;
1173                 struct ldb_dn *dn;
1174                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1175                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1176
1177                 out->value_ctr.values[i].blob   = &blobs[i];
1178
1179                 dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &in->values[i]);
1180
1181                 W_ERROR_HAVE_NO_MEMORY(dn);
1182
1183                 guid_blob = ldb_dn_get_extended_component(dn, "GUID");
1184
1185                 ZERO_STRUCT(id3);
1186
1187                 if (guid_blob) {
1188                         ndr_err = ndr_pull_struct_blob_all(guid_blob, 
1189                                                            tmp_ctx, schema->iconv_convenience, &id3.guid,
1190                                                            (ndr_pull_flags_fn_t)ndr_pull_GUID);
1191                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1192                                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1193                                 talloc_free(tmp_ctx);
1194                                 return ntstatus_to_werror(status);
1195                         }
1196                 }
1197
1198                 sid_blob = ldb_dn_get_extended_component(dn, "SID");
1199                 if (sid_blob) {
1200                         
1201                         ndr_err = ndr_pull_struct_blob_all(sid_blob, 
1202                                                            tmp_ctx, schema->iconv_convenience, &id3.sid,
1203                                                            (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1204                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1205                                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1206                                 talloc_free(tmp_ctx);
1207                                 return ntstatus_to_werror(status);
1208                         }
1209                 }
1210
1211                 id3.dn = ldb_dn_get_linearized(dn);
1212
1213                 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
1214                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1215                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1216                         talloc_free(tmp_ctx);
1217                         return ntstatus_to_werror(status);
1218                 }
1219                 talloc_free(tmp_ctx);
1220         }
1221
1222         return WERR_OK;
1223 }
1224
1225
1226
1227 static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(struct ldb_context *ldb, 
1228                                                    const struct dsdb_schema *schema,
1229                                                    const struct dsdb_attribute *attr,
1230                                                    const struct drsuapi_DsReplicaAttribute *in,
1231                                                    TALLOC_CTX *mem_ctx,
1232                                                    struct ldb_message_element *out)
1233 {
1234         uint32_t i;
1235         int ret;
1236
1237         out->flags      = 0;
1238         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1239         W_ERROR_HAVE_NO_MEMORY(out->name);
1240
1241         out->num_values = in->value_ctr.num_values;
1242         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1243         W_ERROR_HAVE_NO_MEMORY(out->values);
1244
1245         for (i=0; i < out->num_values; i++) {
1246                 struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
1247                 enum ndr_err_code ndr_err;
1248                 DATA_BLOB guid_blob;
1249                 struct ldb_dn *dn;
1250                 struct dsdb_dn *dsdb_dn;
1251                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1252                 if (!tmp_ctx) {
1253                         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1254                 }
1255
1256                 if (in->value_ctr.values[i].blob == NULL) {
1257                         talloc_free(tmp_ctx);
1258                         return WERR_FOOBAR;
1259                 }
1260
1261                 if (in->value_ctr.values[i].blob->length == 0) {
1262                         talloc_free(tmp_ctx);
1263                         return WERR_FOOBAR;
1264                 }
1265
1266                 
1267                 /* windows sometimes sends an extra two pad bytes here */
1268                 ndr_err = ndr_pull_struct_blob(in->value_ctr.values[i].blob,
1269                                                tmp_ctx, schema->iconv_convenience, &id3,
1270                                                (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3Binary);
1271                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1272                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1273                         talloc_free(tmp_ctx);
1274                         return ntstatus_to_werror(status);
1275                 }
1276
1277                 dn = ldb_dn_new(tmp_ctx, ldb, id3.dn);
1278                 if (!dn) {
1279                         talloc_free(tmp_ctx);
1280                         /* If this fails, it must be out of memory, as it does not do much parsing */
1281                         W_ERROR_HAVE_NO_MEMORY(dn);
1282                 }
1283
1284                 ndr_err = ndr_push_struct_blob(&guid_blob, tmp_ctx, schema->iconv_convenience, &id3.guid,
1285                                                (ndr_push_flags_fn_t)ndr_push_GUID);
1286                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1287                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1288                         talloc_free(tmp_ctx);
1289                         return ntstatus_to_werror(status);
1290                 }
1291
1292                 ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
1293                 if (ret != LDB_SUCCESS) {
1294                         talloc_free(tmp_ctx);
1295                         return WERR_FOOBAR;
1296                 }
1297
1298                 talloc_free(guid_blob.data);
1299
1300                 if (id3.__ndr_size_sid) {
1301                         DATA_BLOB sid_blob;
1302                         ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, schema->iconv_convenience, &id3.sid,
1303                                                        (ndr_push_flags_fn_t)ndr_push_dom_sid);
1304                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1305                                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1306                                 talloc_free(tmp_ctx);
1307                                 return ntstatus_to_werror(status);
1308                         }
1309
1310                         ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
1311                         if (ret != LDB_SUCCESS) {
1312                                 talloc_free(tmp_ctx);
1313                                 return WERR_FOOBAR;
1314                         }
1315                 }
1316
1317                 /* set binary stuff */
1318                 dsdb_dn = dsdb_dn_construct(tmp_ctx, dn, id3.binary, attr->syntax->ldap_oid);
1319                 if (!dsdb_dn) {
1320                         /* If this fails, it must be out of memory, we know the ldap_oid is valid */
1321                         talloc_free(tmp_ctx);
1322                         W_ERROR_HAVE_NO_MEMORY(dsdb_dn);
1323                 }
1324                 out->values[i] = data_blob_string_const(dsdb_dn_get_extended_linearized(out->values, dsdb_dn, 1));
1325                 talloc_free(tmp_ctx);
1326         }
1327
1328         return WERR_OK;
1329 }
1330
1331 static WERROR dsdb_syntax_DN_BINARY_ldb_to_drsuapi(struct ldb_context *ldb, 
1332                                                    const struct dsdb_schema *schema,
1333                                                    const struct dsdb_attribute *attr,
1334                                                    const struct ldb_message_element *in,
1335                                                    TALLOC_CTX *mem_ctx,
1336                                                    struct drsuapi_DsReplicaAttribute *out)
1337 {
1338         uint32_t i;
1339         DATA_BLOB *blobs;
1340
1341         if (attr->attributeID_id == 0xFFFFFFFF) {
1342                 return WERR_FOOBAR;
1343         }
1344
1345         out->attid                      = attr->attributeID_id;
1346         out->value_ctr.num_values       = in->num_values;
1347         out->value_ctr.values           = talloc_array(mem_ctx,
1348                                                        struct drsuapi_DsAttributeValue,
1349                                                        in->num_values);
1350         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1351
1352         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1353         W_ERROR_HAVE_NO_MEMORY(blobs);
1354
1355         for (i=0; i < in->num_values; i++) {
1356                 struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
1357                 enum ndr_err_code ndr_err;
1358                 const DATA_BLOB *guid_blob, *sid_blob;
1359                 struct dsdb_dn *dsdb_dn;
1360                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1361                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1362
1363                 out->value_ctr.values[i].blob   = &blobs[i];
1364
1365                 dsdb_dn = dsdb_dn_parse(tmp_ctx, ldb, &in->values[i], attr->syntax->ldap_oid);
1366
1367                 if (!dsdb_dn) {
1368                         talloc_free(tmp_ctx);
1369                         return ntstatus_to_werror(NT_STATUS_INVALID_PARAMETER);
1370                 }
1371
1372                 guid_blob = ldb_dn_get_extended_component(dsdb_dn->dn, "GUID");
1373
1374                 ZERO_STRUCT(id3);
1375
1376                 if (guid_blob) {
1377                         ndr_err = ndr_pull_struct_blob_all(guid_blob, 
1378                                                            tmp_ctx, schema->iconv_convenience, &id3.guid,
1379                                                            (ndr_pull_flags_fn_t)ndr_pull_GUID);
1380                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1381                                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1382                                 talloc_free(tmp_ctx);
1383                                 return ntstatus_to_werror(status);
1384                         }
1385                 }
1386
1387                 sid_blob = ldb_dn_get_extended_component(dsdb_dn->dn, "SID");
1388                 if (sid_blob) {
1389                         
1390                         ndr_err = ndr_pull_struct_blob_all(sid_blob, 
1391                                                            tmp_ctx, schema->iconv_convenience, &id3.sid,
1392                                                            (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1393                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1394                                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1395                                 talloc_free(tmp_ctx);
1396                                 return ntstatus_to_werror(status);
1397                         }
1398                 }
1399
1400                 id3.dn = ldb_dn_get_linearized(dsdb_dn->dn);
1401
1402                 /* get binary stuff */
1403                 id3.binary = dsdb_dn->extra_part;
1404
1405                 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3Binary);
1406                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1407                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1408                         talloc_free(tmp_ctx);
1409                         return ntstatus_to_werror(status);
1410                 }
1411                 talloc_free(tmp_ctx);
1412         }
1413
1414         return WERR_OK;
1415 }
1416
1417
1418
1419 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb(struct ldb_context *ldb, 
1420                                                               const struct dsdb_schema *schema,
1421                                                               const struct dsdb_attribute *attr,
1422                                                               const struct drsuapi_DsReplicaAttribute *in,
1423                                                               TALLOC_CTX *mem_ctx,
1424                                                               struct ldb_message_element *out)
1425 {
1426         uint32_t i;
1427
1428         out->flags      = 0;
1429         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1430         W_ERROR_HAVE_NO_MEMORY(out->name);
1431
1432         out->num_values = in->value_ctr.num_values;
1433         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1434         W_ERROR_HAVE_NO_MEMORY(out->values);
1435
1436         for (i=0; i < out->num_values; i++) {
1437                 uint32_t len;
1438                 char *str;
1439
1440                 if (in->value_ctr.values[i].blob == NULL) {
1441                         return WERR_FOOBAR;
1442                 }
1443
1444                 if (in->value_ctr.values[i].blob->length < 4) {
1445                         return WERR_FOOBAR;
1446                 }
1447
1448                 len = IVAL(in->value_ctr.values[i].blob->data, 0);
1449
1450                 if (len != in->value_ctr.values[i].blob->length) {
1451                         return WERR_FOOBAR;
1452                 }
1453
1454                 if (!convert_string_talloc_convenience(out->values, schema->iconv_convenience, CH_UTF16, CH_UNIX,
1455                                             in->value_ctr.values[i].blob->data+4,
1456                                             in->value_ctr.values[i].blob->length-4,
1457                                             (void **)&str, NULL, false)) {
1458                         return WERR_FOOBAR;
1459                 }
1460
1461                 out->values[i] = data_blob_string_const(str);
1462         }
1463
1464         return WERR_OK;
1465 }
1466
1467 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi(struct ldb_context *ldb, 
1468                                                               const struct dsdb_schema *schema,
1469                                                               const struct dsdb_attribute *attr,
1470                                                               const struct ldb_message_element *in,
1471                                                               TALLOC_CTX *mem_ctx,
1472                                                               struct drsuapi_DsReplicaAttribute *out)
1473 {
1474         uint32_t i;
1475         DATA_BLOB *blobs;
1476
1477         if (attr->attributeID_id == 0xFFFFFFFF) {
1478                 return WERR_FOOBAR;
1479         }
1480
1481         out->attid                      = attr->attributeID_id;
1482         out->value_ctr.num_values       = in->num_values;
1483         out->value_ctr.values           = talloc_array(mem_ctx,
1484                                                        struct drsuapi_DsAttributeValue,
1485                                                        in->num_values);
1486         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1487
1488         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1489         W_ERROR_HAVE_NO_MEMORY(blobs);
1490
1491         for (i=0; i < in->num_values; i++) {
1492                 uint8_t *data;
1493                 size_t ret;
1494
1495                 out->value_ctr.values[i].blob   = &blobs[i];
1496
1497                 if (!convert_string_talloc_convenience(blobs, schema->iconv_convenience, CH_UNIX, CH_UTF16,
1498                                             in->values[i].data,
1499                                             in->values[i].length,
1500                                             (void **)&data, &ret, false)) {
1501                         return WERR_FOOBAR;
1502                 }
1503
1504                 blobs[i] = data_blob_talloc(blobs, NULL, 4 + ret);
1505                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1506
1507                 SIVAL(blobs[i].data, 0, 4 + ret);
1508
1509                 if (ret > 0) {
1510                         memcpy(blobs[i].data + 4, data, ret);
1511                         talloc_free(data);
1512                 }
1513         }
1514
1515         return WERR_OK;
1516 }
1517
1518 #define OMOBJECTCLASS(val) { .length = sizeof(val) - 1, .data = discard_const_p(uint8_t, val) }
1519
1520 static const struct dsdb_syntax dsdb_syntaxes[] = {
1521         {
1522                 .name                   = "Boolean",
1523                 .ldap_oid               = LDB_SYNTAX_BOOLEAN,
1524                 .oMSyntax               = 1,
1525                 .attributeSyntax_oid    = "2.5.5.8",
1526                 .drsuapi_to_ldb         = dsdb_syntax_BOOL_drsuapi_to_ldb,
1527                 .ldb_to_drsuapi         = dsdb_syntax_BOOL_ldb_to_drsuapi,
1528                 .equality               = "booleanMatch",
1529                 .comment                = "Boolean" 
1530         },{
1531                 .name                   = "Integer",
1532                 .ldap_oid               = LDB_SYNTAX_INTEGER,
1533                 .oMSyntax               = 2,
1534                 .attributeSyntax_oid    = "2.5.5.9",
1535                 .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
1536                 .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
1537                 .equality               = "integerMatch",
1538                 .comment                = "Integer",
1539                 .ldb_syntax             = LDB_SYNTAX_SAMBA_INT32
1540         },{
1541                 .name                   = "String(Octet)",
1542                 .ldap_oid               = LDB_SYNTAX_OCTET_STRING,
1543                 .oMSyntax               = 4,
1544                 .attributeSyntax_oid    = "2.5.5.10",
1545                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1546                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1547                 .equality               = "octetStringMatch",
1548                 .comment                = "Octet String",
1549         },{
1550                 .name                   = "String(Sid)",
1551                 .ldap_oid               = LDB_SYNTAX_OCTET_STRING,
1552                 .oMSyntax               = 4,
1553                 .attributeSyntax_oid    = "2.5.5.17",
1554                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1555                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1556                 .equality               = "octetStringMatch",
1557                 .comment                = "Octet String - Security Identifier (SID)",
1558                 .ldb_syntax             = LDB_SYNTAX_SAMBA_SID
1559         },{
1560                 .name                   = "String(Object-Identifier)",
1561                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.38",
1562                 .oMSyntax               = 6,
1563                 .attributeSyntax_oid    = "2.5.5.2",
1564                 .drsuapi_to_ldb         = dsdb_syntax_OID_drsuapi_to_ldb,
1565                 .ldb_to_drsuapi         = dsdb_syntax_OID_ldb_to_drsuapi,
1566                 .equality               = "caseIgnoreMatch", /* Would use "objectIdentifierMatch" but most are ldap attribute/class names */
1567                 .comment                = "OID String",
1568                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING
1569         },{
1570                 .name                   = "Enumeration",
1571                 .ldap_oid               = LDB_SYNTAX_INTEGER,
1572                 .oMSyntax               = 10,
1573                 .attributeSyntax_oid    = "2.5.5.9",
1574                 .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
1575                 .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
1576                 .ldb_syntax             = LDB_SYNTAX_SAMBA_INT32
1577         },{
1578         /* not used in w2k3 forest */
1579                 .name                   = "String(Numeric)",
1580                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.36",
1581                 .oMSyntax               = 18,
1582                 .attributeSyntax_oid    = "2.5.5.6",
1583                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1584                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1585                 .equality               = "numericStringMatch",
1586                 .substring              = "numericStringSubstringsMatch",
1587                 .comment                = "Numeric String",
1588                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1589         },{
1590                 .name                   = "String(Printable)",
1591                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.44",
1592                 .oMSyntax               = 19,
1593                 .attributeSyntax_oid    = "2.5.5.5",
1594                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1595                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1596                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
1597         },{
1598                 .name                   = "String(Teletex)",
1599                 .ldap_oid               = "1.2.840.113556.1.4.905",
1600                 .oMSyntax               = 20,
1601                 .attributeSyntax_oid    = "2.5.5.4",
1602                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1603                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1604                 .equality               = "caseIgnoreMatch",
1605                 .substring              = "caseIgnoreSubstringsMatch",
1606                 .comment                = "Case Insensitive String",
1607                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1608         },{
1609                 .name                   = "String(IA5)",
1610                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.26",
1611                 .oMSyntax               = 22,
1612                 .attributeSyntax_oid    = "2.5.5.5",
1613                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1614                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1615                 .equality               = "caseExactIA5Match",
1616                 .comment                = "Printable String",
1617                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
1618         },{
1619                 .name                   = "String(UTC-Time)",
1620                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.53",
1621                 .oMSyntax               = 23,
1622                 .attributeSyntax_oid    = "2.5.5.11",
1623                 .drsuapi_to_ldb         = dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb,
1624                 .ldb_to_drsuapi         = dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi,
1625                 .equality               = "generalizedTimeMatch",
1626                 .comment                = "UTC Time",
1627         },{
1628                 .name                   = "String(Generalized-Time)",
1629                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.24",
1630                 .oMSyntax               = 24,
1631                 .attributeSyntax_oid    = "2.5.5.11",
1632                 .drsuapi_to_ldb         = dsdb_syntax_NTTIME_drsuapi_to_ldb,
1633                 .ldb_to_drsuapi         = dsdb_syntax_NTTIME_ldb_to_drsuapi,
1634                 .equality               = "generalizedTimeMatch",
1635                 .comment                = "Generalized Time",
1636                 .ldb_syntax             = LDB_SYNTAX_UTC_TIME,
1637         },{
1638         /* not used in w2k3 schema */
1639                 .name                   = "String(Case Sensitive)",
1640                 .ldap_oid               = "1.2.840.113556.1.4.1362",
1641                 .oMSyntax               = 27,
1642                 .attributeSyntax_oid    = "2.5.5.3",
1643                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1644                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1645         },{
1646                 .name                   = "String(Unicode)",
1647                 .ldap_oid               = LDB_SYNTAX_DIRECTORY_STRING,
1648                 .oMSyntax               = 64,
1649                 .attributeSyntax_oid    = "2.5.5.12",
1650                 .drsuapi_to_ldb         = dsdb_syntax_UNICODE_drsuapi_to_ldb,
1651                 .ldb_to_drsuapi         = dsdb_syntax_UNICODE_ldb_to_drsuapi,
1652                 .equality               = "caseIgnoreMatch",
1653                 .substring              = "caseIgnoreSubstringsMatch",
1654                 .comment                = "Directory String",
1655         },{
1656                 .name                   = "Interval/LargeInteger",
1657                 .ldap_oid               = "1.2.840.113556.1.4.906",
1658                 .oMSyntax               = 65,
1659                 .attributeSyntax_oid    = "2.5.5.16",
1660                 .drsuapi_to_ldb         = dsdb_syntax_INT64_drsuapi_to_ldb,
1661                 .ldb_to_drsuapi         = dsdb_syntax_INT64_ldb_to_drsuapi,
1662                 .equality               = "integerMatch",
1663                 .comment                = "Large Integer",
1664                 .ldb_syntax             = LDB_SYNTAX_INTEGER,
1665         },{
1666                 .name                   = "String(NT-Sec-Desc)",
1667                 .ldap_oid               = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1668                 .oMSyntax               = 66,
1669                 .attributeSyntax_oid    = "2.5.5.15",
1670                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1671                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1672         },{
1673                 .name                   = "Object(DS-DN)",
1674                 .ldap_oid               = LDB_SYNTAX_DN,
1675                 .oMSyntax               = 127,
1676                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x4a"),
1677                 .attributeSyntax_oid    = "2.5.5.1",
1678                 .drsuapi_to_ldb         = dsdb_syntax_DN_drsuapi_to_ldb,
1679                 .ldb_to_drsuapi         = dsdb_syntax_DN_ldb_to_drsuapi,
1680                 .equality               = "distinguishedNameMatch",
1681                 .comment                = "Object(DS-DN) == a DN",
1682         },{
1683                 .name                   = "Object(DN-Binary)",
1684                 .ldap_oid               = DSDB_SYNTAX_BINARY_DN,
1685                 .oMSyntax               = 127,
1686                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0b"),
1687                 .attributeSyntax_oid    = "2.5.5.7",
1688                 .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
1689                 .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
1690                 .equality               = "octetStringMatch",
1691                 .comment                = "OctetString: Binary+DN",
1692         },{
1693         /* not used in w2k3 schema, but used in Exchange schema*/
1694                 .name                   = "Object(OR-Name)",
1695                 .ldap_oid               = DSDB_SYNTAX_OR_NAME,
1696                 .oMSyntax               = 127,
1697                 .oMObjectClass          = OMOBJECTCLASS("\x56\x06\x01\x02\x05\x0b\x1D"),
1698                 .attributeSyntax_oid    = "2.5.5.7",
1699                 .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
1700                 .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
1701                 .equality               = "caseIgnoreMatch",
1702                 .ldb_syntax             = LDB_SYNTAX_DN,
1703         },{
1704         /* 
1705          * TODO: verify if DATA_BLOB is correct here...!
1706          *
1707          *       repsFrom and repsTo are the only attributes using
1708          *       this attribute syntax, but they're not replicated... 
1709          */
1710                 .name                   = "Object(Replica-Link)",
1711                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.40",
1712                 .oMSyntax               = 127,
1713                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x06"),
1714                 .attributeSyntax_oid    = "2.5.5.10",
1715                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1716                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1717         },{
1718                 .name                   = "Object(Presentation-Address)",
1719                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.43",
1720                 .oMSyntax               = 127,
1721                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x5c"),
1722                 .attributeSyntax_oid    = "2.5.5.13",
1723                 .drsuapi_to_ldb         = dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb,
1724                 .ldb_to_drsuapi         = dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi,
1725                 .comment                = "Presentation Address",
1726                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1727         },{
1728         /* not used in w2k3 schema */
1729                 .name                   = "Object(Access-Point)",
1730                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.2",
1731                 .oMSyntax               = 127,
1732                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x3e"),
1733                 .attributeSyntax_oid    = "2.5.5.14",
1734                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1735                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1736                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1737         },{
1738         /* not used in w2k3 schema */
1739                 .name                   = "Object(DN-String)",
1740                 .ldap_oid               = DSDB_SYNTAX_STRING_DN,
1741                 .oMSyntax               = 127,
1742                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0c"),
1743                 .attributeSyntax_oid    = "2.5.5.14",
1744                 .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
1745                 .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
1746                 .equality               = "octetStringMatch",
1747                 .comment                = "OctetString: String+DN",
1748         }
1749 };
1750
1751 const struct dsdb_syntax *find_syntax_map_by_ad_oid(const char *ad_oid) 
1752 {
1753         int i;
1754         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1755                 if (strcasecmp(ad_oid, dsdb_syntaxes[i].attributeSyntax_oid) == 0) {
1756                         return &dsdb_syntaxes[i];
1757                 }
1758         }
1759         return NULL;
1760 }
1761
1762 const struct dsdb_syntax *find_syntax_map_by_ad_syntax(int oMSyntax) 
1763 {
1764         int i;
1765         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1766                 if (oMSyntax == dsdb_syntaxes[i].oMSyntax) {
1767                         return &dsdb_syntaxes[i];
1768                 }
1769         }
1770         return NULL;
1771 }
1772
1773 const struct dsdb_syntax *find_syntax_map_by_standard_oid(const char *standard_oid) 
1774 {
1775         int i;
1776         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1777                 if (strcasecmp(standard_oid, dsdb_syntaxes[i].ldap_oid) == 0) {
1778                         return &dsdb_syntaxes[i];
1779                 }
1780         }
1781         return NULL;
1782 }
1783 const struct dsdb_syntax *dsdb_syntax_for_attribute(const struct dsdb_attribute *attr)
1784 {
1785         uint32_t i;
1786
1787         for (i=0; i < ARRAY_SIZE(dsdb_syntaxes); i++) {
1788                 if (attr->oMSyntax != dsdb_syntaxes[i].oMSyntax) continue;
1789
1790                 if (attr->oMObjectClass.length != dsdb_syntaxes[i].oMObjectClass.length) continue;
1791
1792                 if (attr->oMObjectClass.length) {
1793                         int ret;
1794                         ret = memcmp(attr->oMObjectClass.data,
1795                                      dsdb_syntaxes[i].oMObjectClass.data,
1796                                      attr->oMObjectClass.length);
1797                         if (ret != 0) continue;
1798                 }
1799
1800                 if (strcmp(attr->attributeSyntax_oid, dsdb_syntaxes[i].attributeSyntax_oid) != 0) continue;
1801
1802                 return &dsdb_syntaxes[i];
1803         }
1804
1805         return NULL;
1806 }
1807
1808 WERROR dsdb_attribute_drsuapi_to_ldb(struct ldb_context *ldb, 
1809                                      const struct dsdb_schema *schema,
1810                                      const struct drsuapi_DsReplicaAttribute *in,
1811                                      TALLOC_CTX *mem_ctx,
1812                                      struct ldb_message_element *out)
1813 {
1814         const struct dsdb_attribute *sa;
1815
1816         sa = dsdb_attribute_by_attributeID_id(schema, in->attid);
1817         if (!sa) {
1818                 return WERR_FOOBAR;
1819         }
1820
1821         return sa->syntax->drsuapi_to_ldb(ldb, schema, sa, in, mem_ctx, out);
1822 }
1823
1824 WERROR dsdb_attribute_ldb_to_drsuapi(struct ldb_context *ldb, 
1825                                      const struct dsdb_schema *schema,
1826                                      const struct ldb_message_element *in,
1827                                      TALLOC_CTX *mem_ctx,
1828                                      struct drsuapi_DsReplicaAttribute *out)
1829 {
1830         const struct dsdb_attribute *sa;
1831
1832         sa = dsdb_attribute_by_lDAPDisplayName(schema, in->name);
1833         if (!sa) {
1834                 return WERR_FOOBAR;
1835         }
1836
1837         return sa->syntax->ldb_to_drsuapi(ldb, schema, sa, in, mem_ctx, out);
1838 }