s4:dsdb: correctly implement _dsdb_syntax_OID_oid_ldb_to_drsuapi()
[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
492                 out->value_ctr.values[i].blob   = &blobs[i];
493
494                 blobs[i] = data_blob_talloc(blobs, NULL, 8);
495                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
496
497                 t = ldb_string_to_time((const char *)in->values[i].data);
498                 unix_to_nt_time(&v, t);
499                 v /= 10000000;
500
501                 SBVAL(blobs[i].data, 0, v);
502         }
503
504         return WERR_OK;
505 }
506
507 static WERROR dsdb_syntax_DATA_BLOB_drsuapi_to_ldb(struct ldb_context *ldb, 
508                                                    const struct dsdb_schema *schema,
509                                                    const struct dsdb_attribute *attr,
510                                                    const struct drsuapi_DsReplicaAttribute *in,
511                                                    TALLOC_CTX *mem_ctx,
512                                                    struct ldb_message_element *out)
513 {
514         uint32_t i;
515
516         out->flags      = 0;
517         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
518         W_ERROR_HAVE_NO_MEMORY(out->name);
519
520         out->num_values = in->value_ctr.num_values;
521         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
522         W_ERROR_HAVE_NO_MEMORY(out->values);
523
524         for (i=0; i < out->num_values; i++) {
525                 if (in->value_ctr.values[i].blob == NULL) {
526                         return WERR_FOOBAR;
527                 }
528
529                 if (in->value_ctr.values[i].blob->length == 0) {
530                         return WERR_FOOBAR;
531                 }
532
533                 out->values[i] = data_blob_dup_talloc(out->values,
534                                                       in->value_ctr.values[i].blob);
535                 W_ERROR_HAVE_NO_MEMORY(out->values[i].data);
536         }
537
538         return WERR_OK;
539 }
540
541 static WERROR dsdb_syntax_DATA_BLOB_ldb_to_drsuapi(struct ldb_context *ldb, 
542                                                    const struct dsdb_schema *schema,
543                                                    const struct dsdb_attribute *attr,
544                                                    const struct ldb_message_element *in,
545                                                    TALLOC_CTX *mem_ctx,
546                                                    struct drsuapi_DsReplicaAttribute *out)
547 {
548         uint32_t i;
549         DATA_BLOB *blobs;
550
551         if (attr->attributeID_id == 0xFFFFFFFF) {
552                 return WERR_FOOBAR;
553         }
554
555         out->attid                      = attr->attributeID_id;
556         out->value_ctr.num_values       = in->num_values;
557         out->value_ctr.values           = talloc_array(mem_ctx,
558                                                        struct drsuapi_DsAttributeValue,
559                                                        in->num_values);
560         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
561
562         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
563         W_ERROR_HAVE_NO_MEMORY(blobs);
564
565         for (i=0; i < in->num_values; i++) {
566                 out->value_ctr.values[i].blob   = &blobs[i];
567
568                 blobs[i] = data_blob_dup_talloc(blobs, &in->values[i]);
569                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
570         }
571
572         return WERR_OK;
573 }
574
575 static WERROR _dsdb_syntax_OID_obj_drsuapi_to_ldb(struct ldb_context *ldb, 
576                                                   const struct dsdb_schema *schema,
577                                                   const struct dsdb_attribute *attr,
578                                                   const struct drsuapi_DsReplicaAttribute *in,
579                                                   TALLOC_CTX *mem_ctx,
580                                                   struct ldb_message_element *out)
581 {
582         uint32_t i;
583
584         out->flags      = 0;
585         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
586         W_ERROR_HAVE_NO_MEMORY(out->name);
587
588         out->num_values = in->value_ctr.num_values;
589         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
590         W_ERROR_HAVE_NO_MEMORY(out->values);
591
592         for (i=0; i < out->num_values; i++) {
593                 uint32_t v;
594                 const struct dsdb_class *c;
595                 const char *str;
596
597                 if (in->value_ctr.values[i].blob == NULL) {
598                         return WERR_FOOBAR;
599                 }
600
601                 if (in->value_ctr.values[i].blob->length != 4) {
602                         return WERR_FOOBAR;
603                 }
604
605                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
606
607                 c = dsdb_class_by_governsID_id(schema, v);
608                 if (!c) {
609                         return WERR_FOOBAR;
610                 }
611
612                 str = talloc_strdup(out->values, c->lDAPDisplayName);
613                 W_ERROR_HAVE_NO_MEMORY(str);
614
615                 /* the values need to be reversed */
616                 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
617         }
618
619         return WERR_OK;
620 }
621
622 static WERROR _dsdb_syntax_OID_oid_drsuapi_to_ldb(struct ldb_context *ldb, 
623                                                   const struct dsdb_schema *schema,
624                                                   const struct dsdb_attribute *attr,
625                                                   const struct drsuapi_DsReplicaAttribute *in,
626                                                   TALLOC_CTX *mem_ctx,
627                                                   struct ldb_message_element *out)
628 {
629         uint32_t i;
630
631         out->flags      = 0;
632         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
633         W_ERROR_HAVE_NO_MEMORY(out->name);
634
635         out->num_values = in->value_ctr.num_values;
636         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
637         W_ERROR_HAVE_NO_MEMORY(out->values);
638
639         for (i=0; i < out->num_values; i++) {
640                 uint32_t v;
641                 WERROR status;
642                 const char *str;
643
644                 if (in->value_ctr.values[i].blob == NULL) {
645                         return WERR_FOOBAR;
646                 }
647
648                 if (in->value_ctr.values[i].blob->length != 4) {
649                         return WERR_FOOBAR;
650                 }
651
652                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
653
654                 status = dsdb_map_int2oid(schema, v, out->values, &str);
655                 W_ERROR_NOT_OK_RETURN(status);
656
657                 out->values[i] = data_blob_string_const(str);
658         }
659
660         return WERR_OK;
661 }
662
663 static WERROR _dsdb_syntax_OID_obj_ldb_to_drsuapi(struct ldb_context *ldb,
664                                                   const struct dsdb_schema *schema,
665                                                   const struct dsdb_attribute *attr,
666                                                   const struct ldb_message_element *in,
667                                                   TALLOC_CTX *mem_ctx,
668                                                   struct drsuapi_DsReplicaAttribute *out)
669 {
670         uint32_t i;
671         DATA_BLOB *blobs;
672
673         out->attid= attr->attributeID_id;
674         out->value_ctr.num_values= in->num_values;
675         out->value_ctr.values= talloc_array(mem_ctx,
676                                             struct drsuapi_DsAttributeValue,
677                                             in->num_values);
678         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
679
680         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
681         W_ERROR_HAVE_NO_MEMORY(blobs);
682
683         for (i=0; i < in->num_values; i++) {
684                 const struct dsdb_class *obj_class;
685
686                 out->value_ctr.values[i].blob= &blobs[i];
687
688                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
689                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
690
691                 obj_class = dsdb_class_by_lDAPDisplayName(schema, (const char *)in->values[i].data);
692                 if (!obj_class) {
693                         return WERR_FOOBAR;
694                 }
695                 SIVAL(blobs[i].data, 0, obj_class->governsID_id);
696         }
697
698
699         return WERR_OK;
700 }
701
702 static WERROR _dsdb_syntax_OID_oid_ldb_to_drsuapi(struct ldb_context *ldb,
703                                                   const struct dsdb_schema *schema,
704                                                   const struct dsdb_attribute *attr,
705                                                   const struct ldb_message_element *in,
706                                                   TALLOC_CTX *mem_ctx,
707                                                   struct drsuapi_DsReplicaAttribute *out)
708 {
709         uint32_t i;
710         DATA_BLOB *blobs;
711
712         out->attid= attr->attributeID_id;
713         out->value_ctr.num_values= in->num_values;
714         out->value_ctr.values= talloc_array(mem_ctx,
715                                             struct drsuapi_DsAttributeValue,
716                                             in->num_values);
717         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
718
719         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
720         W_ERROR_HAVE_NO_MEMORY(blobs);
721
722         for (i=0; i < in->num_values; i++) {
723                 uint32_t v;
724                 WERROR status;
725
726                 out->value_ctr.values[i].blob= &blobs[i];
727
728                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
729                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
730
731                 status = dsdb_map_oid2int(schema,
732                                           (const char *)in->values[i].data,
733                                           &v);
734                 W_ERROR_NOT_OK_RETURN(status);
735
736                 SIVAL(blobs[i].data, 0, v);
737         }
738
739         return WERR_OK;
740 }
741
742 static WERROR dsdb_syntax_OID_drsuapi_to_ldb(struct ldb_context *ldb, 
743                                              const struct dsdb_schema *schema,
744                                              const struct dsdb_attribute *attr,
745                                              const struct drsuapi_DsReplicaAttribute *in,
746                                              TALLOC_CTX *mem_ctx,
747                                              struct ldb_message_element *out)
748 {
749         uint32_t i;
750
751         switch (attr->attributeID_id) {
752         case DRSUAPI_ATTRIBUTE_objectClass:
753                 return _dsdb_syntax_OID_obj_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
754         case DRSUAPI_ATTRIBUTE_governsID:
755         case DRSUAPI_ATTRIBUTE_attributeID:
756         case DRSUAPI_ATTRIBUTE_attributeSyntax:
757                 return _dsdb_syntax_OID_oid_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
758         }
759
760         out->flags      = 0;
761         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
762         W_ERROR_HAVE_NO_MEMORY(out->name);
763
764         out->num_values = in->value_ctr.num_values;
765         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
766         W_ERROR_HAVE_NO_MEMORY(out->values);
767
768         for (i=0; i < out->num_values; i++) {
769                 uint32_t v;
770                 const char *name;
771                 char *str;
772
773                 if (in->value_ctr.values[i].blob == NULL) {
774                         return WERR_FOOBAR;
775                 }
776
777                 if (in->value_ctr.values[i].blob->length != 4) {
778                         return WERR_FOOBAR;
779                 }
780
781                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
782
783                 name = dsdb_lDAPDisplayName_by_id(schema, v);
784                 if (!name) {
785                         return WERR_FOOBAR;
786                 }
787
788                 str = talloc_strdup(out->values, name);
789                 W_ERROR_HAVE_NO_MEMORY(str);
790
791                 out->values[i] = data_blob_string_const(str);
792         }
793
794         return WERR_OK;
795 }
796
797 static WERROR dsdb_syntax_OID_ldb_to_drsuapi(struct ldb_context *ldb, 
798                                              const struct dsdb_schema *schema,
799                                              const struct dsdb_attribute *attr,
800                                              const struct ldb_message_element *in,
801                                              TALLOC_CTX *mem_ctx,
802                                              struct drsuapi_DsReplicaAttribute *out)
803 {
804         uint32_t i;
805         DATA_BLOB *blobs;
806
807         if (attr->attributeID_id == 0xFFFFFFFF) {
808                 return WERR_FOOBAR;
809         }
810
811         switch (attr->attributeID_id) {
812         case DRSUAPI_ATTRIBUTE_objectClass:
813                 return _dsdb_syntax_OID_obj_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
814         case DRSUAPI_ATTRIBUTE_governsID:
815         case DRSUAPI_ATTRIBUTE_attributeID:
816         case DRSUAPI_ATTRIBUTE_attributeSyntax:
817                 return _dsdb_syntax_OID_oid_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
818         }
819
820         out->attid                      = attr->attributeID_id;
821         out->value_ctr.num_values       = in->num_values;
822         out->value_ctr.values           = talloc_array(mem_ctx,
823                                                        struct drsuapi_DsAttributeValue,
824                                                        in->num_values);
825         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
826
827         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
828         W_ERROR_HAVE_NO_MEMORY(blobs);
829
830         for (i=0; i < in->num_values; i++) {
831                 uint32_t v;
832
833                 out->value_ctr.values[i].blob   = &blobs[i];
834
835                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
836                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
837
838                 v = strtol((const char *)in->values[i].data, NULL, 10);
839
840                 SIVAL(blobs[i].data, 0, v);
841         }
842
843         return WERR_OK;
844 }
845
846 static WERROR dsdb_syntax_UNICODE_drsuapi_to_ldb(struct ldb_context *ldb, 
847                                                  const struct dsdb_schema *schema,
848                                                  const struct dsdb_attribute *attr,
849                                                  const struct drsuapi_DsReplicaAttribute *in,
850                                                  TALLOC_CTX *mem_ctx,
851                                                  struct ldb_message_element *out)
852 {
853         uint32_t i;
854
855         out->flags      = 0;
856         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
857         W_ERROR_HAVE_NO_MEMORY(out->name);
858
859         out->num_values = in->value_ctr.num_values;
860         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
861         W_ERROR_HAVE_NO_MEMORY(out->values);
862
863         for (i=0; i < out->num_values; i++) {
864                 char *str;
865
866                 if (in->value_ctr.values[i].blob == NULL) {
867                         return WERR_FOOBAR;
868                 }
869
870                 if (in->value_ctr.values[i].blob->length == 0) {
871                         return WERR_FOOBAR;
872                 }
873
874                 if (!convert_string_talloc_convenience(out->values, 
875                                                 schema->iconv_convenience, 
876                                                                         CH_UTF16, CH_UNIX,
877                                             in->value_ctr.values[i].blob->data,
878                                             in->value_ctr.values[i].blob->length,
879                                             (void **)&str, NULL, false)) {
880                         return WERR_FOOBAR;
881                 }
882
883                 out->values[i] = data_blob_string_const(str);
884         }
885
886         return WERR_OK;
887 }
888
889 static WERROR dsdb_syntax_UNICODE_ldb_to_drsuapi(struct ldb_context *ldb, 
890                                                  const struct dsdb_schema *schema,
891                                                  const struct dsdb_attribute *attr,
892                                                  const struct ldb_message_element *in,
893                                                  TALLOC_CTX *mem_ctx,
894                                                  struct drsuapi_DsReplicaAttribute *out)
895 {
896         uint32_t i;
897         DATA_BLOB *blobs;
898
899         if (attr->attributeID_id == 0xFFFFFFFF) {
900                 return WERR_FOOBAR;
901         }
902
903         out->attid                      = attr->attributeID_id;
904         out->value_ctr.num_values       = in->num_values;
905         out->value_ctr.values           = talloc_array(mem_ctx,
906                                                        struct drsuapi_DsAttributeValue,
907                                                        in->num_values);
908         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
909
910         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
911         W_ERROR_HAVE_NO_MEMORY(blobs);
912
913         for (i=0; i < in->num_values; i++) {
914                 out->value_ctr.values[i].blob   = &blobs[i];
915
916                 if (!convert_string_talloc_convenience(blobs,
917                         schema->iconv_convenience, CH_UNIX, CH_UTF16,
918                         in->values[i].data, in->values[i].length,
919                         (void **)&blobs[i].data, &blobs[i].length, false)) {
920                                 return WERR_FOOBAR;
921                 }
922         }
923
924         return WERR_OK;
925 }
926
927 static WERROR dsdb_syntax_DN_drsuapi_to_ldb(struct ldb_context *ldb, 
928                                             const struct dsdb_schema *schema,
929                                             const struct dsdb_attribute *attr,
930                                             const struct drsuapi_DsReplicaAttribute *in,
931                                             TALLOC_CTX *mem_ctx,
932                                             struct ldb_message_element *out)
933 {
934         uint32_t i;
935         int ret;
936
937         out->flags      = 0;
938         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
939         W_ERROR_HAVE_NO_MEMORY(out->name);
940
941         out->num_values = in->value_ctr.num_values;
942         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
943         W_ERROR_HAVE_NO_MEMORY(out->values);
944
945         for (i=0; i < out->num_values; i++) {
946                 struct drsuapi_DsReplicaObjectIdentifier3 id3;
947                 enum ndr_err_code ndr_err;
948                 DATA_BLOB guid_blob;
949                 struct ldb_dn *dn;
950                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
951                 if (!tmp_ctx) {
952                         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
953                 }
954
955                 if (in->value_ctr.values[i].blob == NULL) {
956                         talloc_free(tmp_ctx);
957                         return WERR_FOOBAR;
958                 }
959
960                 if (in->value_ctr.values[i].blob->length == 0) {
961                         talloc_free(tmp_ctx);
962                         return WERR_FOOBAR;
963                 }
964
965                 
966
967                 ndr_err = ndr_pull_struct_blob_all(in->value_ctr.values[i].blob,
968                                                    tmp_ctx, schema->iconv_convenience, &id3,
969                                                    (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3);
970                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
971                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
972                         talloc_free(tmp_ctx);
973                         return ntstatus_to_werror(status);
974                 }
975
976                 dn = ldb_dn_new(tmp_ctx, ldb, id3.dn);
977                 if (!dn) {
978                         talloc_free(tmp_ctx);
979                         /* If this fails, it must be out of memory, as it does not do much parsing */
980                         W_ERROR_HAVE_NO_MEMORY(dn);
981                 }
982
983                 ndr_err = ndr_push_struct_blob(&guid_blob, tmp_ctx, schema->iconv_convenience, &id3.guid,
984                                                (ndr_push_flags_fn_t)ndr_push_GUID);
985                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
986                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
987                         talloc_free(tmp_ctx);
988                         return ntstatus_to_werror(status);
989                 }
990
991                 ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
992                 if (ret != LDB_SUCCESS) {
993                         talloc_free(tmp_ctx);
994                         return WERR_FOOBAR;
995                 }
996
997                 talloc_free(guid_blob.data);
998
999                 if (id3.__ndr_size_sid) {
1000                         DATA_BLOB sid_blob;
1001                         ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, schema->iconv_convenience, &id3.sid,
1002                                                        (ndr_push_flags_fn_t)ndr_push_dom_sid);
1003                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1004                                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1005                                 talloc_free(tmp_ctx);
1006                                 return ntstatus_to_werror(status);
1007                         }
1008
1009                         ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
1010                         if (ret != LDB_SUCCESS) {
1011                                 talloc_free(tmp_ctx);
1012                                 return WERR_FOOBAR;
1013                         }
1014                 }
1015
1016                 out->values[i] = data_blob_string_const(ldb_dn_get_extended_linearized(out->values, dn, 1));
1017                 talloc_free(tmp_ctx);
1018         }
1019
1020         return WERR_OK;
1021 }
1022
1023 static WERROR dsdb_syntax_DN_ldb_to_drsuapi(struct ldb_context *ldb, 
1024                                             const struct dsdb_schema *schema,
1025                                             const struct dsdb_attribute *attr,
1026                                             const struct ldb_message_element *in,
1027                                             TALLOC_CTX *mem_ctx,
1028                                             struct drsuapi_DsReplicaAttribute *out)
1029 {
1030         uint32_t i;
1031         DATA_BLOB *blobs;
1032
1033         if (attr->attributeID_id == 0xFFFFFFFF) {
1034                 return WERR_FOOBAR;
1035         }
1036
1037         out->attid                      = attr->attributeID_id;
1038         out->value_ctr.num_values       = in->num_values;
1039         out->value_ctr.values           = talloc_array(mem_ctx,
1040                                                        struct drsuapi_DsAttributeValue,
1041                                                        in->num_values);
1042         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1043
1044         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1045         W_ERROR_HAVE_NO_MEMORY(blobs);
1046
1047         for (i=0; i < in->num_values; i++) {
1048                 struct drsuapi_DsReplicaObjectIdentifier3 id3;
1049                 enum ndr_err_code ndr_err;
1050                 const DATA_BLOB *guid_blob, *sid_blob;
1051                 struct ldb_dn *dn;
1052                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1053                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1054
1055                 out->value_ctr.values[i].blob   = &blobs[i];
1056
1057                 dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &in->values[i]);
1058
1059                 W_ERROR_HAVE_NO_MEMORY(dn);
1060
1061                 guid_blob = ldb_dn_get_extended_component(dn, "GUID");
1062
1063                 ZERO_STRUCT(id3);
1064
1065                 if (guid_blob) {
1066                         ndr_err = ndr_pull_struct_blob_all(guid_blob, 
1067                                                            tmp_ctx, schema->iconv_convenience, &id3.guid,
1068                                                            (ndr_pull_flags_fn_t)ndr_pull_GUID);
1069                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1070                                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1071                                 talloc_free(tmp_ctx);
1072                                 return ntstatus_to_werror(status);
1073                         }
1074                 }
1075
1076                 sid_blob = ldb_dn_get_extended_component(dn, "SID");
1077                 if (sid_blob) {
1078                         
1079                         ndr_err = ndr_pull_struct_blob_all(sid_blob, 
1080                                                            tmp_ctx, schema->iconv_convenience, &id3.sid,
1081                                                            (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1082                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1083                                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1084                                 talloc_free(tmp_ctx);
1085                                 return ntstatus_to_werror(status);
1086                         }
1087                 }
1088
1089                 id3.dn = ldb_dn_get_linearized(dn);
1090
1091                 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
1092                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1093                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1094                         talloc_free(tmp_ctx);
1095                         return ntstatus_to_werror(status);
1096                 }
1097                 talloc_free(tmp_ctx);
1098         }
1099
1100         return WERR_OK;
1101 }
1102
1103 static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(struct ldb_context *ldb, 
1104                                                    const struct dsdb_schema *schema,
1105                                                    const struct dsdb_attribute *attr,
1106                                                    const struct drsuapi_DsReplicaAttribute *in,
1107                                                    TALLOC_CTX *mem_ctx,
1108                                                    struct ldb_message_element *out)
1109 {
1110         uint32_t i;
1111
1112         out->flags      = 0;
1113         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1114         W_ERROR_HAVE_NO_MEMORY(out->name);
1115
1116         out->num_values = in->value_ctr.num_values;
1117         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1118         W_ERROR_HAVE_NO_MEMORY(out->values);
1119
1120         for (i=0; i < out->num_values; i++) {
1121                 struct drsuapi_DsReplicaObjectIdentifier3Binary id3b;
1122                 char *binary;
1123                 char *str;
1124                 enum ndr_err_code ndr_err;
1125
1126                 if (in->value_ctr.values[i].blob == NULL) {
1127                         return WERR_FOOBAR;
1128                 }
1129
1130                 if (in->value_ctr.values[i].blob->length == 0) {
1131                         return WERR_FOOBAR;
1132                 }
1133
1134                 ndr_err = ndr_pull_struct_blob_all(in->value_ctr.values[i].blob,
1135                                                    out->values, schema->iconv_convenience, &id3b,
1136                                                    (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3Binary);
1137                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1138                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1139                         return ntstatus_to_werror(status);
1140                 }
1141
1142                 /* TODO: handle id3.guid and id3.sid */
1143                 binary = data_blob_hex_string(out->values, &id3b.binary);
1144                 W_ERROR_HAVE_NO_MEMORY(binary);
1145
1146                 str = talloc_asprintf(out->values, "B:%u:%s:%s",
1147                                       (unsigned int)(id3b.binary.length * 2), /* because of 2 hex chars per byte */
1148                                       binary,
1149                                       id3b.dn);
1150                 W_ERROR_HAVE_NO_MEMORY(str);
1151
1152                 /* TODO: handle id3.guid and id3.sid */
1153                 out->values[i] = data_blob_string_const(str);
1154         }
1155
1156         return WERR_OK;
1157 }
1158
1159 static WERROR dsdb_syntax_DN_BINARY_ldb_to_drsuapi(struct ldb_context *ldb, 
1160                                                    const struct dsdb_schema *schema,
1161                                                    const struct dsdb_attribute *attr,
1162                                                    const struct ldb_message_element *in,
1163                                                    TALLOC_CTX *mem_ctx,
1164                                                    struct drsuapi_DsReplicaAttribute *out)
1165 {
1166         uint32_t i;
1167         DATA_BLOB *blobs;
1168
1169         if (attr->attributeID_id == 0xFFFFFFFF) {
1170                 return WERR_FOOBAR;
1171         }
1172
1173         out->attid                      = attr->attributeID_id;
1174         out->value_ctr.num_values       = in->num_values;
1175         out->value_ctr.values           = talloc_array(mem_ctx,
1176                                                        struct drsuapi_DsAttributeValue,
1177                                                        in->num_values);
1178         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1179
1180         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1181         W_ERROR_HAVE_NO_MEMORY(blobs);
1182
1183         for (i=0; i < in->num_values; i++) {
1184                 struct drsuapi_DsReplicaObjectIdentifier3Binary id3b;
1185                 enum ndr_err_code ndr_err;
1186
1187                 out->value_ctr.values[i].blob   = &blobs[i];
1188
1189                 /* TODO: handle id3b.guid and id3b.sid, id3.binary */
1190                 ZERO_STRUCT(id3b);
1191                 id3b.dn         = (const char *)in->values[i].data;
1192                 id3b.binary     = data_blob(NULL, 0);
1193
1194                 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3b,
1195                                                (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3Binary);
1196                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1197                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1198                         return ntstatus_to_werror(status);
1199                 }
1200         }
1201
1202         return WERR_OK;
1203 }
1204
1205 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb(struct ldb_context *ldb, 
1206                                                               const struct dsdb_schema *schema,
1207                                                               const struct dsdb_attribute *attr,
1208                                                               const struct drsuapi_DsReplicaAttribute *in,
1209                                                               TALLOC_CTX *mem_ctx,
1210                                                               struct ldb_message_element *out)
1211 {
1212         uint32_t i;
1213
1214         out->flags      = 0;
1215         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1216         W_ERROR_HAVE_NO_MEMORY(out->name);
1217
1218         out->num_values = in->value_ctr.num_values;
1219         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1220         W_ERROR_HAVE_NO_MEMORY(out->values);
1221
1222         for (i=0; i < out->num_values; i++) {
1223                 uint32_t len;
1224                 char *str;
1225
1226                 if (in->value_ctr.values[i].blob == NULL) {
1227                         return WERR_FOOBAR;
1228                 }
1229
1230                 if (in->value_ctr.values[i].blob->length < 4) {
1231                         return WERR_FOOBAR;
1232                 }
1233
1234                 len = IVAL(in->value_ctr.values[i].blob->data, 0);
1235
1236                 if (len != in->value_ctr.values[i].blob->length) {
1237                         return WERR_FOOBAR;
1238                 }
1239
1240                 if (!convert_string_talloc_convenience(out->values, schema->iconv_convenience, CH_UTF16, CH_UNIX,
1241                                             in->value_ctr.values[i].blob->data+4,
1242                                             in->value_ctr.values[i].blob->length-4,
1243                                             (void **)&str, NULL, false)) {
1244                         return WERR_FOOBAR;
1245                 }
1246
1247                 out->values[i] = data_blob_string_const(str);
1248         }
1249
1250         return WERR_OK;
1251 }
1252
1253 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi(struct ldb_context *ldb, 
1254                                                               const struct dsdb_schema *schema,
1255                                                               const struct dsdb_attribute *attr,
1256                                                               const struct ldb_message_element *in,
1257                                                               TALLOC_CTX *mem_ctx,
1258                                                               struct drsuapi_DsReplicaAttribute *out)
1259 {
1260         uint32_t i;
1261         DATA_BLOB *blobs;
1262
1263         if (attr->attributeID_id == 0xFFFFFFFF) {
1264                 return WERR_FOOBAR;
1265         }
1266
1267         out->attid                      = attr->attributeID_id;
1268         out->value_ctr.num_values       = in->num_values;
1269         out->value_ctr.values           = talloc_array(mem_ctx,
1270                                                        struct drsuapi_DsAttributeValue,
1271                                                        in->num_values);
1272         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1273
1274         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1275         W_ERROR_HAVE_NO_MEMORY(blobs);
1276
1277         for (i=0; i < in->num_values; i++) {
1278                 uint8_t *data;
1279                 size_t ret;
1280
1281                 out->value_ctr.values[i].blob   = &blobs[i];
1282
1283                 if (!convert_string_talloc_convenience(blobs, schema->iconv_convenience, CH_UNIX, CH_UTF16,
1284                                             in->values[i].data,
1285                                             in->values[i].length,
1286                                             (void **)&data, &ret, false)) {
1287                         return WERR_FOOBAR;
1288                 }
1289
1290                 blobs[i] = data_blob_talloc(blobs, NULL, 4 + ret);
1291                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1292
1293                 SIVAL(blobs[i].data, 0, 4 + ret);
1294
1295                 if (ret > 0) {
1296                         memcpy(blobs[i].data + 4, data, ret);
1297                         talloc_free(data);
1298                 }
1299         }
1300
1301         return WERR_OK;
1302 }
1303
1304 #define OMOBJECTCLASS(val) { .length = sizeof(val) - 1, .data = discard_const_p(uint8_t, val) }
1305
1306 static const struct dsdb_syntax dsdb_syntaxes[] = {
1307         {
1308                 .name                   = "Boolean",
1309                 .ldap_oid               = LDB_SYNTAX_BOOLEAN,
1310                 .oMSyntax               = 1,
1311                 .attributeSyntax_oid    = "2.5.5.8",
1312                 .drsuapi_to_ldb         = dsdb_syntax_BOOL_drsuapi_to_ldb,
1313                 .ldb_to_drsuapi         = dsdb_syntax_BOOL_ldb_to_drsuapi,
1314                 .equality               = "booleanMatch",
1315                 .comment                = "Boolean" 
1316         },{
1317                 .name                   = "Integer",
1318                 .ldap_oid               = LDB_SYNTAX_INTEGER,
1319                 .oMSyntax               = 2,
1320                 .attributeSyntax_oid    = "2.5.5.9",
1321                 .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
1322                 .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
1323                 .equality               = "integerMatch",
1324                 .comment                = "Integer",
1325                 .ldb_syntax             = LDB_SYNTAX_SAMBA_INT32
1326         },{
1327                 .name                   = "String(Octet)",
1328                 .ldap_oid               = LDB_SYNTAX_OCTET_STRING,
1329                 .oMSyntax               = 4,
1330                 .attributeSyntax_oid    = "2.5.5.10",
1331                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1332                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1333                 .equality               = "octetStringMatch",
1334                 .comment                = "Octet String",
1335         },{
1336                 .name                   = "String(Sid)",
1337                 .ldap_oid               = LDB_SYNTAX_OCTET_STRING,
1338                 .oMSyntax               = 4,
1339                 .attributeSyntax_oid    = "2.5.5.17",
1340                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1341                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1342                 .equality               = "octetStringMatch",
1343                 .comment                = "Octet String - Security Identifier (SID)",
1344                 .ldb_syntax             = LDB_SYNTAX_SAMBA_SID
1345         },{
1346                 .name                   = "String(Object-Identifier)",
1347                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.38",
1348                 .oMSyntax               = 6,
1349                 .attributeSyntax_oid    = "2.5.5.2",
1350                 .drsuapi_to_ldb         = dsdb_syntax_OID_drsuapi_to_ldb,
1351                 .ldb_to_drsuapi         = dsdb_syntax_OID_ldb_to_drsuapi,
1352                 .equality               = "caseIgnoreMatch", /* Would use "objectIdentifierMatch" but most are ldap attribute/class names */
1353                 .comment                = "OID String",
1354                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING
1355         },{
1356                 .name                   = "Enumeration",
1357                 .ldap_oid               = LDB_SYNTAX_INTEGER,
1358                 .oMSyntax               = 10,
1359                 .attributeSyntax_oid    = "2.5.5.9",
1360                 .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
1361                 .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
1362                 .ldb_syntax             = LDB_SYNTAX_SAMBA_INT32
1363         },{
1364         /* not used in w2k3 forest */
1365                 .name                   = "String(Numeric)",
1366                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.36",
1367                 .oMSyntax               = 18,
1368                 .attributeSyntax_oid    = "2.5.5.6",
1369                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1370                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1371                 .equality               = "numericStringMatch",
1372                 .substring              = "numericStringSubstringsMatch",
1373                 .comment                = "Numeric String",
1374                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1375         },{
1376                 .name                   = "String(Printable)",
1377                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.44",
1378                 .oMSyntax               = 19,
1379                 .attributeSyntax_oid    = "2.5.5.5",
1380                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1381                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1382                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
1383         },{
1384                 .name                   = "String(Teletex)",
1385                 .ldap_oid               = "1.2.840.113556.1.4.905",
1386                 .oMSyntax               = 20,
1387                 .attributeSyntax_oid    = "2.5.5.4",
1388                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1389                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1390                 .equality               = "caseIgnoreMatch",
1391                 .substring              = "caseIgnoreSubstringsMatch",
1392                 .comment                = "Case Insensitive String",
1393                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1394         },{
1395                 .name                   = "String(IA5)",
1396                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.26",
1397                 .oMSyntax               = 22,
1398                 .attributeSyntax_oid    = "2.5.5.5",
1399                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1400                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1401                 .equality               = "caseExactIA5Match",
1402                 .comment                = "Printable String",
1403                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
1404         },{
1405                 .name                   = "String(UTC-Time)",
1406                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.53",
1407                 .oMSyntax               = 23,
1408                 .attributeSyntax_oid    = "2.5.5.11",
1409                 .drsuapi_to_ldb         = dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb,
1410                 .ldb_to_drsuapi         = dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi,
1411                 .equality               = "generalizedTimeMatch",
1412                 .comment                = "UTC Time",
1413         },{
1414                 .name                   = "String(Generalized-Time)",
1415                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.24",
1416                 .oMSyntax               = 24,
1417                 .attributeSyntax_oid    = "2.5.5.11",
1418                 .drsuapi_to_ldb         = dsdb_syntax_NTTIME_drsuapi_to_ldb,
1419                 .ldb_to_drsuapi         = dsdb_syntax_NTTIME_ldb_to_drsuapi,
1420                 .equality               = "generalizedTimeMatch",
1421                 .comment                = "Generalized Time",
1422                 .ldb_syntax             = LDB_SYNTAX_UTC_TIME,
1423         },{
1424         /* not used in w2k3 schema */
1425                 .name                   = "String(Case Sensitive)",
1426                 .ldap_oid               = "1.2.840.113556.1.4.1362",
1427                 .oMSyntax               = 27,
1428                 .attributeSyntax_oid    = "2.5.5.3",
1429                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1430                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1431         },{
1432                 .name                   = "String(Unicode)",
1433                 .ldap_oid               = LDB_SYNTAX_DIRECTORY_STRING,
1434                 .oMSyntax               = 64,
1435                 .attributeSyntax_oid    = "2.5.5.12",
1436                 .drsuapi_to_ldb         = dsdb_syntax_UNICODE_drsuapi_to_ldb,
1437                 .ldb_to_drsuapi         = dsdb_syntax_UNICODE_ldb_to_drsuapi,
1438                 .equality               = "caseIgnoreMatch",
1439                 .substring              = "caseIgnoreSubstringsMatch",
1440                 .comment                = "Directory String",
1441         },{
1442                 .name                   = "Interval/LargeInteger",
1443                 .ldap_oid               = "1.2.840.113556.1.4.906",
1444                 .oMSyntax               = 65,
1445                 .attributeSyntax_oid    = "2.5.5.16",
1446                 .drsuapi_to_ldb         = dsdb_syntax_INT64_drsuapi_to_ldb,
1447                 .ldb_to_drsuapi         = dsdb_syntax_INT64_ldb_to_drsuapi,
1448                 .equality               = "integerMatch",
1449                 .comment                = "Large Integer",
1450                 .ldb_syntax             = LDB_SYNTAX_INTEGER,
1451         },{
1452                 .name                   = "String(NT-Sec-Desc)",
1453                 .ldap_oid               = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1454                 .oMSyntax               = 66,
1455                 .attributeSyntax_oid    = "2.5.5.15",
1456                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1457                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1458         },{
1459                 .name                   = "Object(DS-DN)",
1460                 .ldap_oid               = LDB_SYNTAX_DN,
1461                 .oMSyntax               = 127,
1462                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x4a"),
1463                 .attributeSyntax_oid    = "2.5.5.1",
1464                 .drsuapi_to_ldb         = dsdb_syntax_DN_drsuapi_to_ldb,
1465                 .ldb_to_drsuapi         = dsdb_syntax_DN_ldb_to_drsuapi,
1466                 .equality               = "distinguishedNameMatch",
1467                 .comment                = "Object(DS-DN) == a DN",
1468         },{
1469                 .name                   = "Object(DN-Binary)",
1470                 .ldap_oid               = "1.2.840.113556.1.4.903",
1471                 .oMSyntax               = 127,
1472                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0b"),
1473                 .attributeSyntax_oid    = "2.5.5.7",
1474                 .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
1475                 .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
1476                 .equality               = "octetStringMatch",
1477                 .comment                = "OctetString: Binary+DN",
1478                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
1479         },{
1480         /* not used in w2k3 schema */
1481                 .name                   = "Object(OR-Name)",
1482                 .ldap_oid               = "1.2.840.113556.1.4.1221",
1483                 .oMSyntax               = 127,
1484                 .oMObjectClass          = OMOBJECTCLASS("\x56\x06\x01\x02\x05\x0b\x1D"),
1485                 .attributeSyntax_oid    = "2.5.5.7",
1486                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1487                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1488         },{
1489         /* 
1490          * TODO: verify if DATA_BLOB is correct here...!
1491          *
1492          *       repsFrom and repsTo are the only attributes using
1493          *       this attribute syntax, but they're not replicated... 
1494          */
1495                 .name                   = "Object(Replica-Link)",
1496                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.40",
1497                 .oMSyntax               = 127,
1498                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x06"),
1499                 .attributeSyntax_oid    = "2.5.5.10",
1500                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1501                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1502         },{
1503                 .name                   = "Object(Presentation-Address)",
1504                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.43",
1505                 .oMSyntax               = 127,
1506                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x5c"),
1507                 .attributeSyntax_oid    = "2.5.5.13",
1508                 .drsuapi_to_ldb         = dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb,
1509                 .ldb_to_drsuapi         = dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi,
1510                 .comment                = "Presentation Address",
1511                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1512         },{
1513         /* not used in w2k3 schema */
1514                 .name                   = "Object(Access-Point)",
1515                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.2",
1516                 .oMSyntax               = 127,
1517                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x3e"),
1518                 .attributeSyntax_oid    = "2.5.5.14",
1519                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1520                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1521                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1522         },{
1523         /* not used in w2k3 schema */
1524                 .name                   = "Object(DN-String)",
1525                 .ldap_oid               = "1.2.840.113556.1.4.904",
1526                 .oMSyntax               = 127,
1527                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0c"),
1528                 .attributeSyntax_oid    = "2.5.5.14",
1529                 .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
1530                 .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
1531                 .equality               = "octetStringMatch",
1532                 .comment                = "OctetString: String+DN",
1533                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
1534         }
1535 };
1536
1537 const struct dsdb_syntax *find_syntax_map_by_ad_oid(const char *ad_oid) 
1538 {
1539         int i;
1540         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1541                 if (strcasecmp(ad_oid, dsdb_syntaxes[i].attributeSyntax_oid) == 0) {
1542                         return &dsdb_syntaxes[i];
1543                 }
1544         }
1545         return NULL;
1546 }
1547
1548 const struct dsdb_syntax *find_syntax_map_by_ad_syntax(int oMSyntax) 
1549 {
1550         int i;
1551         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1552                 if (oMSyntax == dsdb_syntaxes[i].oMSyntax) {
1553                         return &dsdb_syntaxes[i];
1554                 }
1555         }
1556         return NULL;
1557 }
1558
1559 const struct dsdb_syntax *find_syntax_map_by_standard_oid(const char *standard_oid) 
1560 {
1561         int i;
1562         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1563                 if (strcasecmp(standard_oid, dsdb_syntaxes[i].ldap_oid) == 0) {
1564                         return &dsdb_syntaxes[i];
1565                 }
1566         }
1567         return NULL;
1568 }
1569 const struct dsdb_syntax *dsdb_syntax_for_attribute(const struct dsdb_attribute *attr)
1570 {
1571         uint32_t i;
1572
1573         for (i=0; i < ARRAY_SIZE(dsdb_syntaxes); i++) {
1574                 if (attr->oMSyntax != dsdb_syntaxes[i].oMSyntax) continue;
1575
1576                 if (attr->oMObjectClass.length != dsdb_syntaxes[i].oMObjectClass.length) continue;
1577
1578                 if (attr->oMObjectClass.length) {
1579                         int ret;
1580                         ret = memcmp(attr->oMObjectClass.data,
1581                                      dsdb_syntaxes[i].oMObjectClass.data,
1582                                      attr->oMObjectClass.length);
1583                         if (ret != 0) continue;
1584                 }
1585
1586                 if (strcmp(attr->attributeSyntax_oid, dsdb_syntaxes[i].attributeSyntax_oid) != 0) continue;
1587
1588                 return &dsdb_syntaxes[i];
1589         }
1590
1591         return NULL;
1592 }
1593
1594 WERROR dsdb_attribute_drsuapi_to_ldb(struct ldb_context *ldb, 
1595                                      const struct dsdb_schema *schema,
1596                                      const struct drsuapi_DsReplicaAttribute *in,
1597                                      TALLOC_CTX *mem_ctx,
1598                                      struct ldb_message_element *out)
1599 {
1600         const struct dsdb_attribute *sa;
1601
1602         sa = dsdb_attribute_by_attributeID_id(schema, in->attid);
1603         if (!sa) {
1604                 return WERR_FOOBAR;
1605         }
1606
1607         return sa->syntax->drsuapi_to_ldb(ldb, schema, sa, in, mem_ctx, out);
1608 }
1609
1610 WERROR dsdb_attribute_ldb_to_drsuapi(struct ldb_context *ldb, 
1611                                      const struct dsdb_schema *schema,
1612                                      const struct ldb_message_element *in,
1613                                      TALLOC_CTX *mem_ctx,
1614                                      struct drsuapi_DsReplicaAttribute *out)
1615 {
1616         const struct dsdb_attribute *sa;
1617
1618         sa = dsdb_attribute_by_lDAPDisplayName(schema, in->name);
1619         if (!sa) {
1620                 return WERR_FOOBAR;
1621         }
1622
1623         return sa->syntax->ldb_to_drsuapi(ldb, schema, sa, in, mem_ctx, out);
1624 }