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