s4-dsdb: use ldb_val_to_time() instead of ldb_string_to_time()
[ira/wip.git] / source4 / dsdb / schema / schema_syntax.c
1 /* 
2    Unix SMB/CIFS mplementation.
3    DSDB schema syntaxes
4    
5    Copyright (C) Stefan Metzmacher <metze@samba.org> 2006
6    Copyright (C) Simo Sorce 2005
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21    
22 */
23 #include "includes.h"
24 #include "dsdb/samdb/samdb.h"
25 #include "librpc/gen_ndr/ndr_drsuapi.h"
26 #include "librpc/gen_ndr/ndr_security.h"
27 #include "librpc/gen_ndr/ndr_misc.h"
28 #include "lib/ldb/include/ldb.h"
29 #include "lib/ldb/include/ldb_errors.h"
30 #include "system/time.h"
31 #include "../lib/util/charset/charset.h"
32 #include "librpc/ndr/libndr.h"
33
34 static WERROR dsdb_syntax_FOOBAR_drsuapi_to_ldb(struct ldb_context *ldb, 
35                                                 const struct dsdb_schema *schema,
36                                                 const struct dsdb_attribute *attr,
37                                                 const struct drsuapi_DsReplicaAttribute *in,
38                                                 TALLOC_CTX *mem_ctx,
39                                                 struct ldb_message_element *out)
40 {
41         uint32_t i;
42
43         out->flags      = 0;
44         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
45         W_ERROR_HAVE_NO_MEMORY(out->name);
46
47         out->num_values = in->value_ctr.num_values;
48         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
49         W_ERROR_HAVE_NO_MEMORY(out->values);
50
51         for (i=0; i < out->num_values; i++) {
52                 char *str;
53
54                 if (in->value_ctr.values[i].blob == NULL) {
55                         return WERR_FOOBAR;
56                 }
57
58                 str = talloc_asprintf(out->values, "%s: not implemented",
59                                       attr->syntax->name);
60                 W_ERROR_HAVE_NO_MEMORY(str);
61
62                 out->values[i] = data_blob_string_const(str);
63         }
64
65         return WERR_OK;
66 }
67
68 static WERROR dsdb_syntax_FOOBAR_ldb_to_drsuapi(struct ldb_context *ldb, 
69                                                 const struct dsdb_schema *schema,
70                                                 const struct dsdb_attribute *attr,
71                                                 const struct ldb_message_element *in,
72                                                 TALLOC_CTX *mem_ctx,
73                                                 struct drsuapi_DsReplicaAttribute *out)
74 {
75         return WERR_FOOBAR;
76 }
77
78 static WERROR dsdb_syntax_BOOL_drsuapi_to_ldb(struct ldb_context *ldb, 
79                                               const struct dsdb_schema *schema,
80                                               const struct dsdb_attribute *attr,
81                                               const struct drsuapi_DsReplicaAttribute *in,
82                                               TALLOC_CTX *mem_ctx,
83                                               struct ldb_message_element *out)
84 {
85         uint32_t i;
86
87         out->flags      = 0;
88         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
89         W_ERROR_HAVE_NO_MEMORY(out->name);
90
91         out->num_values = in->value_ctr.num_values;
92         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
93         W_ERROR_HAVE_NO_MEMORY(out->values);
94
95         for (i=0; i < out->num_values; i++) {
96                 uint32_t v;
97                 char *str;
98
99                 if (in->value_ctr.values[i].blob == NULL) {
100                         return WERR_FOOBAR;
101                 }
102
103                 if (in->value_ctr.values[i].blob->length != 4) {
104                         return WERR_FOOBAR;
105                 }
106
107                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
108
109                 if (v != 0) {
110                         str = talloc_strdup(out->values, "TRUE");
111                         W_ERROR_HAVE_NO_MEMORY(str);
112                 } else {
113                         str = talloc_strdup(out->values, "FALSE");
114                         W_ERROR_HAVE_NO_MEMORY(str);
115                 }
116
117                 out->values[i] = data_blob_string_const(str);
118         }
119
120         return WERR_OK;
121 }
122
123 static WERROR dsdb_syntax_BOOL_ldb_to_drsuapi(struct ldb_context *ldb, 
124                                               const struct dsdb_schema *schema,
125                                               const struct dsdb_attribute *attr,
126                                               const struct ldb_message_element *in,
127                                               TALLOC_CTX *mem_ctx,
128                                               struct drsuapi_DsReplicaAttribute *out)
129 {
130         uint32_t i;
131         DATA_BLOB *blobs;
132
133         if (attr->attributeID_id == 0xFFFFFFFF) {
134                 return WERR_FOOBAR;
135         }
136
137         out->attid                      = attr->attributeID_id;
138         out->value_ctr.num_values       = in->num_values;
139         out->value_ctr.values           = talloc_array(mem_ctx,
140                                                        struct drsuapi_DsAttributeValue,
141                                                        in->num_values);
142         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
143
144         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
145         W_ERROR_HAVE_NO_MEMORY(blobs);
146
147         for (i=0; i < in->num_values; i++) {
148                 out->value_ctr.values[i].blob   = &blobs[i];
149
150                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
151                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
152
153                 if (strcmp("TRUE", (const char *)in->values[i].data) == 0) {
154                         SIVAL(blobs[i].data, 0, 0x00000001);
155                 } else if (strcmp("FALSE", (const char *)in->values[i].data) == 0) {
156                         SIVAL(blobs[i].data, 0, 0x00000000);
157                 } else {
158                         return WERR_FOOBAR;
159                 }
160         }
161
162         return WERR_OK;
163 }
164
165 static WERROR dsdb_syntax_INT32_drsuapi_to_ldb(struct ldb_context *ldb, 
166                                                const struct dsdb_schema *schema,
167                                                const struct dsdb_attribute *attr,
168                                                const struct drsuapi_DsReplicaAttribute *in,
169                                                TALLOC_CTX *mem_ctx,
170                                                struct ldb_message_element *out)
171 {
172         uint32_t i;
173
174         out->flags      = 0;
175         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
176         W_ERROR_HAVE_NO_MEMORY(out->name);
177
178         out->num_values = in->value_ctr.num_values;
179         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
180         W_ERROR_HAVE_NO_MEMORY(out->values);
181
182         for (i=0; i < out->num_values; i++) {
183                 int32_t v;
184                 char *str;
185
186                 if (in->value_ctr.values[i].blob == NULL) {
187                         return WERR_FOOBAR;
188                 }
189
190                 if (in->value_ctr.values[i].blob->length != 4) {
191                         return WERR_FOOBAR;
192                 }
193
194                 v = IVALS(in->value_ctr.values[i].blob->data, 0);
195
196                 str = talloc_asprintf(out->values, "%d", v);
197                 W_ERROR_HAVE_NO_MEMORY(str);
198
199                 out->values[i] = data_blob_string_const(str);
200         }
201
202         return WERR_OK;
203 }
204
205 static WERROR dsdb_syntax_INT32_ldb_to_drsuapi(struct ldb_context *ldb, 
206                                                const struct dsdb_schema *schema,
207                                                const struct dsdb_attribute *attr,
208                                                const struct ldb_message_element *in,
209                                                TALLOC_CTX *mem_ctx,
210                                                struct drsuapi_DsReplicaAttribute *out)
211 {
212         uint32_t i;
213         DATA_BLOB *blobs;
214
215         if (attr->attributeID_id == 0xFFFFFFFF) {
216                 return WERR_FOOBAR;
217         }
218
219         out->attid                      = attr->attributeID_id;
220         out->value_ctr.num_values       = in->num_values;
221         out->value_ctr.values           = talloc_array(mem_ctx,
222                                                        struct drsuapi_DsAttributeValue,
223                                                        in->num_values);
224         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
225
226         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
227         W_ERROR_HAVE_NO_MEMORY(blobs);
228
229         for (i=0; i < in->num_values; i++) {
230                 int32_t v;
231
232                 out->value_ctr.values[i].blob   = &blobs[i];
233
234                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
235                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
236
237                 /* 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                 int ret;
492
493                 out->value_ctr.values[i].blob   = &blobs[i];
494
495                 blobs[i] = data_blob_talloc(blobs, NULL, 8);
496                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
497
498                 ret = ldb_val_to_time(&in->values[i], &t);
499                 if (ret != LDB_SUCCESS) {
500                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
501                 }
502                 unix_to_nt_time(&v, t);
503                 v /= 10000000;
504
505                 SBVAL(blobs[i].data, 0, v);
506         }
507
508         return WERR_OK;
509 }
510
511 static WERROR dsdb_syntax_DATA_BLOB_drsuapi_to_ldb(struct ldb_context *ldb, 
512                                                    const struct dsdb_schema *schema,
513                                                    const struct dsdb_attribute *attr,
514                                                    const struct drsuapi_DsReplicaAttribute *in,
515                                                    TALLOC_CTX *mem_ctx,
516                                                    struct ldb_message_element *out)
517 {
518         uint32_t i;
519
520         out->flags      = 0;
521         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
522         W_ERROR_HAVE_NO_MEMORY(out->name);
523
524         out->num_values = in->value_ctr.num_values;
525         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
526         W_ERROR_HAVE_NO_MEMORY(out->values);
527
528         for (i=0; i < out->num_values; i++) {
529                 if (in->value_ctr.values[i].blob == NULL) {
530                         return WERR_FOOBAR;
531                 }
532
533                 if (in->value_ctr.values[i].blob->length == 0) {
534                         return WERR_FOOBAR;
535                 }
536
537                 out->values[i] = data_blob_dup_talloc(out->values,
538                                                       in->value_ctr.values[i].blob);
539                 W_ERROR_HAVE_NO_MEMORY(out->values[i].data);
540         }
541
542         return WERR_OK;
543 }
544
545 static WERROR dsdb_syntax_DATA_BLOB_ldb_to_drsuapi(struct ldb_context *ldb, 
546                                                    const struct dsdb_schema *schema,
547                                                    const struct dsdb_attribute *attr,
548                                                    const struct ldb_message_element *in,
549                                                    TALLOC_CTX *mem_ctx,
550                                                    struct drsuapi_DsReplicaAttribute *out)
551 {
552         uint32_t i;
553         DATA_BLOB *blobs;
554
555         if (attr->attributeID_id == 0xFFFFFFFF) {
556                 return WERR_FOOBAR;
557         }
558
559         out->attid                      = attr->attributeID_id;
560         out->value_ctr.num_values       = in->num_values;
561         out->value_ctr.values           = talloc_array(mem_ctx,
562                                                        struct drsuapi_DsAttributeValue,
563                                                        in->num_values);
564         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
565
566         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
567         W_ERROR_HAVE_NO_MEMORY(blobs);
568
569         for (i=0; i < in->num_values; i++) {
570                 out->value_ctr.values[i].blob   = &blobs[i];
571
572                 blobs[i] = data_blob_dup_talloc(blobs, &in->values[i]);
573                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
574         }
575
576         return WERR_OK;
577 }
578
579 static WERROR _dsdb_syntax_OID_obj_drsuapi_to_ldb(struct ldb_context *ldb, 
580                                                   const struct dsdb_schema *schema,
581                                                   const struct dsdb_attribute *attr,
582                                                   const struct drsuapi_DsReplicaAttribute *in,
583                                                   TALLOC_CTX *mem_ctx,
584                                                   struct ldb_message_element *out)
585 {
586         uint32_t i;
587
588         out->flags      = 0;
589         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
590         W_ERROR_HAVE_NO_MEMORY(out->name);
591
592         out->num_values = in->value_ctr.num_values;
593         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
594         W_ERROR_HAVE_NO_MEMORY(out->values);
595
596         for (i=0; i < out->num_values; i++) {
597                 uint32_t v;
598                 const struct dsdb_class *c;
599                 const char *str;
600
601                 if (in->value_ctr.values[i].blob == NULL) {
602                         return WERR_FOOBAR;
603                 }
604
605                 if (in->value_ctr.values[i].blob->length != 4) {
606                         return WERR_FOOBAR;
607                 }
608
609                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
610
611                 c = dsdb_class_by_governsID_id(schema, v);
612                 if (!c) {
613                         return WERR_FOOBAR;
614                 }
615
616                 str = talloc_strdup(out->values, c->lDAPDisplayName);
617                 W_ERROR_HAVE_NO_MEMORY(str);
618
619                 /* the values need to be reversed */
620                 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
621         }
622
623         return WERR_OK;
624 }
625
626 static WERROR _dsdb_syntax_OID_attr_drsuapi_to_ldb(struct ldb_context *ldb, 
627                                                    const struct dsdb_schema *schema,
628                                                    const struct dsdb_attribute *attr,
629                                                    const struct drsuapi_DsReplicaAttribute *in,
630                                                    TALLOC_CTX *mem_ctx,
631                                                    struct ldb_message_element *out)
632 {
633         uint32_t i;
634
635         out->flags      = 0;
636         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
637         W_ERROR_HAVE_NO_MEMORY(out->name);
638
639         out->num_values = in->value_ctr.num_values;
640         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
641         W_ERROR_HAVE_NO_MEMORY(out->values);
642
643         for (i=0; i < out->num_values; i++) {
644                 uint32_t v;
645                 const struct dsdb_attribute *a;
646                 const char *str;
647
648                 if (in->value_ctr.values[i].blob == NULL) {
649                         return WERR_FOOBAR;
650                 }
651
652                 if (in->value_ctr.values[i].blob->length != 4) {
653                         return WERR_FOOBAR;
654                 }
655
656                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
657
658                 a = dsdb_attribute_by_attributeID_id(schema, v);
659                 if (!a) {
660                         return WERR_FOOBAR;
661                 }
662
663                 str = talloc_strdup(out->values, a->lDAPDisplayName);
664                 W_ERROR_HAVE_NO_MEMORY(str);
665
666                 /* the values need to be reversed */
667                 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
668         }
669
670         return WERR_OK;
671 }
672
673 static WERROR _dsdb_syntax_OID_oid_drsuapi_to_ldb(struct ldb_context *ldb, 
674                                                   const struct dsdb_schema *schema,
675                                                   const struct dsdb_attribute *attr,
676                                                   const struct drsuapi_DsReplicaAttribute *in,
677                                                   TALLOC_CTX *mem_ctx,
678                                                   struct ldb_message_element *out)
679 {
680         uint32_t i;
681
682         out->flags      = 0;
683         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
684         W_ERROR_HAVE_NO_MEMORY(out->name);
685
686         out->num_values = in->value_ctr.num_values;
687         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
688         W_ERROR_HAVE_NO_MEMORY(out->values);
689
690         for (i=0; i < out->num_values; i++) {
691                 uint32_t attid;
692                 WERROR status;
693                 const char *oid;
694
695                 if (in->value_ctr.values[i].blob == NULL) {
696                         return WERR_FOOBAR;
697                 }
698
699                 if (in->value_ctr.values[i].blob->length != 4) {
700                         return WERR_FOOBAR;
701                 }
702
703                 attid = IVAL(in->value_ctr.values[i].blob->data, 0);
704
705                 status = dsdb_schema_pfm_oid_from_attid(schema->prefixmap, attid, out->values, &oid);
706                 W_ERROR_NOT_OK_RETURN(status);
707
708                 out->values[i] = data_blob_string_const(oid);
709         }
710
711         return WERR_OK;
712 }
713
714 static WERROR _dsdb_syntax_OID_obj_ldb_to_drsuapi(struct ldb_context *ldb,
715                                                   const struct dsdb_schema *schema,
716                                                   const struct dsdb_attribute *attr,
717                                                   const struct ldb_message_element *in,
718                                                   TALLOC_CTX *mem_ctx,
719                                                   struct drsuapi_DsReplicaAttribute *out)
720 {
721         uint32_t i;
722         DATA_BLOB *blobs;
723
724         out->attid= attr->attributeID_id;
725         out->value_ctr.num_values= in->num_values;
726         out->value_ctr.values= talloc_array(mem_ctx,
727                                             struct drsuapi_DsAttributeValue,
728                                             in->num_values);
729         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
730
731         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
732         W_ERROR_HAVE_NO_MEMORY(blobs);
733
734         for (i=0; i < in->num_values; i++) {
735                 const struct dsdb_class *obj_class;
736
737                 out->value_ctr.values[i].blob= &blobs[i];
738
739                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
740                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
741
742                 /* in DRS windows puts the classes in the opposite
743                    order to the order used in ldap */
744                 obj_class = dsdb_class_by_lDAPDisplayName(schema,
745                                                           (const char *)in->values[(in->num_values-1)-i].data);
746                 if (!obj_class) {
747                         return WERR_FOOBAR;
748                 }
749                 SIVAL(blobs[i].data, 0, obj_class->governsID_id);
750         }
751
752
753         return WERR_OK;
754 }
755
756 static WERROR _dsdb_syntax_OID_attr_ldb_to_drsuapi(struct ldb_context *ldb,
757                                                    const struct dsdb_schema *schema,
758                                                    const struct dsdb_attribute *attr,
759                                                    const struct ldb_message_element *in,
760                                                    TALLOC_CTX *mem_ctx,
761                                                    struct drsuapi_DsReplicaAttribute *out)
762 {
763         uint32_t i;
764         DATA_BLOB *blobs;
765
766         out->attid= attr->attributeID_id;
767         out->value_ctr.num_values= in->num_values;
768         out->value_ctr.values= talloc_array(mem_ctx,
769                                             struct drsuapi_DsAttributeValue,
770                                             in->num_values);
771         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
772
773         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
774         W_ERROR_HAVE_NO_MEMORY(blobs);
775
776         for (i=0; i < in->num_values; i++) {
777                 const struct dsdb_attribute *obj_attr;
778
779                 out->value_ctr.values[i].blob= &blobs[i];
780
781                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
782                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
783
784                 obj_attr = dsdb_attribute_by_lDAPDisplayName(schema, (const char *)in->values[i].data);
785                 if (!obj_attr) {
786                         return WERR_FOOBAR;
787                 }
788                 SIVAL(blobs[i].data, 0, obj_attr->attributeID_id);
789         }
790
791
792         return WERR_OK;
793 }
794
795 static WERROR _dsdb_syntax_OID_oid_ldb_to_drsuapi(struct ldb_context *ldb,
796                                                   const struct dsdb_schema *schema,
797                                                   const struct dsdb_attribute *attr,
798                                                   const struct ldb_message_element *in,
799                                                   TALLOC_CTX *mem_ctx,
800                                                   struct drsuapi_DsReplicaAttribute *out)
801 {
802         uint32_t i;
803         DATA_BLOB *blobs;
804
805         out->attid= attr->attributeID_id;
806         out->value_ctr.num_values= in->num_values;
807         out->value_ctr.values= talloc_array(mem_ctx,
808                                             struct drsuapi_DsAttributeValue,
809                                             in->num_values);
810         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
811
812         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
813         W_ERROR_HAVE_NO_MEMORY(blobs);
814
815         for (i=0; i < in->num_values; i++) {
816                 uint32_t attid;
817                 WERROR status;
818
819                 out->value_ctr.values[i].blob= &blobs[i];
820
821                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
822                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
823
824                 status = dsdb_schema_pfm_make_attid(schema->prefixmap,
825                                                     (const char *)in->values[i].data,
826                                                     &attid);
827                 W_ERROR_NOT_OK_RETURN(status);
828
829                 SIVAL(blobs[i].data, 0, attid);
830         }
831
832         return WERR_OK;
833 }
834
835 static WERROR dsdb_syntax_OID_drsuapi_to_ldb(struct ldb_context *ldb, 
836                                              const struct dsdb_schema *schema,
837                                              const struct dsdb_attribute *attr,
838                                              const struct drsuapi_DsReplicaAttribute *in,
839                                              TALLOC_CTX *mem_ctx,
840                                              struct ldb_message_element *out)
841 {
842         uint32_t i;
843
844         switch (attr->attributeID_id) {
845         case DRSUAPI_ATTRIBUTE_objectClass:
846         case DRSUAPI_ATTRIBUTE_subClassOf:
847         case DRSUAPI_ATTRIBUTE_auxiliaryClass:
848         case DRSUAPI_ATTRIBUTE_systemPossSuperiors:
849         case DRSUAPI_ATTRIBUTE_possSuperiors:
850                 return _dsdb_syntax_OID_obj_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
851         case DRSUAPI_ATTRIBUTE_systemMustContain:
852         case DRSUAPI_ATTRIBUTE_systemMayContain:        
853         case DRSUAPI_ATTRIBUTE_mustContain:
854         case DRSUAPI_ATTRIBUTE_mayContain:
855                 return _dsdb_syntax_OID_attr_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
856         case DRSUAPI_ATTRIBUTE_governsID:
857         case DRSUAPI_ATTRIBUTE_attributeID:
858         case DRSUAPI_ATTRIBUTE_attributeSyntax:
859                 return _dsdb_syntax_OID_oid_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
860         }
861
862         out->flags      = 0;
863         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
864         W_ERROR_HAVE_NO_MEMORY(out->name);
865
866         out->num_values = in->value_ctr.num_values;
867         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
868         W_ERROR_HAVE_NO_MEMORY(out->values);
869
870         for (i=0; i < out->num_values; i++) {
871                 uint32_t v;
872                 const char *name;
873                 char *str;
874
875                 if (in->value_ctr.values[i].blob == NULL) {
876                         return WERR_FOOBAR;
877                 }
878
879                 if (in->value_ctr.values[i].blob->length != 4) {
880                         return WERR_FOOBAR;
881                 }
882
883                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
884
885                 name = dsdb_lDAPDisplayName_by_id(schema, v);
886                 if (!name) {
887                         return WERR_FOOBAR;
888                 }
889
890                 str = talloc_strdup(out->values, name);
891                 W_ERROR_HAVE_NO_MEMORY(str);
892
893                 out->values[i] = data_blob_string_const(str);
894         }
895
896         return WERR_OK;
897 }
898
899 static WERROR dsdb_syntax_OID_ldb_to_drsuapi(struct ldb_context *ldb, 
900                                              const struct dsdb_schema *schema,
901                                              const struct dsdb_attribute *attr,
902                                              const struct ldb_message_element *in,
903                                              TALLOC_CTX *mem_ctx,
904                                              struct drsuapi_DsReplicaAttribute *out)
905 {
906         uint32_t i;
907         DATA_BLOB *blobs;
908
909         if (attr->attributeID_id == 0xFFFFFFFF) {
910                 return WERR_FOOBAR;
911         }
912
913         switch (attr->attributeID_id) {
914         case DRSUAPI_ATTRIBUTE_objectClass:
915         case DRSUAPI_ATTRIBUTE_subClassOf:
916         case DRSUAPI_ATTRIBUTE_auxiliaryClass:
917         case DRSUAPI_ATTRIBUTE_systemPossSuperiors:
918         case DRSUAPI_ATTRIBUTE_possSuperiors:
919                 return _dsdb_syntax_OID_obj_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
920         case DRSUAPI_ATTRIBUTE_systemMustContain:
921         case DRSUAPI_ATTRIBUTE_systemMayContain:        
922         case DRSUAPI_ATTRIBUTE_mustContain:
923         case DRSUAPI_ATTRIBUTE_mayContain:
924                 return _dsdb_syntax_OID_attr_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
925         case DRSUAPI_ATTRIBUTE_governsID:
926         case DRSUAPI_ATTRIBUTE_attributeID:
927         case DRSUAPI_ATTRIBUTE_attributeSyntax:
928                 return _dsdb_syntax_OID_oid_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
929         }
930
931         out->attid                      = attr->attributeID_id;
932         out->value_ctr.num_values       = in->num_values;
933         out->value_ctr.values           = talloc_array(mem_ctx,
934                                                        struct drsuapi_DsAttributeValue,
935                                                        in->num_values);
936         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
937
938         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
939         W_ERROR_HAVE_NO_MEMORY(blobs);
940
941         for (i=0; i < in->num_values; i++) {
942                 uint32_t v;
943
944                 out->value_ctr.values[i].blob   = &blobs[i];
945
946                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
947                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
948
949                 v = strtol((const char *)in->values[i].data, NULL, 10);
950
951                 SIVAL(blobs[i].data, 0, v);
952         }
953
954         return WERR_OK;
955 }
956
957 static WERROR dsdb_syntax_UNICODE_drsuapi_to_ldb(struct ldb_context *ldb, 
958                                                  const struct dsdb_schema *schema,
959                                                  const struct dsdb_attribute *attr,
960                                                  const struct drsuapi_DsReplicaAttribute *in,
961                                                  TALLOC_CTX *mem_ctx,
962                                                  struct ldb_message_element *out)
963 {
964         uint32_t i;
965
966         out->flags      = 0;
967         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
968         W_ERROR_HAVE_NO_MEMORY(out->name);
969
970         out->num_values = in->value_ctr.num_values;
971         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
972         W_ERROR_HAVE_NO_MEMORY(out->values);
973
974         for (i=0; i < out->num_values; i++) {
975                 char *str;
976
977                 if (in->value_ctr.values[i].blob == NULL) {
978                         return WERR_FOOBAR;
979                 }
980
981                 if (in->value_ctr.values[i].blob->length == 0) {
982                         return WERR_FOOBAR;
983                 }
984
985                 if (!convert_string_talloc_convenience(out->values, 
986                                                 schema->iconv_convenience, 
987                                                                         CH_UTF16, CH_UNIX,
988                                             in->value_ctr.values[i].blob->data,
989                                             in->value_ctr.values[i].blob->length,
990                                             (void **)&str, NULL, false)) {
991                         return WERR_FOOBAR;
992                 }
993
994                 out->values[i] = data_blob_string_const(str);
995         }
996
997         return WERR_OK;
998 }
999
1000 static WERROR dsdb_syntax_UNICODE_ldb_to_drsuapi(struct ldb_context *ldb, 
1001                                                  const struct dsdb_schema *schema,
1002                                                  const struct dsdb_attribute *attr,
1003                                                  const struct ldb_message_element *in,
1004                                                  TALLOC_CTX *mem_ctx,
1005                                                  struct drsuapi_DsReplicaAttribute *out)
1006 {
1007         uint32_t i;
1008         DATA_BLOB *blobs;
1009
1010         if (attr->attributeID_id == 0xFFFFFFFF) {
1011                 return WERR_FOOBAR;
1012         }
1013
1014         out->attid                      = attr->attributeID_id;
1015         out->value_ctr.num_values       = in->num_values;
1016         out->value_ctr.values           = talloc_array(mem_ctx,
1017                                                        struct drsuapi_DsAttributeValue,
1018                                                        in->num_values);
1019         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1020
1021         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1022         W_ERROR_HAVE_NO_MEMORY(blobs);
1023
1024         for (i=0; i < in->num_values; i++) {
1025                 out->value_ctr.values[i].blob   = &blobs[i];
1026
1027                 if (!convert_string_talloc_convenience(blobs,
1028                         schema->iconv_convenience, CH_UNIX, CH_UTF16,
1029                         in->values[i].data, in->values[i].length,
1030                         (void **)&blobs[i].data, &blobs[i].length, false)) {
1031                                 return WERR_FOOBAR;
1032                 }
1033         }
1034
1035         return WERR_OK;
1036 }
1037
1038
1039 WERROR dsdb_syntax_one_DN_drsuapi_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, 
1040                                          const struct dsdb_syntax *syntax, 
1041                                          struct smb_iconv_convenience *iconv_convenience,
1042                                          const DATA_BLOB *in, DATA_BLOB *out)
1043 {
1044         struct drsuapi_DsReplicaObjectIdentifier3 id3;
1045         enum ndr_err_code ndr_err;
1046         DATA_BLOB guid_blob;
1047         struct ldb_dn *dn;
1048         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1049         int ret;
1050         NTSTATUS status;
1051
1052         if (!tmp_ctx) {
1053                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1054         }
1055         
1056         if (in == NULL) {
1057                 talloc_free(tmp_ctx);
1058                 return WERR_FOOBAR;
1059         }
1060         
1061         if (in->length == 0) {
1062                 talloc_free(tmp_ctx);
1063                 return WERR_FOOBAR;
1064         }
1065         
1066         
1067         /* windows sometimes sends an extra two pad bytes here */
1068         ndr_err = ndr_pull_struct_blob(in,
1069                                        tmp_ctx, iconv_convenience, &id3,
1070                                        (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3);
1071         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1072                 status = ndr_map_error2ntstatus(ndr_err);
1073                 talloc_free(tmp_ctx);
1074                 return ntstatus_to_werror(status);
1075         }
1076         
1077         dn = ldb_dn_new(tmp_ctx, ldb, id3.dn);
1078         if (!dn) {
1079                 talloc_free(tmp_ctx);
1080                 /* If this fails, it must be out of memory, as it does not do much parsing */
1081                 W_ERROR_HAVE_NO_MEMORY(dn);
1082         }
1083
1084         if (!GUID_all_zero(&id3.guid)) {
1085                 status = GUID_to_ndr_blob(&id3.guid, tmp_ctx, &guid_blob);
1086                 if (!NT_STATUS_IS_OK(status)) {
1087                         talloc_free(tmp_ctx);
1088                         return ntstatus_to_werror(status);
1089                 }
1090         
1091                 ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
1092                 if (ret != LDB_SUCCESS) {
1093                         talloc_free(tmp_ctx);
1094                         return WERR_FOOBAR;
1095                 }
1096                 talloc_free(guid_blob.data);
1097         }
1098         
1099         if (id3.__ndr_size_sid) {
1100                 DATA_BLOB sid_blob;
1101                 ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, iconv_convenience, &id3.sid,
1102                                                (ndr_push_flags_fn_t)ndr_push_dom_sid);
1103                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1104                         status = ndr_map_error2ntstatus(ndr_err);
1105                         talloc_free(tmp_ctx);
1106                         return ntstatus_to_werror(status);
1107                 }
1108                 
1109                 ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
1110                 if (ret != LDB_SUCCESS) {
1111                         talloc_free(tmp_ctx);
1112                         return WERR_FOOBAR;
1113                 }
1114         }
1115         
1116         *out = data_blob_string_const(ldb_dn_get_extended_linearized(mem_ctx, dn, 1));
1117         talloc_free(tmp_ctx);
1118         return WERR_OK;
1119 }
1120
1121 static WERROR dsdb_syntax_DN_drsuapi_to_ldb(struct ldb_context *ldb, 
1122                                             const struct dsdb_schema *schema,
1123                                             const struct dsdb_attribute *attr,
1124                                             const struct drsuapi_DsReplicaAttribute *in,
1125                                             TALLOC_CTX *mem_ctx,
1126                                             struct ldb_message_element *out)
1127 {
1128         uint32_t i;
1129
1130         out->flags      = 0;
1131         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1132         W_ERROR_HAVE_NO_MEMORY(out->name);
1133
1134         out->num_values = in->value_ctr.num_values;
1135         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1136         W_ERROR_HAVE_NO_MEMORY(out->values);
1137
1138         for (i=0; i < out->num_values; i++) {
1139                 WERROR status = dsdb_syntax_one_DN_drsuapi_to_ldb(out->values, ldb, attr->syntax, 
1140                                                                   schema->iconv_convenience, 
1141                                                                   in->value_ctr.values[i].blob, 
1142                                                                   &out->values[i]);
1143                 if (!W_ERROR_IS_OK(status)) {
1144                         return status;
1145                 }
1146                                                   
1147         }
1148
1149         return WERR_OK;
1150 }
1151
1152 static WERROR dsdb_syntax_DN_ldb_to_drsuapi(struct ldb_context *ldb, 
1153                                             const struct dsdb_schema *schema,
1154                                             const struct dsdb_attribute *attr,
1155                                             const struct ldb_message_element *in,
1156                                             TALLOC_CTX *mem_ctx,
1157                                             struct drsuapi_DsReplicaAttribute *out)
1158 {
1159         uint32_t i;
1160         DATA_BLOB *blobs;
1161
1162         if (attr->attributeID_id == 0xFFFFFFFF) {
1163                 return WERR_FOOBAR;
1164         }
1165
1166         out->attid                      = attr->attributeID_id;
1167         out->value_ctr.num_values       = in->num_values;
1168         out->value_ctr.values           = talloc_array(mem_ctx,
1169                                                        struct drsuapi_DsAttributeValue,
1170                                                        in->num_values);
1171         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1172
1173         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1174         W_ERROR_HAVE_NO_MEMORY(blobs);
1175
1176         for (i=0; i < in->num_values; i++) {
1177                 struct drsuapi_DsReplicaObjectIdentifier3 id3;
1178                 enum ndr_err_code ndr_err;
1179                 const DATA_BLOB *sid_blob;
1180                 struct ldb_dn *dn;
1181                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1182                 NTSTATUS status;
1183
1184                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1185
1186                 out->value_ctr.values[i].blob   = &blobs[i];
1187
1188                 dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &in->values[i]);
1189
1190                 W_ERROR_HAVE_NO_MEMORY(dn);
1191
1192                 ZERO_STRUCT(id3);
1193
1194                 status = dsdb_get_extended_dn_guid(dn, &id3.guid, "GUID");
1195                 if (!NT_STATUS_IS_OK(status) &&
1196                     !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1197                         talloc_free(tmp_ctx);
1198                         return ntstatus_to_werror(status);
1199                 }
1200
1201                 sid_blob = ldb_dn_get_extended_component(dn, "SID");
1202                 if (sid_blob) {
1203                         
1204                         ndr_err = ndr_pull_struct_blob_all(sid_blob, 
1205                                                            tmp_ctx, schema->iconv_convenience, &id3.sid,
1206                                                            (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1207                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1208                                 status = ndr_map_error2ntstatus(ndr_err);
1209                                 talloc_free(tmp_ctx);
1210                                 return ntstatus_to_werror(status);
1211                         }
1212                 }
1213
1214                 id3.dn = ldb_dn_get_linearized(dn);
1215
1216                 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
1217                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1218                         status = ndr_map_error2ntstatus(ndr_err);
1219                         talloc_free(tmp_ctx);
1220                         return ntstatus_to_werror(status);
1221                 }
1222                 talloc_free(tmp_ctx);
1223         }
1224
1225         return WERR_OK;
1226 }
1227
1228
1229
1230 static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(struct ldb_context *ldb, 
1231                                                    const struct dsdb_schema *schema,
1232                                                    const struct dsdb_attribute *attr,
1233                                                    const struct drsuapi_DsReplicaAttribute *in,
1234                                                    TALLOC_CTX *mem_ctx,
1235                                                    struct ldb_message_element *out)
1236 {
1237         uint32_t i;
1238         int ret;
1239
1240         out->flags      = 0;
1241         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1242         W_ERROR_HAVE_NO_MEMORY(out->name);
1243
1244         out->num_values = in->value_ctr.num_values;
1245         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1246         W_ERROR_HAVE_NO_MEMORY(out->values);
1247
1248         for (i=0; i < out->num_values; i++) {
1249                 struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
1250                 enum ndr_err_code ndr_err;
1251                 DATA_BLOB guid_blob;
1252                 struct ldb_dn *dn;
1253                 struct dsdb_dn *dsdb_dn;
1254                 NTSTATUS status;
1255                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1256                 if (!tmp_ctx) {
1257                         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1258                 }
1259
1260                 if (in->value_ctr.values[i].blob == NULL) {
1261                         talloc_free(tmp_ctx);
1262                         return WERR_FOOBAR;
1263                 }
1264
1265                 if (in->value_ctr.values[i].blob->length == 0) {
1266                         talloc_free(tmp_ctx);
1267                         return WERR_FOOBAR;
1268                 }
1269
1270                 
1271                 /* windows sometimes sends an extra two pad bytes here */
1272                 ndr_err = ndr_pull_struct_blob(in->value_ctr.values[i].blob,
1273                                                tmp_ctx, schema->iconv_convenience, &id3,
1274                                                (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3Binary);
1275                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1276                         status = ndr_map_error2ntstatus(ndr_err);
1277                         talloc_free(tmp_ctx);
1278                         return ntstatus_to_werror(status);
1279                 }
1280
1281                 dn = ldb_dn_new(tmp_ctx, ldb, id3.dn);
1282                 if (!dn) {
1283                         talloc_free(tmp_ctx);
1284                         /* If this fails, it must be out of memory, as it does not do much parsing */
1285                         W_ERROR_HAVE_NO_MEMORY(dn);
1286                 }
1287
1288                 status = GUID_to_ndr_blob(&id3.guid, tmp_ctx, &guid_blob);
1289                 if (!NT_STATUS_IS_OK(status)) {
1290                         talloc_free(tmp_ctx);
1291                         return ntstatus_to_werror(status);
1292                 }
1293
1294                 ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
1295                 if (ret != LDB_SUCCESS) {
1296                         talloc_free(tmp_ctx);
1297                         return WERR_FOOBAR;
1298                 }
1299
1300                 talloc_free(guid_blob.data);
1301
1302                 if (id3.__ndr_size_sid) {
1303                         DATA_BLOB sid_blob;
1304                         ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, schema->iconv_convenience, &id3.sid,
1305                                                        (ndr_push_flags_fn_t)ndr_push_dom_sid);
1306                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1307                                 status = ndr_map_error2ntstatus(ndr_err);
1308                                 talloc_free(tmp_ctx);
1309                                 return ntstatus_to_werror(status);
1310                         }
1311
1312                         ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
1313                         if (ret != LDB_SUCCESS) {
1314                                 talloc_free(tmp_ctx);
1315                                 return WERR_FOOBAR;
1316                         }
1317                 }
1318
1319                 /* set binary stuff */
1320                 dsdb_dn = dsdb_dn_construct(tmp_ctx, dn, id3.binary, attr->syntax->ldap_oid);
1321                 if (!dsdb_dn) {
1322                         /* If this fails, it must be out of memory, we know the ldap_oid is valid */
1323                         talloc_free(tmp_ctx);
1324                         W_ERROR_HAVE_NO_MEMORY(dsdb_dn);
1325                 }
1326                 out->values[i] = data_blob_string_const(dsdb_dn_get_extended_linearized(out->values, dsdb_dn, 1));
1327                 talloc_free(tmp_ctx);
1328         }
1329
1330         return WERR_OK;
1331 }
1332
1333 static WERROR dsdb_syntax_DN_BINARY_ldb_to_drsuapi(struct ldb_context *ldb, 
1334                                                    const struct dsdb_schema *schema,
1335                                                    const struct dsdb_attribute *attr,
1336                                                    const struct ldb_message_element *in,
1337                                                    TALLOC_CTX *mem_ctx,
1338                                                    struct drsuapi_DsReplicaAttribute *out)
1339 {
1340         uint32_t i;
1341         DATA_BLOB *blobs;
1342
1343         if (attr->attributeID_id == 0xFFFFFFFF) {
1344                 return WERR_FOOBAR;
1345         }
1346
1347         out->attid                      = attr->attributeID_id;
1348         out->value_ctr.num_values       = in->num_values;
1349         out->value_ctr.values           = talloc_array(mem_ctx,
1350                                                        struct drsuapi_DsAttributeValue,
1351                                                        in->num_values);
1352         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1353
1354         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1355         W_ERROR_HAVE_NO_MEMORY(blobs);
1356
1357         for (i=0; i < in->num_values; i++) {
1358                 struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
1359                 enum ndr_err_code ndr_err;
1360                 const DATA_BLOB *sid_blob;
1361                 struct dsdb_dn *dsdb_dn;
1362                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1363                 NTSTATUS status;
1364
1365                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1366
1367                 out->value_ctr.values[i].blob   = &blobs[i];
1368
1369                 dsdb_dn = dsdb_dn_parse(tmp_ctx, ldb, &in->values[i], attr->syntax->ldap_oid);
1370
1371                 if (!dsdb_dn) {
1372                         talloc_free(tmp_ctx);
1373                         return ntstatus_to_werror(NT_STATUS_INVALID_PARAMETER);
1374                 }
1375
1376                 ZERO_STRUCT(id3);
1377
1378                 status = dsdb_get_extended_dn_guid(dsdb_dn->dn, &id3.guid, "GUID");
1379                 if (!NT_STATUS_IS_OK(status) &&
1380                     !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1381                         talloc_free(tmp_ctx);
1382                         return ntstatus_to_werror(status);
1383                 }
1384
1385                 sid_blob = ldb_dn_get_extended_component(dsdb_dn->dn, "SID");
1386                 if (sid_blob) {
1387                         
1388                         ndr_err = ndr_pull_struct_blob_all(sid_blob, 
1389                                                            tmp_ctx, schema->iconv_convenience, &id3.sid,
1390                                                            (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1391                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1392                                 status = ndr_map_error2ntstatus(ndr_err);
1393                                 talloc_free(tmp_ctx);
1394                                 return ntstatus_to_werror(status);
1395                         }
1396                 }
1397
1398                 id3.dn = ldb_dn_get_linearized(dsdb_dn->dn);
1399
1400                 /* get binary stuff */
1401                 id3.binary = dsdb_dn->extra_part;
1402
1403                 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3Binary);
1404                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1405                         status = ndr_map_error2ntstatus(ndr_err);
1406                         talloc_free(tmp_ctx);
1407                         return ntstatus_to_werror(status);
1408                 }
1409                 talloc_free(tmp_ctx);
1410         }
1411
1412         return WERR_OK;
1413 }
1414
1415
1416
1417 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb(struct ldb_context *ldb, 
1418                                                               const struct dsdb_schema *schema,
1419                                                               const struct dsdb_attribute *attr,
1420                                                               const struct drsuapi_DsReplicaAttribute *in,
1421                                                               TALLOC_CTX *mem_ctx,
1422                                                               struct ldb_message_element *out)
1423 {
1424         uint32_t i;
1425
1426         out->flags      = 0;
1427         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1428         W_ERROR_HAVE_NO_MEMORY(out->name);
1429
1430         out->num_values = in->value_ctr.num_values;
1431         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1432         W_ERROR_HAVE_NO_MEMORY(out->values);
1433
1434         for (i=0; i < out->num_values; i++) {
1435                 uint32_t len;
1436                 char *str;
1437
1438                 if (in->value_ctr.values[i].blob == NULL) {
1439                         return WERR_FOOBAR;
1440                 }
1441
1442                 if (in->value_ctr.values[i].blob->length < 4) {
1443                         return WERR_FOOBAR;
1444                 }
1445
1446                 len = IVAL(in->value_ctr.values[i].blob->data, 0);
1447
1448                 if (len != in->value_ctr.values[i].blob->length) {
1449                         return WERR_FOOBAR;
1450                 }
1451
1452                 if (!convert_string_talloc_convenience(out->values, schema->iconv_convenience, CH_UTF16, CH_UNIX,
1453                                             in->value_ctr.values[i].blob->data+4,
1454                                             in->value_ctr.values[i].blob->length-4,
1455                                             (void **)&str, NULL, false)) {
1456                         return WERR_FOOBAR;
1457                 }
1458
1459                 out->values[i] = data_blob_string_const(str);
1460         }
1461
1462         return WERR_OK;
1463 }
1464
1465 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi(struct ldb_context *ldb, 
1466                                                               const struct dsdb_schema *schema,
1467                                                               const struct dsdb_attribute *attr,
1468                                                               const struct ldb_message_element *in,
1469                                                               TALLOC_CTX *mem_ctx,
1470                                                               struct drsuapi_DsReplicaAttribute *out)
1471 {
1472         uint32_t i;
1473         DATA_BLOB *blobs;
1474
1475         if (attr->attributeID_id == 0xFFFFFFFF) {
1476                 return WERR_FOOBAR;
1477         }
1478
1479         out->attid                      = attr->attributeID_id;
1480         out->value_ctr.num_values       = in->num_values;
1481         out->value_ctr.values           = talloc_array(mem_ctx,
1482                                                        struct drsuapi_DsAttributeValue,
1483                                                        in->num_values);
1484         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1485
1486         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1487         W_ERROR_HAVE_NO_MEMORY(blobs);
1488
1489         for (i=0; i < in->num_values; i++) {
1490                 uint8_t *data;
1491                 size_t ret;
1492
1493                 out->value_ctr.values[i].blob   = &blobs[i];
1494
1495                 if (!convert_string_talloc_convenience(blobs, schema->iconv_convenience, CH_UNIX, CH_UTF16,
1496                                             in->values[i].data,
1497                                             in->values[i].length,
1498                                             (void **)&data, &ret, false)) {
1499                         return WERR_FOOBAR;
1500                 }
1501
1502                 blobs[i] = data_blob_talloc(blobs, NULL, 4 + ret);
1503                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1504
1505                 SIVAL(blobs[i].data, 0, 4 + ret);
1506
1507                 if (ret > 0) {
1508                         memcpy(blobs[i].data + 4, data, ret);
1509                         talloc_free(data);
1510                 }
1511         }
1512
1513         return WERR_OK;
1514 }
1515
1516 #define OMOBJECTCLASS(val) { .length = sizeof(val) - 1, .data = discard_const_p(uint8_t, val) }
1517
1518 static const struct dsdb_syntax dsdb_syntaxes[] = {
1519         {
1520                 .name                   = "Boolean",
1521                 .ldap_oid               = LDB_SYNTAX_BOOLEAN,
1522                 .oMSyntax               = 1,
1523                 .attributeSyntax_oid    = "2.5.5.8",
1524                 .drsuapi_to_ldb         = dsdb_syntax_BOOL_drsuapi_to_ldb,
1525                 .ldb_to_drsuapi         = dsdb_syntax_BOOL_ldb_to_drsuapi,
1526                 .equality               = "booleanMatch",
1527                 .comment                = "Boolean" 
1528         },{
1529                 .name                   = "Integer",
1530                 .ldap_oid               = LDB_SYNTAX_INTEGER,
1531                 .oMSyntax               = 2,
1532                 .attributeSyntax_oid    = "2.5.5.9",
1533                 .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
1534                 .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
1535                 .equality               = "integerMatch",
1536                 .comment                = "Integer",
1537                 .ldb_syntax             = LDB_SYNTAX_SAMBA_INT32
1538         },{
1539                 .name                   = "String(Octet)",
1540                 .ldap_oid               = LDB_SYNTAX_OCTET_STRING,
1541                 .oMSyntax               = 4,
1542                 .attributeSyntax_oid    = "2.5.5.10",
1543                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1544                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1545                 .equality               = "octetStringMatch",
1546                 .comment                = "Octet String",
1547         },{
1548                 .name                   = "String(Sid)",
1549                 .ldap_oid               = LDB_SYNTAX_OCTET_STRING,
1550                 .oMSyntax               = 4,
1551                 .attributeSyntax_oid    = "2.5.5.17",
1552                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1553                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1554                 .equality               = "octetStringMatch",
1555                 .comment                = "Octet String - Security Identifier (SID)",
1556                 .ldb_syntax             = LDB_SYNTAX_SAMBA_SID
1557         },{
1558                 .name                   = "String(Object-Identifier)",
1559                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.38",
1560                 .oMSyntax               = 6,
1561                 .attributeSyntax_oid    = "2.5.5.2",
1562                 .drsuapi_to_ldb         = dsdb_syntax_OID_drsuapi_to_ldb,
1563                 .ldb_to_drsuapi         = dsdb_syntax_OID_ldb_to_drsuapi,
1564                 .equality               = "caseIgnoreMatch", /* Would use "objectIdentifierMatch" but most are ldap attribute/class names */
1565                 .comment                = "OID String",
1566                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING
1567         },{
1568                 .name                   = "Enumeration",
1569                 .ldap_oid               = LDB_SYNTAX_INTEGER,
1570                 .oMSyntax               = 10,
1571                 .attributeSyntax_oid    = "2.5.5.9",
1572                 .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
1573                 .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
1574                 .ldb_syntax             = LDB_SYNTAX_SAMBA_INT32
1575         },{
1576         /* not used in w2k3 forest */
1577                 .name                   = "String(Numeric)",
1578                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.36",
1579                 .oMSyntax               = 18,
1580                 .attributeSyntax_oid    = "2.5.5.6",
1581                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1582                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1583                 .equality               = "numericStringMatch",
1584                 .substring              = "numericStringSubstringsMatch",
1585                 .comment                = "Numeric String",
1586                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1587         },{
1588                 .name                   = "String(Printable)",
1589                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.44",
1590                 .oMSyntax               = 19,
1591                 .attributeSyntax_oid    = "2.5.5.5",
1592                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1593                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1594                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
1595         },{
1596                 .name                   = "String(Teletex)",
1597                 .ldap_oid               = "1.2.840.113556.1.4.905",
1598                 .oMSyntax               = 20,
1599                 .attributeSyntax_oid    = "2.5.5.4",
1600                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1601                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1602                 .equality               = "caseIgnoreMatch",
1603                 .substring              = "caseIgnoreSubstringsMatch",
1604                 .comment                = "Case Insensitive String",
1605                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1606         },{
1607                 .name                   = "String(IA5)",
1608                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.26",
1609                 .oMSyntax               = 22,
1610                 .attributeSyntax_oid    = "2.5.5.5",
1611                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1612                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1613                 .equality               = "caseExactIA5Match",
1614                 .comment                = "Printable String",
1615                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
1616         },{
1617                 .name                   = "String(UTC-Time)",
1618                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.53",
1619                 .oMSyntax               = 23,
1620                 .attributeSyntax_oid    = "2.5.5.11",
1621                 .drsuapi_to_ldb         = dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb,
1622                 .ldb_to_drsuapi         = dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi,
1623                 .equality               = "generalizedTimeMatch",
1624                 .comment                = "UTC Time",
1625         },{
1626                 .name                   = "String(Generalized-Time)",
1627                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.24",
1628                 .oMSyntax               = 24,
1629                 .attributeSyntax_oid    = "2.5.5.11",
1630                 .drsuapi_to_ldb         = dsdb_syntax_NTTIME_drsuapi_to_ldb,
1631                 .ldb_to_drsuapi         = dsdb_syntax_NTTIME_ldb_to_drsuapi,
1632                 .equality               = "generalizedTimeMatch",
1633                 .comment                = "Generalized Time",
1634                 .ldb_syntax             = LDB_SYNTAX_UTC_TIME,
1635         },{
1636         /* not used in w2k3 schema */
1637                 .name                   = "String(Case Sensitive)",
1638                 .ldap_oid               = "1.2.840.113556.1.4.1362",
1639                 .oMSyntax               = 27,
1640                 .attributeSyntax_oid    = "2.5.5.3",
1641                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1642                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1643         },{
1644                 .name                   = "String(Unicode)",
1645                 .ldap_oid               = LDB_SYNTAX_DIRECTORY_STRING,
1646                 .oMSyntax               = 64,
1647                 .attributeSyntax_oid    = "2.5.5.12",
1648                 .drsuapi_to_ldb         = dsdb_syntax_UNICODE_drsuapi_to_ldb,
1649                 .ldb_to_drsuapi         = dsdb_syntax_UNICODE_ldb_to_drsuapi,
1650                 .equality               = "caseIgnoreMatch",
1651                 .substring              = "caseIgnoreSubstringsMatch",
1652                 .comment                = "Directory String",
1653         },{
1654                 .name                   = "Interval/LargeInteger",
1655                 .ldap_oid               = "1.2.840.113556.1.4.906",
1656                 .oMSyntax               = 65,
1657                 .attributeSyntax_oid    = "2.5.5.16",
1658                 .drsuapi_to_ldb         = dsdb_syntax_INT64_drsuapi_to_ldb,
1659                 .ldb_to_drsuapi         = dsdb_syntax_INT64_ldb_to_drsuapi,
1660                 .equality               = "integerMatch",
1661                 .comment                = "Large Integer",
1662                 .ldb_syntax             = LDB_SYNTAX_INTEGER,
1663         },{
1664                 .name                   = "String(NT-Sec-Desc)",
1665                 .ldap_oid               = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1666                 .oMSyntax               = 66,
1667                 .attributeSyntax_oid    = "2.5.5.15",
1668                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1669                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1670         },{
1671                 .name                   = "Object(DS-DN)",
1672                 .ldap_oid               = LDB_SYNTAX_DN,
1673                 .oMSyntax               = 127,
1674                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x4a"),
1675                 .attributeSyntax_oid    = "2.5.5.1",
1676                 .drsuapi_to_ldb         = dsdb_syntax_DN_drsuapi_to_ldb,
1677                 .ldb_to_drsuapi         = dsdb_syntax_DN_ldb_to_drsuapi,
1678                 .equality               = "distinguishedNameMatch",
1679                 .comment                = "Object(DS-DN) == a DN",
1680         },{
1681                 .name                   = "Object(DN-Binary)",
1682                 .ldap_oid               = DSDB_SYNTAX_BINARY_DN,
1683                 .oMSyntax               = 127,
1684                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0b"),
1685                 .attributeSyntax_oid    = "2.5.5.7",
1686                 .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
1687                 .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
1688                 .equality               = "octetStringMatch",
1689                 .comment                = "OctetString: Binary+DN",
1690         },{
1691         /* not used in w2k3 schema, but used in Exchange schema*/
1692                 .name                   = "Object(OR-Name)",
1693                 .ldap_oid               = DSDB_SYNTAX_OR_NAME,
1694                 .oMSyntax               = 127,
1695                 .oMObjectClass          = OMOBJECTCLASS("\x56\x06\x01\x02\x05\x0b\x1D"),
1696                 .attributeSyntax_oid    = "2.5.5.7",
1697                 .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
1698                 .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
1699                 .equality               = "caseIgnoreMatch",
1700                 .ldb_syntax             = LDB_SYNTAX_DN,
1701         },{
1702         /* 
1703          * TODO: verify if DATA_BLOB is correct here...!
1704          *
1705          *       repsFrom and repsTo are the only attributes using
1706          *       this attribute syntax, but they're not replicated... 
1707          */
1708                 .name                   = "Object(Replica-Link)",
1709                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.40",
1710                 .oMSyntax               = 127,
1711                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x06"),
1712                 .attributeSyntax_oid    = "2.5.5.10",
1713                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1714                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1715         },{
1716                 .name                   = "Object(Presentation-Address)",
1717                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.43",
1718                 .oMSyntax               = 127,
1719                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x5c"),
1720                 .attributeSyntax_oid    = "2.5.5.13",
1721                 .drsuapi_to_ldb         = dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb,
1722                 .ldb_to_drsuapi         = dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi,
1723                 .comment                = "Presentation Address",
1724                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1725         },{
1726         /* not used in w2k3 schema */
1727                 .name                   = "Object(Access-Point)",
1728                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.2",
1729                 .oMSyntax               = 127,
1730                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x3e"),
1731                 .attributeSyntax_oid    = "2.5.5.14",
1732                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1733                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1734                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1735         },{
1736         /* not used in w2k3 schema */
1737                 .name                   = "Object(DN-String)",
1738                 .ldap_oid               = DSDB_SYNTAX_STRING_DN,
1739                 .oMSyntax               = 127,
1740                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0c"),
1741                 .attributeSyntax_oid    = "2.5.5.14",
1742                 .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
1743                 .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
1744                 .equality               = "octetStringMatch",
1745                 .comment                = "OctetString: String+DN",
1746         }
1747 };
1748
1749 const struct dsdb_syntax *find_syntax_map_by_ad_oid(const char *ad_oid) 
1750 {
1751         int i;
1752         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1753                 if (strcasecmp(ad_oid, dsdb_syntaxes[i].attributeSyntax_oid) == 0) {
1754                         return &dsdb_syntaxes[i];
1755                 }
1756         }
1757         return NULL;
1758 }
1759
1760 const struct dsdb_syntax *find_syntax_map_by_ad_syntax(int oMSyntax) 
1761 {
1762         int i;
1763         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1764                 if (oMSyntax == dsdb_syntaxes[i].oMSyntax) {
1765                         return &dsdb_syntaxes[i];
1766                 }
1767         }
1768         return NULL;
1769 }
1770
1771 const struct dsdb_syntax *find_syntax_map_by_standard_oid(const char *standard_oid) 
1772 {
1773         int i;
1774         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1775                 if (strcasecmp(standard_oid, dsdb_syntaxes[i].ldap_oid) == 0) {
1776                         return &dsdb_syntaxes[i];
1777                 }
1778         }
1779         return NULL;
1780 }
1781 const struct dsdb_syntax *dsdb_syntax_for_attribute(const struct dsdb_attribute *attr)
1782 {
1783         uint32_t i;
1784
1785         for (i=0; i < ARRAY_SIZE(dsdb_syntaxes); i++) {
1786                 if (attr->oMSyntax != dsdb_syntaxes[i].oMSyntax) continue;
1787
1788                 if (attr->oMObjectClass.length != dsdb_syntaxes[i].oMObjectClass.length) continue;
1789
1790                 if (attr->oMObjectClass.length) {
1791                         int ret;
1792                         ret = memcmp(attr->oMObjectClass.data,
1793                                      dsdb_syntaxes[i].oMObjectClass.data,
1794                                      attr->oMObjectClass.length);
1795                         if (ret != 0) continue;
1796                 }
1797
1798                 if (strcmp(attr->attributeSyntax_oid, dsdb_syntaxes[i].attributeSyntax_oid) != 0) continue;
1799
1800                 return &dsdb_syntaxes[i];
1801         }
1802
1803         return NULL;
1804 }
1805
1806 WERROR dsdb_attribute_drsuapi_to_ldb(struct ldb_context *ldb, 
1807                                      const struct dsdb_schema *schema,
1808                                      const struct drsuapi_DsReplicaAttribute *in,
1809                                      TALLOC_CTX *mem_ctx,
1810                                      struct ldb_message_element *out)
1811 {
1812         const struct dsdb_attribute *sa;
1813
1814         sa = dsdb_attribute_by_attributeID_id(schema, in->attid);
1815         if (!sa) {
1816                 return WERR_FOOBAR;
1817         }
1818
1819         return sa->syntax->drsuapi_to_ldb(ldb, schema, sa, in, mem_ctx, out);
1820 }
1821
1822 WERROR dsdb_attribute_ldb_to_drsuapi(struct ldb_context *ldb, 
1823                                      const struct dsdb_schema *schema,
1824                                      const struct ldb_message_element *in,
1825                                      TALLOC_CTX *mem_ctx,
1826                                      struct drsuapi_DsReplicaAttribute *out)
1827 {
1828         const struct dsdb_attribute *sa;
1829
1830         sa = dsdb_attribute_by_lDAPDisplayName(schema, in->name);
1831         if (!sa) {
1832                 return WERR_FOOBAR;
1833         }
1834
1835         return sa->syntax->ldb_to_drsuapi(ldb, schema, sa, in, mem_ctx, out);
1836 }