Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into 4-0-abartlet
[kai/samba.git] / source4 / dsdb / schema / schema_syntax.c
1 /* 
2    Unix SMB/CIFS mplementation.
3    DSDB schema syntaxes
4    
5    Copyright (C) Stefan Metzmacher <metze@samba.org> 2006
6    Copyright (C) Simo Sorce 2005
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21    
22 */
23 #include "includes.h"
24 #include "dsdb/samdb/samdb.h"
25 #include "librpc/gen_ndr/ndr_drsuapi.h"
26 #include "lib/ldb/include/ldb.h"
27 #include "system/time.h"
28 #include "lib/charset/charset.h"
29 #include "librpc/ndr/libndr.h"
30 #include "param/param.h"
31
32 static WERROR dsdb_syntax_FOOBAR_drsuapi_to_ldb(const struct dsdb_schema *schema,
33                                                 const struct dsdb_attribute *attr,
34                                                 const struct drsuapi_DsReplicaAttribute *in,
35                                                 TALLOC_CTX *mem_ctx,
36                                                 struct ldb_message_element *out)
37 {
38         uint32_t i;
39
40         out->flags      = 0;
41         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
42         W_ERROR_HAVE_NO_MEMORY(out->name);
43
44         out->num_values = in->value_ctr.num_values;
45         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
46         W_ERROR_HAVE_NO_MEMORY(out->values);
47
48         for (i=0; i < out->num_values; i++) {
49                 char *str;
50
51                 if (in->value_ctr.values[i].blob == NULL) {
52                         return WERR_FOOBAR;
53                 }
54
55                 str = talloc_asprintf(out->values, "%s: not implemented",
56                                       attr->syntax->name);
57                 W_ERROR_HAVE_NO_MEMORY(str);
58
59                 out->values[i] = data_blob_string_const(str);
60         }
61
62         return WERR_OK;
63 }
64
65 static WERROR dsdb_syntax_FOOBAR_ldb_to_drsuapi(const struct dsdb_schema *schema,
66                                                 const struct dsdb_attribute *attr,
67                                                 const struct ldb_message_element *in,
68                                                 TALLOC_CTX *mem_ctx,
69                                                 struct drsuapi_DsReplicaAttribute *out)
70 {
71         return WERR_FOOBAR;
72 }
73
74 static WERROR dsdb_syntax_BOOL_drsuapi_to_ldb(const struct dsdb_schema *schema,
75                                               const struct dsdb_attribute *attr,
76                                               const struct drsuapi_DsReplicaAttribute *in,
77                                               TALLOC_CTX *mem_ctx,
78                                               struct ldb_message_element *out)
79 {
80         uint32_t i;
81
82         out->flags      = 0;
83         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
84         W_ERROR_HAVE_NO_MEMORY(out->name);
85
86         out->num_values = in->value_ctr.num_values;
87         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
88         W_ERROR_HAVE_NO_MEMORY(out->values);
89
90         for (i=0; i < out->num_values; i++) {
91                 uint32_t v;
92                 char *str;
93
94                 if (in->value_ctr.values[i].blob == NULL) {
95                         return WERR_FOOBAR;
96                 }
97
98                 if (in->value_ctr.values[i].blob->length != 4) {
99                         return WERR_FOOBAR;
100                 }
101
102                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
103
104                 if (v != 0) {
105                         str = talloc_strdup(out->values, "TRUE");
106                         W_ERROR_HAVE_NO_MEMORY(str);
107                 } else {
108                         str = talloc_strdup(out->values, "FALSE");
109                         W_ERROR_HAVE_NO_MEMORY(str);
110                 }
111
112                 out->values[i] = data_blob_string_const(str);
113         }
114
115         return WERR_OK;
116 }
117
118 static WERROR dsdb_syntax_BOOL_ldb_to_drsuapi(const struct dsdb_schema *schema,
119                                               const struct dsdb_attribute *attr,
120                                               const struct ldb_message_element *in,
121                                               TALLOC_CTX *mem_ctx,
122                                               struct drsuapi_DsReplicaAttribute *out)
123 {
124         uint32_t i;
125         DATA_BLOB *blobs;
126
127         if (attr->attributeID_id == 0xFFFFFFFF) {
128                 return WERR_FOOBAR;
129         }
130
131         out->attid                      = attr->attributeID_id;
132         out->value_ctr.num_values       = in->num_values;
133         out->value_ctr.values           = talloc_array(mem_ctx,
134                                                        struct drsuapi_DsAttributeValue,
135                                                        in->num_values);
136         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
137
138         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
139         W_ERROR_HAVE_NO_MEMORY(blobs);
140
141         for (i=0; i < in->num_values; i++) {
142                 out->value_ctr.values[i].blob   = &blobs[i];
143
144                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
145                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
146
147                 if (strcmp("TRUE", (const char *)in->values[i].data) == 0) {
148                         SIVAL(blobs[i].data, 0, 0x00000001);
149                 } else if (strcmp("FALSE", (const char *)in->values[i].data) == 0) {
150                         SIVAL(blobs[i].data, 0, 0x00000000);
151                 } else {
152                         return WERR_FOOBAR;
153                 }
154         }
155
156         return WERR_OK;
157 }
158
159 static WERROR dsdb_syntax_INT32_drsuapi_to_ldb(const struct dsdb_schema *schema,
160                                                const struct dsdb_attribute *attr,
161                                                const struct drsuapi_DsReplicaAttribute *in,
162                                                TALLOC_CTX *mem_ctx,
163                                                struct ldb_message_element *out)
164 {
165         uint32_t i;
166
167         out->flags      = 0;
168         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
169         W_ERROR_HAVE_NO_MEMORY(out->name);
170
171         out->num_values = in->value_ctr.num_values;
172         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
173         W_ERROR_HAVE_NO_MEMORY(out->values);
174
175         for (i=0; i < out->num_values; i++) {
176                 int32_t v;
177                 char *str;
178
179                 if (in->value_ctr.values[i].blob == NULL) {
180                         return WERR_FOOBAR;
181                 }
182
183                 if (in->value_ctr.values[i].blob->length != 4) {
184                         return WERR_FOOBAR;
185                 }
186
187                 v = IVALS(in->value_ctr.values[i].blob->data, 0);
188
189                 str = talloc_asprintf(out->values, "%d", v);
190                 W_ERROR_HAVE_NO_MEMORY(str);
191
192                 out->values[i] = data_blob_string_const(str);
193         }
194
195         return WERR_OK;
196 }
197
198 static WERROR dsdb_syntax_INT32_ldb_to_drsuapi(const struct dsdb_schema *schema,
199                                                const struct dsdb_attribute *attr,
200                                                const struct ldb_message_element *in,
201                                                TALLOC_CTX *mem_ctx,
202                                                struct drsuapi_DsReplicaAttribute *out)
203 {
204         uint32_t i;
205         DATA_BLOB *blobs;
206
207         if (attr->attributeID_id == 0xFFFFFFFF) {
208                 return WERR_FOOBAR;
209         }
210
211         out->attid                      = attr->attributeID_id;
212         out->value_ctr.num_values       = in->num_values;
213         out->value_ctr.values           = talloc_array(mem_ctx,
214                                                        struct drsuapi_DsAttributeValue,
215                                                        in->num_values);
216         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
217
218         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
219         W_ERROR_HAVE_NO_MEMORY(blobs);
220
221         for (i=0; i < in->num_values; i++) {
222                 int32_t v;
223
224                 out->value_ctr.values[i].blob   = &blobs[i];
225
226                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
227                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
228
229                 v = strtol((const char *)in->values[i].data, NULL, 10);
230
231                 SIVALS(blobs[i].data, 0, v);
232         }
233
234         return WERR_OK;
235 }
236
237 static WERROR dsdb_syntax_INT64_drsuapi_to_ldb(const struct dsdb_schema *schema,
238                                                const struct dsdb_attribute *attr,
239                                                const struct drsuapi_DsReplicaAttribute *in,
240                                                TALLOC_CTX *mem_ctx,
241                                                struct ldb_message_element *out)
242 {
243         uint32_t i;
244
245         out->flags      = 0;
246         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
247         W_ERROR_HAVE_NO_MEMORY(out->name);
248
249         out->num_values = in->value_ctr.num_values;
250         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
251         W_ERROR_HAVE_NO_MEMORY(out->values);
252
253         for (i=0; i < out->num_values; i++) {
254                 int64_t v;
255                 char *str;
256
257                 if (in->value_ctr.values[i].blob == NULL) {
258                         return WERR_FOOBAR;
259                 }
260
261                 if (in->value_ctr.values[i].blob->length != 8) {
262                         return WERR_FOOBAR;
263                 }
264
265                 v = BVALS(in->value_ctr.values[i].blob->data, 0);
266
267                 str = talloc_asprintf(out->values, "%lld", (long long int)v);
268                 W_ERROR_HAVE_NO_MEMORY(str);
269
270                 out->values[i] = data_blob_string_const(str);
271         }
272
273         return WERR_OK;
274 }
275
276 static WERROR dsdb_syntax_INT64_ldb_to_drsuapi(const struct dsdb_schema *schema,
277                                                const struct dsdb_attribute *attr,
278                                                const struct ldb_message_element *in,
279                                                TALLOC_CTX *mem_ctx,
280                                                struct drsuapi_DsReplicaAttribute *out)
281 {
282         uint32_t i;
283         DATA_BLOB *blobs;
284
285         if (attr->attributeID_id == 0xFFFFFFFF) {
286                 return WERR_FOOBAR;
287         }
288
289         out->attid                      = attr->attributeID_id;
290         out->value_ctr.num_values       = in->num_values;
291         out->value_ctr.values           = talloc_array(mem_ctx,
292                                                        struct drsuapi_DsAttributeValue,
293                                                        in->num_values);
294         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
295
296         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
297         W_ERROR_HAVE_NO_MEMORY(blobs);
298
299         for (i=0; i < in->num_values; i++) {
300                 int64_t v;
301
302                 out->value_ctr.values[i].blob   = &blobs[i];
303
304                 blobs[i] = data_blob_talloc(blobs, NULL, 8);
305                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
306
307                 v = strtoll((const char *)in->values[i].data, NULL, 10);
308
309                 SBVALS(blobs[i].data, 0, v);
310         }
311
312         return WERR_OK;
313 }
314
315 static WERROR dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb(const struct dsdb_schema *schema,
316                                                     const struct dsdb_attribute *attr,
317                                                     const struct drsuapi_DsReplicaAttribute *in,
318                                                     TALLOC_CTX *mem_ctx,
319                                                     struct ldb_message_element *out)
320 {
321         uint32_t i;
322
323         out->flags      = 0;
324         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
325         W_ERROR_HAVE_NO_MEMORY(out->name);
326
327         out->num_values = in->value_ctr.num_values;
328         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
329         W_ERROR_HAVE_NO_MEMORY(out->values);
330
331         for (i=0; i < out->num_values; i++) {
332                 NTTIME v;
333                 time_t t;
334                 char *str;
335
336                 if (in->value_ctr.values[i].blob == NULL) {
337                         return WERR_FOOBAR;
338                 }
339
340                 if (in->value_ctr.values[i].blob->length != 8) {
341                         return WERR_FOOBAR;
342                 }
343
344                 v = BVAL(in->value_ctr.values[i].blob->data, 0);
345                 v *= 10000000;
346                 t = nt_time_to_unix(v);
347
348                 /* 
349                  * NOTE: On a w2k3 server you can set a GeneralizedTime string
350                  *       via LDAP, but you get back an UTCTime string,
351                  *       but via DRSUAPI you get back the NTTIME_1sec value
352                  *       that represents the GeneralizedTime value!
353                  *
354                  *       So if we store the UTCTime string in our ldb
355                  *       we'll loose information!
356                  */
357                 str = ldb_timestring_utc(out->values, t); 
358                 W_ERROR_HAVE_NO_MEMORY(str);
359                 out->values[i] = data_blob_string_const(str);
360         }
361
362         return WERR_OK;
363 }
364
365 static WERROR dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi(const struct dsdb_schema *schema,
366                                                     const struct dsdb_attribute *attr,
367                                                     const struct ldb_message_element *in,
368                                                     TALLOC_CTX *mem_ctx,
369                                                     struct drsuapi_DsReplicaAttribute *out)
370 {
371         uint32_t i;
372         DATA_BLOB *blobs;
373
374         if (attr->attributeID_id == 0xFFFFFFFF) {
375                 return WERR_FOOBAR;
376         }
377
378         out->attid                      = attr->attributeID_id;
379         out->value_ctr.num_values       = in->num_values;
380         out->value_ctr.values           = talloc_array(mem_ctx,
381                                                        struct drsuapi_DsAttributeValue,
382                                                        in->num_values);
383         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
384
385         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
386         W_ERROR_HAVE_NO_MEMORY(blobs);
387
388         for (i=0; i < in->num_values; i++) {
389                 NTTIME v;
390                 time_t t;
391
392                 out->value_ctr.values[i].blob   = &blobs[i];
393
394                 blobs[i] = data_blob_talloc(blobs, NULL, 8);
395                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
396
397                 t = ldb_string_utc_to_time((const char *)in->values[i].data);
398                 unix_to_nt_time(&v, t);
399                 v /= 10000000;
400
401                 SBVAL(blobs[i].data, 0, v);
402         }
403
404         return WERR_OK;
405 }
406
407 static WERROR dsdb_syntax_NTTIME_drsuapi_to_ldb(const struct dsdb_schema *schema,
408                                                 const struct dsdb_attribute *attr,
409                                                 const struct drsuapi_DsReplicaAttribute *in,
410                                                 TALLOC_CTX *mem_ctx,
411                                                 struct ldb_message_element *out)
412 {
413         uint32_t i;
414
415         out->flags      = 0;
416         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
417         W_ERROR_HAVE_NO_MEMORY(out->name);
418
419         out->num_values = in->value_ctr.num_values;
420         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
421         W_ERROR_HAVE_NO_MEMORY(out->values);
422
423         for (i=0; i < out->num_values; i++) {
424                 NTTIME v;
425                 time_t t;
426                 char *str;
427
428                 if (in->value_ctr.values[i].blob == NULL) {
429                         return WERR_FOOBAR;
430                 }
431
432                 if (in->value_ctr.values[i].blob->length != 8) {
433                         return WERR_FOOBAR;
434                 }
435
436                 v = BVAL(in->value_ctr.values[i].blob->data, 0);
437                 v *= 10000000;
438                 t = nt_time_to_unix(v);
439
440                 str = ldb_timestring(out->values, t); 
441                 W_ERROR_HAVE_NO_MEMORY(str);
442
443                 out->values[i] = data_blob_string_const(str);
444         }
445
446         return WERR_OK;
447 }
448
449 static WERROR dsdb_syntax_NTTIME_ldb_to_drsuapi(const struct dsdb_schema *schema,
450                                                 const struct dsdb_attribute *attr,
451                                                 const struct ldb_message_element *in,
452                                                 TALLOC_CTX *mem_ctx,
453                                                 struct drsuapi_DsReplicaAttribute *out)
454 {
455         uint32_t i;
456         DATA_BLOB *blobs;
457
458         if (attr->attributeID_id == 0xFFFFFFFF) {
459                 return WERR_FOOBAR;
460         }
461
462         out->attid                      = attr->attributeID_id;
463         out->value_ctr.num_values       = in->num_values;
464         out->value_ctr.values           = talloc_array(mem_ctx,
465                                                        struct drsuapi_DsAttributeValue,
466                                                        in->num_values);
467         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
468
469         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
470         W_ERROR_HAVE_NO_MEMORY(blobs);
471
472         for (i=0; i < in->num_values; i++) {
473                 NTTIME v;
474                 time_t t;
475
476                 out->value_ctr.values[i].blob   = &blobs[i];
477
478                 blobs[i] = data_blob_talloc(blobs, NULL, 8);
479                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
480
481                 t = ldb_string_to_time((const char *)in->values[i].data);
482                 unix_to_nt_time(&v, t);
483                 v /= 10000000;
484
485                 SBVAL(blobs[i].data, 0, v);
486         }
487
488         return WERR_OK;
489 }
490
491 static WERROR dsdb_syntax_DATA_BLOB_drsuapi_to_ldb(const struct dsdb_schema *schema,
492                                                    const struct dsdb_attribute *attr,
493                                                    const struct drsuapi_DsReplicaAttribute *in,
494                                                    TALLOC_CTX *mem_ctx,
495                                                    struct ldb_message_element *out)
496 {
497         uint32_t i;
498
499         out->flags      = 0;
500         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
501         W_ERROR_HAVE_NO_MEMORY(out->name);
502
503         out->num_values = in->value_ctr.num_values;
504         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
505         W_ERROR_HAVE_NO_MEMORY(out->values);
506
507         for (i=0; i < out->num_values; i++) {
508                 if (in->value_ctr.values[i].blob == NULL) {
509                         return WERR_FOOBAR;
510                 }
511
512                 if (in->value_ctr.values[i].blob->length == 0) {
513                         return WERR_FOOBAR;
514                 }
515
516                 out->values[i] = data_blob_dup_talloc(out->values,
517                                                       in->value_ctr.values[i].blob);
518                 W_ERROR_HAVE_NO_MEMORY(out->values[i].data);
519         }
520
521         return WERR_OK;
522 }
523
524 static WERROR dsdb_syntax_DATA_BLOB_ldb_to_drsuapi(const struct dsdb_schema *schema,
525                                                    const struct dsdb_attribute *attr,
526                                                    const struct ldb_message_element *in,
527                                                    TALLOC_CTX *mem_ctx,
528                                                    struct drsuapi_DsReplicaAttribute *out)
529 {
530         uint32_t i;
531         DATA_BLOB *blobs;
532
533         if (attr->attributeID_id == 0xFFFFFFFF) {
534                 return WERR_FOOBAR;
535         }
536
537         out->attid                      = attr->attributeID_id;
538         out->value_ctr.num_values       = in->num_values;
539         out->value_ctr.values           = talloc_array(mem_ctx,
540                                                        struct drsuapi_DsAttributeValue,
541                                                        in->num_values);
542         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
543
544         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
545         W_ERROR_HAVE_NO_MEMORY(blobs);
546
547         for (i=0; i < in->num_values; i++) {
548                 out->value_ctr.values[i].blob   = &blobs[i];
549
550                 blobs[i] = data_blob_dup_talloc(blobs, &in->values[i]);
551                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
552         }
553
554         return WERR_OK;
555 }
556
557 static WERROR _dsdb_syntax_OID_obj_drsuapi_to_ldb(const struct dsdb_schema *schema,
558                                                   const struct dsdb_attribute *attr,
559                                                   const struct drsuapi_DsReplicaAttribute *in,
560                                                   TALLOC_CTX *mem_ctx,
561                                                   struct ldb_message_element *out)
562 {
563         uint32_t i;
564
565         out->flags      = 0;
566         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
567         W_ERROR_HAVE_NO_MEMORY(out->name);
568
569         out->num_values = in->value_ctr.num_values;
570         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
571         W_ERROR_HAVE_NO_MEMORY(out->values);
572
573         for (i=0; i < out->num_values; i++) {
574                 uint32_t v;
575                 const struct dsdb_class *c;
576                 const char *str;
577
578                 if (in->value_ctr.values[i].blob == NULL) {
579                         return WERR_FOOBAR;
580                 }
581
582                 if (in->value_ctr.values[i].blob->length != 4) {
583                         return WERR_FOOBAR;
584                 }
585
586                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
587
588                 c = dsdb_class_by_governsID_id(schema, v);
589                 if (!c) {
590                         return WERR_FOOBAR;
591                 }
592
593                 str = talloc_strdup(out->values, c->lDAPDisplayName);
594                 W_ERROR_HAVE_NO_MEMORY(str);
595
596                 /* the values need to be reversed */
597                 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
598         }
599
600         return WERR_OK;
601 }
602
603 static WERROR _dsdb_syntax_OID_oid_drsuapi_to_ldb(const struct dsdb_schema *schema,
604                                                   const struct dsdb_attribute *attr,
605                                                   const struct drsuapi_DsReplicaAttribute *in,
606                                                   TALLOC_CTX *mem_ctx,
607                                                   struct ldb_message_element *out)
608 {
609         uint32_t i;
610
611         out->flags      = 0;
612         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
613         W_ERROR_HAVE_NO_MEMORY(out->name);
614
615         out->num_values = in->value_ctr.num_values;
616         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
617         W_ERROR_HAVE_NO_MEMORY(out->values);
618
619         for (i=0; i < out->num_values; i++) {
620                 uint32_t v;
621                 WERROR status;
622                 const char *str;
623
624                 if (in->value_ctr.values[i].blob == NULL) {
625                         return WERR_FOOBAR;
626                 }
627
628                 if (in->value_ctr.values[i].blob->length != 4) {
629                         return WERR_FOOBAR;
630                 }
631
632                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
633
634                 status = dsdb_map_int2oid(schema, v, out->values, &str);
635                 W_ERROR_NOT_OK_RETURN(status);
636
637                 out->values[i] = data_blob_string_const(str);
638         }
639
640         return WERR_OK;
641 }
642
643 static WERROR dsdb_syntax_OID_drsuapi_to_ldb(const struct dsdb_schema *schema,
644                                              const struct dsdb_attribute *attr,
645                                              const struct drsuapi_DsReplicaAttribute *in,
646                                              TALLOC_CTX *mem_ctx,
647                                              struct ldb_message_element *out)
648 {
649         uint32_t i;
650
651         switch (attr->attributeID_id) {
652         case DRSUAPI_ATTRIBUTE_objectClass:
653                 return _dsdb_syntax_OID_obj_drsuapi_to_ldb(schema, attr, in, mem_ctx, out);
654         case DRSUAPI_ATTRIBUTE_governsID:
655         case DRSUAPI_ATTRIBUTE_attributeID:
656         case DRSUAPI_ATTRIBUTE_attributeSyntax:
657                 return _dsdb_syntax_OID_oid_drsuapi_to_ldb(schema, attr, in, mem_ctx, out);
658         }
659
660         out->flags      = 0;
661         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
662         W_ERROR_HAVE_NO_MEMORY(out->name);
663
664         out->num_values = in->value_ctr.num_values;
665         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
666         W_ERROR_HAVE_NO_MEMORY(out->values);
667
668         for (i=0; i < out->num_values; i++) {
669                 uint32_t v;
670                 const char *name;
671                 char *str;
672
673                 if (in->value_ctr.values[i].blob == NULL) {
674                         return WERR_FOOBAR;
675                 }
676
677                 if (in->value_ctr.values[i].blob->length != 4) {
678                         return WERR_FOOBAR;
679                 }
680
681                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
682
683                 name = dsdb_lDAPDisplayName_by_id(schema, v);
684                 if (!name) {
685                         return WERR_FOOBAR;
686                 }
687
688                 str = talloc_strdup(out->values, name);
689                 W_ERROR_HAVE_NO_MEMORY(str);
690
691                 out->values[i] = data_blob_string_const(str);
692         }
693
694         return WERR_OK;
695 }
696
697 static WERROR dsdb_syntax_OID_ldb_to_drsuapi(const struct dsdb_schema *schema,
698                                              const struct dsdb_attribute *attr,
699                                              const struct ldb_message_element *in,
700                                              TALLOC_CTX *mem_ctx,
701                                              struct drsuapi_DsReplicaAttribute *out)
702 {
703         uint32_t i;
704         DATA_BLOB *blobs;
705
706         if (attr->attributeID_id == 0xFFFFFFFF) {
707                 return WERR_FOOBAR;
708         }
709
710         switch (attr->attributeID_id) {
711         case DRSUAPI_ATTRIBUTE_objectClass:
712         case DRSUAPI_ATTRIBUTE_governsID:
713         case DRSUAPI_ATTRIBUTE_attributeID:
714         case DRSUAPI_ATTRIBUTE_attributeSyntax:
715                 return dsdb_syntax_FOOBAR_ldb_to_drsuapi(schema, attr, in, mem_ctx, out);
716         }
717
718         out->attid                      = attr->attributeID_id;
719         out->value_ctr.num_values       = in->num_values;
720         out->value_ctr.values           = talloc_array(mem_ctx,
721                                                        struct drsuapi_DsAttributeValue,
722                                                        in->num_values);
723         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
724
725         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
726         W_ERROR_HAVE_NO_MEMORY(blobs);
727
728         for (i=0; i < in->num_values; i++) {
729                 uint32_t v;
730
731                 out->value_ctr.values[i].blob   = &blobs[i];
732
733                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
734                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
735
736                 v = strtol((const char *)in->values[i].data, NULL, 10);
737
738                 SIVAL(blobs[i].data, 0, v);
739         }
740
741         return WERR_OK;
742 }
743
744 static WERROR dsdb_syntax_UNICODE_drsuapi_to_ldb(const struct dsdb_schema *schema,
745                                                  const struct dsdb_attribute *attr,
746                                                  const struct drsuapi_DsReplicaAttribute *in,
747                                                  TALLOC_CTX *mem_ctx,
748                                                  struct ldb_message_element *out)
749 {
750         uint32_t i;
751
752         out->flags      = 0;
753         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
754         W_ERROR_HAVE_NO_MEMORY(out->name);
755
756         out->num_values = in->value_ctr.num_values;
757         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
758         W_ERROR_HAVE_NO_MEMORY(out->values);
759
760         for (i=0; i < out->num_values; i++) {
761                 ssize_t ret;
762                 char *str;
763
764                 if (in->value_ctr.values[i].blob == NULL) {
765                         return WERR_FOOBAR;
766                 }
767
768                 if (in->value_ctr.values[i].blob->length == 0) {
769                         return WERR_FOOBAR;
770                 }
771
772                 ret = convert_string_talloc(out->values, schema->iconv_convenience, 
773                                                                         CH_UTF16, CH_UNIX,
774                                             in->value_ctr.values[i].blob->data,
775                                             in->value_ctr.values[i].blob->length,
776                                             (void **)&str);
777                 if (ret == -1) {
778                         return WERR_FOOBAR;
779                 }
780
781                 out->values[i] = data_blob_string_const(str);
782         }
783
784         return WERR_OK;
785 }
786
787 static WERROR dsdb_syntax_UNICODE_ldb_to_drsuapi(const struct dsdb_schema *schema,
788                                                  const struct dsdb_attribute *attr,
789                                                  const struct ldb_message_element *in,
790                                                  TALLOC_CTX *mem_ctx,
791                                                  struct drsuapi_DsReplicaAttribute *out)
792 {
793         uint32_t i;
794         DATA_BLOB *blobs;
795
796         if (attr->attributeID_id == 0xFFFFFFFF) {
797                 return WERR_FOOBAR;
798         }
799
800         out->attid                      = attr->attributeID_id;
801         out->value_ctr.num_values       = in->num_values;
802         out->value_ctr.values           = talloc_array(mem_ctx,
803                                                        struct drsuapi_DsAttributeValue,
804                                                        in->num_values);
805         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
806
807         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
808         W_ERROR_HAVE_NO_MEMORY(blobs);
809
810         for (i=0; i < in->num_values; i++) {
811                 ssize_t ret;
812
813                 out->value_ctr.values[i].blob   = &blobs[i];
814
815                 ret = convert_string_talloc(blobs, schema->iconv_convenience, CH_UNIX, CH_UTF16,
816                                             in->values[i].data,
817                                             in->values[i].length,
818                                             (void **)&blobs[i].data);
819                 if (ret == -1) {
820                         return WERR_FOOBAR;
821                 }
822                 blobs[i].length = ret;
823         }
824
825         return WERR_OK;
826 }
827
828 static WERROR dsdb_syntax_DN_drsuapi_to_ldb(const struct dsdb_schema *schema,
829                                             const struct dsdb_attribute *attr,
830                                             const struct drsuapi_DsReplicaAttribute *in,
831                                             TALLOC_CTX *mem_ctx,
832                                             struct ldb_message_element *out)
833 {
834         uint32_t i;
835
836         out->flags      = 0;
837         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
838         W_ERROR_HAVE_NO_MEMORY(out->name);
839
840         out->num_values = in->value_ctr.num_values;
841         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
842         W_ERROR_HAVE_NO_MEMORY(out->values);
843
844         for (i=0; i < out->num_values; i++) {
845                 struct drsuapi_DsReplicaObjectIdentifier3 id3;
846                 enum ndr_err_code ndr_err;
847
848                 if (in->value_ctr.values[i].blob == NULL) {
849                         return WERR_FOOBAR;
850                 }
851
852                 if (in->value_ctr.values[i].blob->length == 0) {
853                         return WERR_FOOBAR;
854                 }
855
856                 ndr_err = ndr_pull_struct_blob_all(in->value_ctr.values[i].blob,
857                                                    out->values, schema->iconv_convenience, &id3,
858                                                    (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3);
859                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
860                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
861                         return ntstatus_to_werror(status);
862                 }
863
864                 /* TODO: handle id3.guid and id3.sid */
865                 out->values[i] = data_blob_string_const(id3.dn);
866         }
867
868         return WERR_OK;
869 }
870
871 static WERROR dsdb_syntax_DN_ldb_to_drsuapi(const struct dsdb_schema *schema,
872                                             const struct dsdb_attribute *attr,
873                                             const struct ldb_message_element *in,
874                                             TALLOC_CTX *mem_ctx,
875                                             struct drsuapi_DsReplicaAttribute *out)
876 {
877         uint32_t i;
878         DATA_BLOB *blobs;
879
880         if (attr->attributeID_id == 0xFFFFFFFF) {
881                 return WERR_FOOBAR;
882         }
883
884         out->attid                      = attr->attributeID_id;
885         out->value_ctr.num_values       = in->num_values;
886         out->value_ctr.values           = talloc_array(mem_ctx,
887                                                        struct drsuapi_DsAttributeValue,
888                                                        in->num_values);
889         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
890
891         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
892         W_ERROR_HAVE_NO_MEMORY(blobs);
893
894         for (i=0; i < in->num_values; i++) {
895                 struct drsuapi_DsReplicaObjectIdentifier3 id3;
896                 enum ndr_err_code ndr_err;
897
898                 out->value_ctr.values[i].blob   = &blobs[i];
899
900                 /* TODO: handle id3.guid and id3.sid */
901                 ZERO_STRUCT(id3);
902                 id3.dn = (const char *)in->values[i].data;
903
904                 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
905                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
906                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
907                         return ntstatus_to_werror(status);
908                 }
909         }
910
911         return WERR_OK;
912 }
913
914 static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(const struct dsdb_schema *schema,
915                                                    const struct dsdb_attribute *attr,
916                                                    const struct drsuapi_DsReplicaAttribute *in,
917                                                    TALLOC_CTX *mem_ctx,
918                                                    struct ldb_message_element *out)
919 {
920         uint32_t i;
921
922         out->flags      = 0;
923         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
924         W_ERROR_HAVE_NO_MEMORY(out->name);
925
926         out->num_values = in->value_ctr.num_values;
927         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
928         W_ERROR_HAVE_NO_MEMORY(out->values);
929
930         for (i=0; i < out->num_values; i++) {
931                 struct drsuapi_DsReplicaObjectIdentifier3Binary id3b;
932                 char *binary;
933                 char *str;
934                 enum ndr_err_code ndr_err;
935
936                 if (in->value_ctr.values[i].blob == NULL) {
937                         return WERR_FOOBAR;
938                 }
939
940                 if (in->value_ctr.values[i].blob->length == 0) {
941                         return WERR_FOOBAR;
942                 }
943
944                 ndr_err = ndr_pull_struct_blob_all(in->value_ctr.values[i].blob,
945                                                    out->values, schema->iconv_convenience, &id3b,
946                                                    (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3Binary);
947                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
948                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
949                         return ntstatus_to_werror(status);
950                 }
951
952                 /* TODO: handle id3.guid and id3.sid */
953                 binary = data_blob_hex_string(out->values, &id3b.binary);
954                 W_ERROR_HAVE_NO_MEMORY(binary);
955
956                 str = talloc_asprintf(out->values, "B:%u:%s:%s",
957                                       (unsigned int)(id3b.binary.length * 2), /* because of 2 hex chars per byte */
958                                       binary,
959                                       id3b.dn);
960                 W_ERROR_HAVE_NO_MEMORY(str);
961
962                 /* TODO: handle id3.guid and id3.sid */
963                 out->values[i] = data_blob_string_const(str);
964         }
965
966         return WERR_OK;
967 }
968
969 static WERROR dsdb_syntax_DN_BINARY_ldb_to_drsuapi(const struct dsdb_schema *schema,
970                                                    const struct dsdb_attribute *attr,
971                                                    const struct ldb_message_element *in,
972                                                    TALLOC_CTX *mem_ctx,
973                                                    struct drsuapi_DsReplicaAttribute *out)
974 {
975         uint32_t i;
976         DATA_BLOB *blobs;
977
978         if (attr->attributeID_id == 0xFFFFFFFF) {
979                 return WERR_FOOBAR;
980         }
981
982         out->attid                      = attr->attributeID_id;
983         out->value_ctr.num_values       = in->num_values;
984         out->value_ctr.values           = talloc_array(mem_ctx,
985                                                        struct drsuapi_DsAttributeValue,
986                                                        in->num_values);
987         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
988
989         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
990         W_ERROR_HAVE_NO_MEMORY(blobs);
991
992         for (i=0; i < in->num_values; i++) {
993                 struct drsuapi_DsReplicaObjectIdentifier3Binary id3b;
994                 enum ndr_err_code ndr_err;
995
996                 out->value_ctr.values[i].blob   = &blobs[i];
997
998                 /* TODO: handle id3b.guid and id3b.sid, id3.binary */
999                 ZERO_STRUCT(id3b);
1000                 id3b.dn         = (const char *)in->values[i].data;
1001                 id3b.binary     = data_blob(NULL, 0);
1002
1003                 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3b,
1004                                                (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3Binary);
1005                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1006                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1007                         return ntstatus_to_werror(status);
1008                 }
1009         }
1010
1011         return WERR_OK;
1012 }
1013
1014 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb(const struct dsdb_schema *schema,
1015                                                               const struct dsdb_attribute *attr,
1016                                                               const struct drsuapi_DsReplicaAttribute *in,
1017                                                               TALLOC_CTX *mem_ctx,
1018                                                               struct ldb_message_element *out)
1019 {
1020         uint32_t i;
1021
1022         out->flags      = 0;
1023         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1024         W_ERROR_HAVE_NO_MEMORY(out->name);
1025
1026         out->num_values = in->value_ctr.num_values;
1027         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1028         W_ERROR_HAVE_NO_MEMORY(out->values);
1029
1030         for (i=0; i < out->num_values; i++) {
1031                 uint32_t len;
1032                 ssize_t ret;
1033                 char *str;
1034
1035                 if (in->value_ctr.values[i].blob == NULL) {
1036                         return WERR_FOOBAR;
1037                 }
1038
1039                 if (in->value_ctr.values[i].blob->length < 4) {
1040                         return WERR_FOOBAR;
1041                 }
1042
1043                 len = IVAL(in->value_ctr.values[i].blob->data, 0);
1044
1045                 if (len != in->value_ctr.values[i].blob->length) {
1046                         return WERR_FOOBAR;
1047                 }
1048
1049                 ret = convert_string_talloc(out->values, schema->iconv_convenience, CH_UTF16, CH_UNIX,
1050                                             in->value_ctr.values[i].blob->data+4,
1051                                             in->value_ctr.values[i].blob->length-4,
1052                                             (void **)&str);
1053                 if (ret == -1) {
1054                         return WERR_FOOBAR;
1055                 }
1056
1057                 out->values[i] = data_blob_string_const(str);
1058         }
1059
1060         return WERR_OK;
1061 }
1062
1063 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi(const struct dsdb_schema *schema,
1064                                                               const struct dsdb_attribute *attr,
1065                                                               const struct ldb_message_element *in,
1066                                                               TALLOC_CTX *mem_ctx,
1067                                                               struct drsuapi_DsReplicaAttribute *out)
1068 {
1069         uint32_t i;
1070         DATA_BLOB *blobs;
1071
1072         if (attr->attributeID_id == 0xFFFFFFFF) {
1073                 return WERR_FOOBAR;
1074         }
1075
1076         out->attid                      = attr->attributeID_id;
1077         out->value_ctr.num_values       = in->num_values;
1078         out->value_ctr.values           = talloc_array(mem_ctx,
1079                                                        struct drsuapi_DsAttributeValue,
1080                                                        in->num_values);
1081         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1082
1083         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1084         W_ERROR_HAVE_NO_MEMORY(blobs);
1085
1086         for (i=0; i < in->num_values; i++) {
1087                 uint8_t *data;
1088                 ssize_t ret;
1089
1090                 out->value_ctr.values[i].blob   = &blobs[i];
1091
1092                 ret = convert_string_talloc(blobs, schema->iconv_convenience, CH_UNIX, CH_UTF16,
1093                                             in->values[i].data,
1094                                             in->values[i].length,
1095                                             (void **)&data);
1096                 if (ret == -1) {
1097                         return WERR_FOOBAR;
1098                 }
1099
1100                 blobs[i] = data_blob_talloc(blobs, NULL, 4 + ret);
1101                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1102
1103                 SIVAL(blobs[i].data, 0, 4 + ret);
1104
1105                 if (ret > 0) {
1106                         memcpy(blobs[i].data + 4, data, ret);
1107                         talloc_free(data);
1108                 }
1109         }
1110
1111         return WERR_OK;
1112 }
1113
1114 #define OMOBJECTCLASS(val) { .length = sizeof(val) - 1, .data = discard_const_p(uint8_t, val) }
1115
1116 static const struct dsdb_syntax dsdb_syntaxes[] = {
1117         {
1118                 .name                   = "Boolean",
1119                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.7",
1120                 .oMSyntax               = 1,
1121                 .attributeSyntax_oid    = "2.5.5.8",
1122                 .drsuapi_to_ldb         = dsdb_syntax_BOOL_drsuapi_to_ldb,
1123                 .ldb_to_drsuapi         = dsdb_syntax_BOOL_ldb_to_drsuapi,
1124                 .equality               = "booleanMatch",
1125                 .comment                = "Boolean" 
1126         },{
1127                 .name                   = "Integer",
1128                 .ldap_oid               = LDB_SYNTAX_INTEGER,
1129                 .oMSyntax               = 2,
1130                 .attributeSyntax_oid    = "2.5.5.9",
1131                 .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
1132                 .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
1133                 .equality               = "integerMatch",
1134                 .comment                = "Integer",
1135         },{
1136                 .name                   = "String(Octet)",
1137                 .ldap_oid               = LDB_SYNTAX_OCTET_STRING,
1138                 .oMSyntax               = 4,
1139                 .attributeSyntax_oid    = "2.5.5.10",
1140                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1141                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1142                 .equality               = "octetStringMatch",
1143                 .comment                = "Octet String",
1144         },{
1145                 .name                   = "String(Sid)",
1146                 .ldap_oid               = LDB_SYNTAX_OCTET_STRING,
1147                 .oMSyntax               = 4,
1148                 .attributeSyntax_oid    = "2.5.5.17",
1149                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1150                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1151                 .equality               = "octetStringMatch",
1152                 .comment                = "Octet String - Security Identifier (SID)",
1153                 .ldb_syntax             = LDB_SYNTAX_SAMBA_SID
1154         },{
1155                 .name                   = "String(Object-Identifier)",
1156                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.38",
1157                 .oMSyntax               = 6,
1158                 .attributeSyntax_oid    = "2.5.5.2",
1159                 .drsuapi_to_ldb         = dsdb_syntax_OID_drsuapi_to_ldb,
1160                 .ldb_to_drsuapi         = dsdb_syntax_OID_ldb_to_drsuapi,
1161                 .equality               = "caseIgnoreMatch", /* Would use "objectIdentifierMatch" but most are ldap attribute/class names */
1162                 .comment                = "OID String",
1163                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING
1164         },{
1165                 .name                   = "Enumeration",
1166                 .ldap_oid               = LDB_SYNTAX_INTEGER,
1167                 .oMSyntax               = 10,
1168                 .attributeSyntax_oid    = "2.5.5.9",
1169                 .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
1170                 .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
1171         },{
1172         /* not used in w2k3 forest */
1173                 .name                   = "String(Numeric)",
1174                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.36",
1175                 .oMSyntax               = 18,
1176                 .attributeSyntax_oid    = "2.5.5.6",
1177                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1178                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1179                 .equality               = "numericStringMatch",
1180                 .substring              = "numericStringSubstringsMatch",
1181                 .comment                = "Numeric String" 
1182         },{
1183                 .name                   = "String(Printable)",
1184                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.44",
1185                 .oMSyntax               = 19,
1186                 .attributeSyntax_oid    = "2.5.5.5",
1187                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1188                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1189         },{
1190                 .name                   = "String(Teletex)",
1191                 .ldap_oid               = "1.2.840.113556.1.4.905",
1192                 .oMSyntax               = 20,
1193                 .attributeSyntax_oid    = "2.5.5.4",
1194                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1195                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1196                 .equality               = "caseIgnoreMatch",
1197                 .substring              = "caseIgnoreSubstringsMatch",
1198                 .comment                = "Case Insensitive String",
1199                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1200         },{
1201                 .name                   = "String(IA5)",
1202                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.26",
1203                 .oMSyntax               = 22,
1204                 .attributeSyntax_oid    = "2.5.5.5",
1205                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1206                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1207                 .equality               = "caseExactIA5Match",
1208                 .comment                = "Printable String"
1209         },{
1210                 .name                   = "String(UTC-Time)",
1211                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.53",
1212                 .oMSyntax               = 23,
1213                 .attributeSyntax_oid    = "2.5.5.11",
1214                 .drsuapi_to_ldb         = dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb,
1215                 .ldb_to_drsuapi         = dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi,
1216                 .equality               = "generalizedTimeMatch",
1217                 .comment                = "UTC Time",
1218         },{
1219                 .name                   = "String(Generalized-Time)",
1220                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.24",
1221                 .oMSyntax               = 24,
1222                 .attributeSyntax_oid    = "2.5.5.11",
1223                 .drsuapi_to_ldb         = dsdb_syntax_NTTIME_drsuapi_to_ldb,
1224                 .ldb_to_drsuapi         = dsdb_syntax_NTTIME_ldb_to_drsuapi,
1225                 .equality               = "generalizedTimeMatch",
1226                 .comment                = "Generalized Time",
1227                 .ldb_syntax             = LDB_SYNTAX_UTC_TIME,
1228         },{
1229         /* not used in w2k3 schema */
1230                 .name                   = "String(Case Sensitive)",
1231                 .ldap_oid               = "1.2.840.113556.1.4.1362",
1232                 .oMSyntax               = 27,
1233                 .attributeSyntax_oid    = "2.5.5.3",
1234                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1235                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1236         },{
1237                 .name                   = "String(Unicode)",
1238                 .ldap_oid               = LDB_SYNTAX_DIRECTORY_STRING,
1239                 .oMSyntax               = 64,
1240                 .attributeSyntax_oid    = "2.5.5.12",
1241                 .drsuapi_to_ldb         = dsdb_syntax_UNICODE_drsuapi_to_ldb,
1242                 .ldb_to_drsuapi         = dsdb_syntax_UNICODE_ldb_to_drsuapi,
1243                 .equality               = "caseIgnoreMatch",
1244                 .substring              = "caseIgnoreSubstringsMatch",
1245                 .comment                = "Directory String",
1246         },{
1247                 .name                   = "Interval/LargeInteger",
1248                 .ldap_oid               = "1.2.840.113556.1.4.906",
1249                 .oMSyntax               = 65,
1250                 .attributeSyntax_oid    = "2.5.5.16",
1251                 .drsuapi_to_ldb         = dsdb_syntax_INT64_drsuapi_to_ldb,
1252                 .ldb_to_drsuapi         = dsdb_syntax_INT64_ldb_to_drsuapi,
1253                 .equality               = "integerMatch",
1254                 .comment                = "Large Integer",
1255                 .ldb_syntax             = LDB_SYNTAX_INTEGER,
1256         },{
1257                 .name                   = "String(NT-Sec-Desc)",
1258                 .ldap_oid               = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1259                 .oMSyntax               = 66,
1260                 .attributeSyntax_oid    = "2.5.5.15",
1261                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1262                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1263         },{
1264                 .name                   = "Object(DS-DN)",
1265                 .ldap_oid               = LDB_SYNTAX_DN,
1266                 .oMSyntax               = 127,
1267                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x4a"),
1268                 .attributeSyntax_oid    = "2.5.5.1",
1269                 .drsuapi_to_ldb         = dsdb_syntax_DN_drsuapi_to_ldb,
1270                 .ldb_to_drsuapi         = dsdb_syntax_DN_ldb_to_drsuapi,
1271                 .equality               = "distinguishedNameMatch",
1272                 .comment                = "Object(DS-DN) == a DN",
1273         },{
1274                 .name                   = "Object(DN-Binary)",
1275                 .ldap_oid               = "1.2.840.113556.1.4.903",
1276                 .oMSyntax               = 127,
1277                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0b"),
1278                 .attributeSyntax_oid    = "2.5.5.7",
1279                 .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
1280                 .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
1281                 .equality               = "distinguishedNameMatch",
1282                 .comment                = "OctetString: Binary+DN",
1283                 .ldb_syntax             = LDB_SYNTAX_DN,
1284         },{
1285         /* not used in w2k3 schema */
1286                 .name                   = "Object(OR-Name)",
1287                 .ldap_oid               = "1.2.840.113556.1.4.1221",
1288                 .oMSyntax               = 127,
1289                 .oMObjectClass          = OMOBJECTCLASS("\x56\x06\x01\x02\x05\x0b\x1D"),
1290                 .attributeSyntax_oid    = "2.5.5.7",
1291                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1292                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1293         },{
1294         /* 
1295          * TODO: verify if DATA_BLOB is correct here...!
1296          *
1297          *       repsFrom and repsTo are the only attributes using
1298          *       this attribute syntax, but they're not replicated... 
1299          */
1300                 .name                   = "Object(Replica-Link)",
1301                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.40",
1302                 .oMSyntax               = 127,
1303                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x06"),
1304                 .attributeSyntax_oid    = "2.5.5.10",
1305                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1306                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1307         },{
1308                 .name                   = "Object(Presentation-Address)",
1309                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.43",
1310                 .oMSyntax               = 127,
1311                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x5c"),
1312                 .attributeSyntax_oid    = "2.5.5.13",
1313                 .drsuapi_to_ldb         = dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb,
1314                 .ldb_to_drsuapi         = dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi,
1315                 .comment                = "Presentation Address" 
1316         },{
1317         /* not used in w2k3 schema */
1318                 .name                   = "Object(Access-Point)",
1319                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.2",
1320                 .oMSyntax               = 127,
1321                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x3e"),
1322                 .attributeSyntax_oid    = "2.5.5.14",
1323                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1324                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1325                 .equality               = "distinguishedNameMatch",
1326                 .comment                = "OctetString: String+DN",
1327                 .ldb_syntax             = LDB_SYNTAX_DN,
1328         },{
1329         /* not used in w2k3 schema */
1330                 .name                   = "Object(DN-String)",
1331                 .ldap_oid               = "1.2.840.113556.1.4.904",
1332                 .oMSyntax               = 127,
1333                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0c"),
1334                 .attributeSyntax_oid    = "2.5.5.14",
1335                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1336                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1337                 .ldb_syntax             = LDB_SYNTAX_DN,
1338         }
1339 };
1340
1341 const struct dsdb_syntax *find_syntax_map_by_ad_oid(const char *ad_oid) 
1342 {
1343         int i;
1344         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1345                 if (strcasecmp(ad_oid, dsdb_syntaxes[i].attributeSyntax_oid) == 0) {
1346                         return &dsdb_syntaxes[i];
1347                 }
1348         }
1349         return NULL;
1350 }
1351
1352 const struct dsdb_syntax *find_syntax_map_by_ad_syntax(int oMSyntax) 
1353 {
1354         int i;
1355         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1356                 if (oMSyntax == dsdb_syntaxes[i].oMSyntax) {
1357                         return &dsdb_syntaxes[i];
1358                 }
1359         }
1360         return NULL;
1361 }
1362
1363 const struct dsdb_syntax *find_syntax_map_by_standard_oid(const char *standard_oid) 
1364 {
1365         int i;
1366         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1367                 if (strcasecmp(standard_oid, dsdb_syntaxes[i].ldap_oid) == 0) {
1368                         return &dsdb_syntaxes[i];
1369                 }
1370         }
1371         return NULL;
1372 }
1373 const struct dsdb_syntax *dsdb_syntax_for_attribute(const struct dsdb_attribute *attr)
1374 {
1375         uint32_t i;
1376
1377         for (i=0; i < ARRAY_SIZE(dsdb_syntaxes); i++) {
1378                 if (attr->oMSyntax != dsdb_syntaxes[i].oMSyntax) continue;
1379
1380                 if (attr->oMObjectClass.length != dsdb_syntaxes[i].oMObjectClass.length) continue;
1381
1382                 if (attr->oMObjectClass.length) {
1383                         int ret;
1384                         ret = memcmp(attr->oMObjectClass.data,
1385                                      dsdb_syntaxes[i].oMObjectClass.data,
1386                                      attr->oMObjectClass.length);
1387                         if (ret != 0) continue;
1388                 }
1389
1390                 if (strcmp(attr->attributeSyntax_oid, dsdb_syntaxes[i].attributeSyntax_oid) != 0) continue;
1391
1392                 return &dsdb_syntaxes[i];
1393         }
1394
1395         return NULL;
1396 }
1397
1398 WERROR dsdb_attribute_drsuapi_to_ldb(const struct dsdb_schema *schema,
1399                                      const struct drsuapi_DsReplicaAttribute *in,
1400                                      TALLOC_CTX *mem_ctx,
1401                                      struct ldb_message_element *out)
1402 {
1403         const struct dsdb_attribute *sa;
1404
1405         sa = dsdb_attribute_by_attributeID_id(schema, in->attid);
1406         if (!sa) {
1407                 return WERR_FOOBAR;
1408         }
1409
1410         return sa->syntax->drsuapi_to_ldb(schema, sa, in, mem_ctx, out);
1411 }
1412
1413 WERROR dsdb_attribute_ldb_to_drsuapi(const struct dsdb_schema *schema,
1414                                      const struct ldb_message_element *in,
1415                                      TALLOC_CTX *mem_ctx,
1416                                      struct drsuapi_DsReplicaAttribute *out)
1417 {
1418         const struct dsdb_attribute *sa;
1419
1420         sa = dsdb_attribute_by_lDAPDisplayName(schema, in->name);
1421         if (!sa) {
1422                 return WERR_FOOBAR;
1423         }
1424
1425         return sa->syntax->ldb_to_drsuapi(schema, sa, in, mem_ctx, out);
1426 }