3805df64635dff91d4ea0c22a0c51dcdda7014e5
[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_FOOBAR_validate_ldb(struct ldb_context *ldb,
79                                               const struct dsdb_schema *schema,
80                                               const struct dsdb_attribute *attr,
81                                               const struct ldb_message_element *in)
82 {
83         return WERR_FOOBAR;
84 }
85
86 static WERROR dsdb_syntax_ALLOW_validate_ldb(struct ldb_context *ldb,
87                                              const struct dsdb_schema *schema,
88                                              const struct dsdb_attribute *attr,
89                                              const struct ldb_message_element *in)
90 {
91         if (attr->attributeID_id == 0xFFFFFFFF) {
92                 return WERR_FOOBAR;
93         }
94
95         return WERR_OK;
96 }
97
98 static WERROR dsdb_syntax_BOOL_drsuapi_to_ldb(struct ldb_context *ldb, 
99                                               const struct dsdb_schema *schema,
100                                               const struct dsdb_attribute *attr,
101                                               const struct drsuapi_DsReplicaAttribute *in,
102                                               TALLOC_CTX *mem_ctx,
103                                               struct ldb_message_element *out)
104 {
105         uint32_t i;
106
107         out->flags      = 0;
108         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
109         W_ERROR_HAVE_NO_MEMORY(out->name);
110
111         out->num_values = in->value_ctr.num_values;
112         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
113         W_ERROR_HAVE_NO_MEMORY(out->values);
114
115         for (i=0; i < out->num_values; i++) {
116                 uint32_t v;
117                 char *str;
118
119                 if (in->value_ctr.values[i].blob == NULL) {
120                         return WERR_FOOBAR;
121                 }
122
123                 if (in->value_ctr.values[i].blob->length != 4) {
124                         return WERR_FOOBAR;
125                 }
126
127                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
128
129                 if (v != 0) {
130                         str = talloc_strdup(out->values, "TRUE");
131                         W_ERROR_HAVE_NO_MEMORY(str);
132                 } else {
133                         str = talloc_strdup(out->values, "FALSE");
134                         W_ERROR_HAVE_NO_MEMORY(str);
135                 }
136
137                 out->values[i] = data_blob_string_const(str);
138         }
139
140         return WERR_OK;
141 }
142
143 static WERROR dsdb_syntax_BOOL_ldb_to_drsuapi(struct ldb_context *ldb, 
144                                               const struct dsdb_schema *schema,
145                                               const struct dsdb_attribute *attr,
146                                               const struct ldb_message_element *in,
147                                               TALLOC_CTX *mem_ctx,
148                                               struct drsuapi_DsReplicaAttribute *out)
149 {
150         uint32_t i;
151         DATA_BLOB *blobs;
152
153         if (attr->attributeID_id == 0xFFFFFFFF) {
154                 return WERR_FOOBAR;
155         }
156
157         out->attid                      = attr->attributeID_id;
158         out->value_ctr.num_values       = in->num_values;
159         out->value_ctr.values           = talloc_array(mem_ctx,
160                                                        struct drsuapi_DsAttributeValue,
161                                                        in->num_values);
162         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
163
164         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
165         W_ERROR_HAVE_NO_MEMORY(blobs);
166
167         for (i=0; i < in->num_values; i++) {
168                 out->value_ctr.values[i].blob   = &blobs[i];
169
170                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
171                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
172
173                 if (strcmp("TRUE", (const char *)in->values[i].data) == 0) {
174                         SIVAL(blobs[i].data, 0, 0x00000001);
175                 } else if (strcmp("FALSE", (const char *)in->values[i].data) == 0) {
176                         SIVAL(blobs[i].data, 0, 0x00000000);
177                 } else {
178                         return WERR_FOOBAR;
179                 }
180         }
181
182         return WERR_OK;
183 }
184
185 static WERROR dsdb_syntax_BOOL_validate_ldb(struct ldb_context *ldb,
186                                             const struct dsdb_schema *schema,
187                                             const struct dsdb_attribute *attr,
188                                             const struct ldb_message_element *in)
189 {
190         uint32_t i;
191
192         if (attr->attributeID_id == 0xFFFFFFFF) {
193                 return WERR_FOOBAR;
194         }
195
196         for (i=0; i < in->num_values; i++) {
197                 int t, f;
198
199                 t = strncmp("TRUE",
200                             (const char *)in->values[i].data,
201                             in->values[i].length);
202                 f = strncmp("FALSE",
203                             (const char *)in->values[i].data,
204                             in->values[i].length);
205
206                 if (t != 0 && f != 0) {
207                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
208                 }
209         }
210
211         return WERR_OK;
212 }
213
214 static WERROR dsdb_syntax_INT32_drsuapi_to_ldb(struct ldb_context *ldb, 
215                                                const struct dsdb_schema *schema,
216                                                const struct dsdb_attribute *attr,
217                                                const struct drsuapi_DsReplicaAttribute *in,
218                                                TALLOC_CTX *mem_ctx,
219                                                struct ldb_message_element *out)
220 {
221         uint32_t i;
222
223         out->flags      = 0;
224         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
225         W_ERROR_HAVE_NO_MEMORY(out->name);
226
227         out->num_values = in->value_ctr.num_values;
228         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
229         W_ERROR_HAVE_NO_MEMORY(out->values);
230
231         for (i=0; i < out->num_values; i++) {
232                 int32_t v;
233                 char *str;
234
235                 if (in->value_ctr.values[i].blob == NULL) {
236                         return WERR_FOOBAR;
237                 }
238
239                 if (in->value_ctr.values[i].blob->length != 4) {
240                         return WERR_FOOBAR;
241                 }
242
243                 v = IVALS(in->value_ctr.values[i].blob->data, 0);
244
245                 str = talloc_asprintf(out->values, "%d", v);
246                 W_ERROR_HAVE_NO_MEMORY(str);
247
248                 out->values[i] = data_blob_string_const(str);
249         }
250
251         return WERR_OK;
252 }
253
254 static WERROR dsdb_syntax_INT32_ldb_to_drsuapi(struct ldb_context *ldb, 
255                                                const struct dsdb_schema *schema,
256                                                const struct dsdb_attribute *attr,
257                                                const struct ldb_message_element *in,
258                                                TALLOC_CTX *mem_ctx,
259                                                struct drsuapi_DsReplicaAttribute *out)
260 {
261         uint32_t i;
262         DATA_BLOB *blobs;
263
264         if (attr->attributeID_id == 0xFFFFFFFF) {
265                 return WERR_FOOBAR;
266         }
267
268         out->attid                      = attr->attributeID_id;
269         out->value_ctr.num_values       = in->num_values;
270         out->value_ctr.values           = talloc_array(mem_ctx,
271                                                        struct drsuapi_DsAttributeValue,
272                                                        in->num_values);
273         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
274
275         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
276         W_ERROR_HAVE_NO_MEMORY(blobs);
277
278         for (i=0; i < in->num_values; i++) {
279                 int32_t v;
280
281                 out->value_ctr.values[i].blob   = &blobs[i];
282
283                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
284                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
285
286                 /* We've to use "strtoll" here to have the intended overflows.
287                  * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
288                 v = (int32_t) strtoll((char *)in->values[i].data, NULL, 0);
289
290                 SIVALS(blobs[i].data, 0, v);
291         }
292
293         return WERR_OK;
294 }
295
296 static WERROR dsdb_syntax_INT32_validate_ldb(struct ldb_context *ldb,
297                                              const struct dsdb_schema *schema,
298                                              const struct dsdb_attribute *attr,
299                                              const struct ldb_message_element *in)
300 {
301         uint32_t i;
302
303         if (attr->attributeID_id == 0xFFFFFFFF) {
304                 return WERR_FOOBAR;
305         }
306
307         for (i=0; i < in->num_values; i++) {
308                 long v;
309                 char buf[sizeof("-2147483648")];
310                 char *end = NULL;
311
312                 ZERO_STRUCT(buf);
313                 if (in->values[i].length >= sizeof(buf)) {
314                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
315                 }
316
317                 memcpy(buf, in->values[i].data, in->values[i].length);
318                 errno = 0;
319                 v = strtol(buf, &end, 10);
320                 if (errno != 0) {
321                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
322                 }
323                 if (end && end[0] != '\0') {
324                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
325                 }
326
327                 if (attr->rangeLower) {
328                         if ((int32_t)v < (int32_t)*attr->rangeLower) {
329                                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
330                         }
331                 }
332
333                 if (attr->rangeUpper) {
334                         if ((int32_t)v > (int32_t)*attr->rangeUpper) {
335                                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
336                         }
337                 }
338         }
339
340         return WERR_OK;
341 }
342
343 static WERROR dsdb_syntax_INT64_drsuapi_to_ldb(struct ldb_context *ldb, 
344                                                const struct dsdb_schema *schema,
345                                                const struct dsdb_attribute *attr,
346                                                const struct drsuapi_DsReplicaAttribute *in,
347                                                TALLOC_CTX *mem_ctx,
348                                                struct ldb_message_element *out)
349 {
350         uint32_t i;
351
352         out->flags      = 0;
353         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
354         W_ERROR_HAVE_NO_MEMORY(out->name);
355
356         out->num_values = in->value_ctr.num_values;
357         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
358         W_ERROR_HAVE_NO_MEMORY(out->values);
359
360         for (i=0; i < out->num_values; i++) {
361                 int64_t v;
362                 char *str;
363
364                 if (in->value_ctr.values[i].blob == NULL) {
365                         return WERR_FOOBAR;
366                 }
367
368                 if (in->value_ctr.values[i].blob->length != 8) {
369                         return WERR_FOOBAR;
370                 }
371
372                 v = BVALS(in->value_ctr.values[i].blob->data, 0);
373
374                 str = talloc_asprintf(out->values, "%lld", (long long int)v);
375                 W_ERROR_HAVE_NO_MEMORY(str);
376
377                 out->values[i] = data_blob_string_const(str);
378         }
379
380         return WERR_OK;
381 }
382
383 static WERROR dsdb_syntax_INT64_ldb_to_drsuapi(struct ldb_context *ldb, 
384                                                const struct dsdb_schema *schema,
385                                                const struct dsdb_attribute *attr,
386                                                const struct ldb_message_element *in,
387                                                TALLOC_CTX *mem_ctx,
388                                                struct drsuapi_DsReplicaAttribute *out)
389 {
390         uint32_t i;
391         DATA_BLOB *blobs;
392
393         if (attr->attributeID_id == 0xFFFFFFFF) {
394                 return WERR_FOOBAR;
395         }
396
397         out->attid                      = attr->attributeID_id;
398         out->value_ctr.num_values       = in->num_values;
399         out->value_ctr.values           = talloc_array(mem_ctx,
400                                                        struct drsuapi_DsAttributeValue,
401                                                        in->num_values);
402         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
403
404         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
405         W_ERROR_HAVE_NO_MEMORY(blobs);
406
407         for (i=0; i < in->num_values; i++) {
408                 int64_t v;
409
410                 out->value_ctr.values[i].blob   = &blobs[i];
411
412                 blobs[i] = data_blob_talloc(blobs, NULL, 8);
413                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
414
415                 v = strtoll((const char *)in->values[i].data, NULL, 10);
416
417                 SBVALS(blobs[i].data, 0, v);
418         }
419
420         return WERR_OK;
421 }
422
423 static WERROR dsdb_syntax_INT64_validate_ldb(struct ldb_context *ldb,
424                                              const struct dsdb_schema *schema,
425                                              const struct dsdb_attribute *attr,
426                                              const struct ldb_message_element *in)
427 {
428         uint32_t i;
429
430         if (attr->attributeID_id == 0xFFFFFFFF) {
431                 return WERR_FOOBAR;
432         }
433
434         for (i=0; i < in->num_values; i++) {
435                 long long v;
436                 char buf[sizeof("-9223372036854775808")];
437                 char *end = NULL;
438
439                 ZERO_STRUCT(buf);
440                 if (in->values[i].length >= sizeof(buf)) {
441                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
442                 }
443                 memcpy(buf, in->values[i].data, in->values[i].length);
444
445                 errno = 0;
446                 v = strtoll(buf, &end, 10);
447                 if (errno != 0) {
448                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
449                 }
450                 if (end && end[0] != '\0') {
451                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
452                 }
453
454                 if (attr->rangeLower) {
455                         if ((int64_t)v < (int64_t)*attr->rangeLower) {
456                                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
457                         }
458                 }
459
460                 if (attr->rangeUpper) {
461                         if ((int64_t)v > (int64_t)*attr->rangeUpper) {
462                                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
463                         }
464                 }
465         }
466
467         return WERR_OK;
468 }
469 static WERROR dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb(struct ldb_context *ldb, 
470                                                     const struct dsdb_schema *schema,
471                                                     const struct dsdb_attribute *attr,
472                                                     const struct drsuapi_DsReplicaAttribute *in,
473                                                     TALLOC_CTX *mem_ctx,
474                                                     struct ldb_message_element *out)
475 {
476         uint32_t i;
477
478         out->flags      = 0;
479         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
480         W_ERROR_HAVE_NO_MEMORY(out->name);
481
482         out->num_values = in->value_ctr.num_values;
483         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
484         W_ERROR_HAVE_NO_MEMORY(out->values);
485
486         for (i=0; i < out->num_values; i++) {
487                 NTTIME v;
488                 time_t t;
489                 char *str;
490
491                 if (in->value_ctr.values[i].blob == NULL) {
492                         return WERR_FOOBAR;
493                 }
494
495                 if (in->value_ctr.values[i].blob->length != 8) {
496                         return WERR_FOOBAR;
497                 }
498
499                 v = BVAL(in->value_ctr.values[i].blob->data, 0);
500                 v *= 10000000;
501                 t = nt_time_to_unix(v);
502
503                 /* 
504                  * NOTE: On a w2k3 server you can set a GeneralizedTime string
505                  *       via LDAP, but you get back an UTCTime string,
506                  *       but via DRSUAPI you get back the NTTIME_1sec value
507                  *       that represents the GeneralizedTime value!
508                  *
509                  *       So if we store the UTCTime string in our ldb
510                  *       we'll loose information!
511                  */
512                 str = ldb_timestring_utc(out->values, t); 
513                 W_ERROR_HAVE_NO_MEMORY(str);
514                 out->values[i] = data_blob_string_const(str);
515         }
516
517         return WERR_OK;
518 }
519
520 static WERROR dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi(struct ldb_context *ldb, 
521                                                     const struct dsdb_schema *schema,
522                                                     const struct dsdb_attribute *attr,
523                                                     const struct ldb_message_element *in,
524                                                     TALLOC_CTX *mem_ctx,
525                                                     struct drsuapi_DsReplicaAttribute *out)
526 {
527         uint32_t i;
528         DATA_BLOB *blobs;
529
530         if (attr->attributeID_id == 0xFFFFFFFF) {
531                 return WERR_FOOBAR;
532         }
533
534         out->attid                      = attr->attributeID_id;
535         out->value_ctr.num_values       = in->num_values;
536         out->value_ctr.values           = talloc_array(mem_ctx,
537                                                        struct drsuapi_DsAttributeValue,
538                                                        in->num_values);
539         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
540
541         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
542         W_ERROR_HAVE_NO_MEMORY(blobs);
543
544         for (i=0; i < in->num_values; i++) {
545                 NTTIME v;
546                 time_t t;
547
548                 out->value_ctr.values[i].blob   = &blobs[i];
549
550                 blobs[i] = data_blob_talloc(blobs, NULL, 8);
551                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
552
553                 t = ldb_string_utc_to_time((const char *)in->values[i].data);
554                 unix_to_nt_time(&v, t);
555                 v /= 10000000;
556
557                 SBVAL(blobs[i].data, 0, v);
558         }
559
560         return WERR_OK;
561 }
562
563 static WERROR dsdb_syntax_NTTIME_UTC_validate_ldb(struct ldb_context *ldb,
564                                                   const struct dsdb_schema *schema,
565                                                   const struct dsdb_attribute *attr,
566                                                   const struct ldb_message_element *in)
567 {
568         uint32_t i;
569
570         if (attr->attributeID_id == 0xFFFFFFFF) {
571                 return WERR_FOOBAR;
572         }
573
574         for (i=0; i < in->num_values; i++) {
575                 time_t t;
576                 char buf[sizeof("090826075717Z")];
577
578                 ZERO_STRUCT(buf);
579                 if (in->values[i].length >= sizeof(buf)) {
580                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
581                 }
582                 memcpy(buf, in->values[i].data, in->values[i].length);
583
584                 errno = 0;
585                 t = ldb_string_utc_to_time(buf);
586                 if (errno != 0) {
587                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
588                 }
589
590                 if (attr->rangeLower) {
591                         if ((int32_t)t < (int32_t)*attr->rangeLower) {
592                                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
593                         }
594                 }
595
596                 if (attr->rangeUpper) {
597                         if ((int32_t)t > (int32_t)*attr->rangeLower) {
598                                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
599                         }
600                 }
601
602                 /*
603                  * TODO: verify the comment in the
604                  * dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb() function!
605                  */
606         }
607
608         return WERR_OK;
609 }
610
611 static WERROR dsdb_syntax_NTTIME_drsuapi_to_ldb(struct ldb_context *ldb, 
612                                                 const struct dsdb_schema *schema,
613                                                 const struct dsdb_attribute *attr,
614                                                 const struct drsuapi_DsReplicaAttribute *in,
615                                                 TALLOC_CTX *mem_ctx,
616                                                 struct ldb_message_element *out)
617 {
618         uint32_t i;
619
620         out->flags      = 0;
621         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
622         W_ERROR_HAVE_NO_MEMORY(out->name);
623
624         out->num_values = in->value_ctr.num_values;
625         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
626         W_ERROR_HAVE_NO_MEMORY(out->values);
627
628         for (i=0; i < out->num_values; i++) {
629                 NTTIME v;
630                 time_t t;
631                 char *str;
632
633                 if (in->value_ctr.values[i].blob == NULL) {
634                         return WERR_FOOBAR;
635                 }
636
637                 if (in->value_ctr.values[i].blob->length != 8) {
638                         return WERR_FOOBAR;
639                 }
640
641                 v = BVAL(in->value_ctr.values[i].blob->data, 0);
642                 v *= 10000000;
643                 t = nt_time_to_unix(v);
644
645                 str = ldb_timestring(out->values, t); 
646                 W_ERROR_HAVE_NO_MEMORY(str);
647
648                 out->values[i] = data_blob_string_const(str);
649         }
650
651         return WERR_OK;
652 }
653
654 static WERROR dsdb_syntax_NTTIME_ldb_to_drsuapi(struct ldb_context *ldb, 
655                                                 const struct dsdb_schema *schema,
656                                                 const struct dsdb_attribute *attr,
657                                                 const struct ldb_message_element *in,
658                                                 TALLOC_CTX *mem_ctx,
659                                                 struct drsuapi_DsReplicaAttribute *out)
660 {
661         uint32_t i;
662         DATA_BLOB *blobs;
663
664         if (attr->attributeID_id == 0xFFFFFFFF) {
665                 return WERR_FOOBAR;
666         }
667
668         out->attid                      = attr->attributeID_id;
669         out->value_ctr.num_values       = in->num_values;
670         out->value_ctr.values           = talloc_array(mem_ctx,
671                                                        struct drsuapi_DsAttributeValue,
672                                                        in->num_values);
673         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
674
675         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
676         W_ERROR_HAVE_NO_MEMORY(blobs);
677
678         for (i=0; i < in->num_values; i++) {
679                 NTTIME v;
680                 time_t t;
681                 int ret;
682
683                 out->value_ctr.values[i].blob   = &blobs[i];
684
685                 blobs[i] = data_blob_talloc(blobs, NULL, 8);
686                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
687
688                 ret = ldb_val_to_time(&in->values[i], &t);
689                 if (ret != LDB_SUCCESS) {
690                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
691                 }
692                 unix_to_nt_time(&v, t);
693                 v /= 10000000;
694
695                 SBVAL(blobs[i].data, 0, v);
696         }
697
698         return WERR_OK;
699 }
700
701 static WERROR dsdb_syntax_DATA_BLOB_drsuapi_to_ldb(struct ldb_context *ldb, 
702                                                    const struct dsdb_schema *schema,
703                                                    const struct dsdb_attribute *attr,
704                                                    const struct drsuapi_DsReplicaAttribute *in,
705                                                    TALLOC_CTX *mem_ctx,
706                                                    struct ldb_message_element *out)
707 {
708         uint32_t i;
709
710         out->flags      = 0;
711         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
712         W_ERROR_HAVE_NO_MEMORY(out->name);
713
714         out->num_values = in->value_ctr.num_values;
715         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
716         W_ERROR_HAVE_NO_MEMORY(out->values);
717
718         for (i=0; i < out->num_values; i++) {
719                 if (in->value_ctr.values[i].blob == NULL) {
720                         return WERR_FOOBAR;
721                 }
722
723                 if (in->value_ctr.values[i].blob->length == 0) {
724                         return WERR_FOOBAR;
725                 }
726
727                 out->values[i] = data_blob_dup_talloc(out->values,
728                                                       in->value_ctr.values[i].blob);
729                 W_ERROR_HAVE_NO_MEMORY(out->values[i].data);
730         }
731
732         return WERR_OK;
733 }
734
735 static WERROR dsdb_syntax_DATA_BLOB_ldb_to_drsuapi(struct ldb_context *ldb, 
736                                                    const struct dsdb_schema *schema,
737                                                    const struct dsdb_attribute *attr,
738                                                    const struct ldb_message_element *in,
739                                                    TALLOC_CTX *mem_ctx,
740                                                    struct drsuapi_DsReplicaAttribute *out)
741 {
742         uint32_t i;
743         DATA_BLOB *blobs;
744
745         if (attr->attributeID_id == 0xFFFFFFFF) {
746                 return WERR_FOOBAR;
747         }
748
749         out->attid                      = attr->attributeID_id;
750         out->value_ctr.num_values       = in->num_values;
751         out->value_ctr.values           = talloc_array(mem_ctx,
752                                                        struct drsuapi_DsAttributeValue,
753                                                        in->num_values);
754         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
755
756         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
757         W_ERROR_HAVE_NO_MEMORY(blobs);
758
759         for (i=0; i < in->num_values; i++) {
760                 out->value_ctr.values[i].blob   = &blobs[i];
761
762                 blobs[i] = data_blob_dup_talloc(blobs, &in->values[i]);
763                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
764         }
765
766         return WERR_OK;
767 }
768
769 static WERROR _dsdb_syntax_auto_OID_drsuapi_to_ldb(struct ldb_context *ldb,
770                                                    const struct dsdb_schema *schema,
771                                                    const struct dsdb_attribute *attr,
772                                                    const struct drsuapi_DsReplicaAttribute *in,
773                                                    TALLOC_CTX *mem_ctx,
774                                                    struct ldb_message_element *out)
775 {
776         uint32_t i;
777
778         out->flags      = 0;
779         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
780         W_ERROR_HAVE_NO_MEMORY(out->name);
781
782         out->num_values = in->value_ctr.num_values;
783         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
784         W_ERROR_HAVE_NO_MEMORY(out->values);
785
786         for (i=0; i < out->num_values; i++) {
787                 uint32_t v;
788                 const struct dsdb_class *c;
789                 const struct dsdb_attribute *a;
790                 const char *str = NULL;
791
792                 if (in->value_ctr.values[i].blob == NULL) {
793                         return WERR_FOOBAR;
794                 }
795
796                 if (in->value_ctr.values[i].blob->length != 4) {
797                         return WERR_FOOBAR;
798                 }
799
800                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
801
802                 if ((c = dsdb_class_by_governsID_id(schema, v))) {
803                         str = talloc_strdup(out->values, c->lDAPDisplayName);
804                 } else if ((a = dsdb_attribute_by_attributeID_id(schema, v))) {
805                         str = talloc_strdup(out->values, a->lDAPDisplayName);
806                 } else {
807                         WERROR werr;
808                         werr = dsdb_schema_pfm_oid_from_attid(schema->prefixmap, v, out->values, &str);
809                         W_ERROR_NOT_OK_RETURN(werr);
810                 }
811                 W_ERROR_HAVE_NO_MEMORY(str);
812
813                 /* the values need to be reversed */
814                 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
815         }
816
817         return WERR_OK;
818 }
819
820 static WERROR _dsdb_syntax_OID_obj_drsuapi_to_ldb(struct ldb_context *ldb, 
821                                                   const struct dsdb_schema *schema,
822                                                   const struct dsdb_attribute *attr,
823                                                   const struct drsuapi_DsReplicaAttribute *in,
824                                                   TALLOC_CTX *mem_ctx,
825                                                   struct ldb_message_element *out)
826 {
827         uint32_t i;
828
829         out->flags      = 0;
830         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
831         W_ERROR_HAVE_NO_MEMORY(out->name);
832
833         out->num_values = in->value_ctr.num_values;
834         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
835         W_ERROR_HAVE_NO_MEMORY(out->values);
836
837         for (i=0; i < out->num_values; i++) {
838                 uint32_t v;
839                 const struct dsdb_class *c;
840                 const char *str;
841
842                 if (in->value_ctr.values[i].blob == NULL) {
843                         return WERR_FOOBAR;
844                 }
845
846                 if (in->value_ctr.values[i].blob->length != 4) {
847                         return WERR_FOOBAR;
848                 }
849
850                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
851
852                 c = dsdb_class_by_governsID_id(schema, v);
853                 if (!c) {
854                         return WERR_FOOBAR;
855                 }
856
857                 str = talloc_strdup(out->values, c->lDAPDisplayName);
858                 W_ERROR_HAVE_NO_MEMORY(str);
859
860                 /* the values need to be reversed */
861                 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
862         }
863
864         return WERR_OK;
865 }
866
867 static WERROR _dsdb_syntax_OID_attr_drsuapi_to_ldb(struct ldb_context *ldb, 
868                                                    const struct dsdb_schema *schema,
869                                                    const struct dsdb_attribute *attr,
870                                                    const struct drsuapi_DsReplicaAttribute *in,
871                                                    TALLOC_CTX *mem_ctx,
872                                                    struct ldb_message_element *out)
873 {
874         uint32_t i;
875
876         out->flags      = 0;
877         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
878         W_ERROR_HAVE_NO_MEMORY(out->name);
879
880         out->num_values = in->value_ctr.num_values;
881         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
882         W_ERROR_HAVE_NO_MEMORY(out->values);
883
884         for (i=0; i < out->num_values; i++) {
885                 uint32_t v;
886                 const struct dsdb_attribute *a;
887                 const char *str;
888
889                 if (in->value_ctr.values[i].blob == NULL) {
890                         return WERR_FOOBAR;
891                 }
892
893                 if (in->value_ctr.values[i].blob->length != 4) {
894                         return WERR_FOOBAR;
895                 }
896
897                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
898
899                 a = dsdb_attribute_by_attributeID_id(schema, v);
900                 if (!a) {
901                         return WERR_FOOBAR;
902                 }
903
904                 str = talloc_strdup(out->values, a->lDAPDisplayName);
905                 W_ERROR_HAVE_NO_MEMORY(str);
906
907                 /* the values need to be reversed */
908                 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
909         }
910
911         return WERR_OK;
912 }
913
914 static WERROR _dsdb_syntax_OID_oid_drsuapi_to_ldb(struct ldb_context *ldb, 
915                                                   const struct dsdb_schema *schema,
916                                                   const struct dsdb_attribute *attr,
917                                                   const struct drsuapi_DsReplicaAttribute *in,
918                                                   TALLOC_CTX *mem_ctx,
919                                                   struct ldb_message_element *out)
920 {
921         uint32_t i;
922
923         out->flags      = 0;
924         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
925         W_ERROR_HAVE_NO_MEMORY(out->name);
926
927         out->num_values = in->value_ctr.num_values;
928         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
929         W_ERROR_HAVE_NO_MEMORY(out->values);
930
931         for (i=0; i < out->num_values; i++) {
932                 uint32_t attid;
933                 WERROR status;
934                 const char *oid;
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 != 4) {
941                         return WERR_FOOBAR;
942                 }
943
944                 attid = IVAL(in->value_ctr.values[i].blob->data, 0);
945
946                 status = dsdb_schema_pfm_oid_from_attid(schema->prefixmap, attid, out->values, &oid);
947                 W_ERROR_NOT_OK_RETURN(status);
948
949                 out->values[i] = data_blob_string_const(oid);
950         }
951
952         return WERR_OK;
953 }
954
955 static WERROR _dsdb_syntax_auto_OID_ldb_to_drsuapi(struct ldb_context *ldb,
956                                                    const struct dsdb_schema *schema,
957                                                    const struct dsdb_attribute *attr,
958                                                    const struct ldb_message_element *in,
959                                                    TALLOC_CTX *mem_ctx,
960                                                   struct drsuapi_DsReplicaAttribute *out)
961 {
962         uint32_t i;
963         DATA_BLOB *blobs;
964
965         out->attid= attr->attributeID_id;
966         out->value_ctr.num_values= in->num_values;
967         out->value_ctr.values= talloc_array(mem_ctx,
968                                             struct drsuapi_DsAttributeValue,
969                                             in->num_values);
970         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
971
972         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
973         W_ERROR_HAVE_NO_MEMORY(blobs);
974
975         for (i=0; i < in->num_values; i++) {
976                 const struct dsdb_class *obj_class;
977                 const struct dsdb_attribute *obj_attr;
978                 struct ldb_val *v;
979
980                 out->value_ctr.values[i].blob= &blobs[i];
981
982                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
983                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
984
985                 /* in DRS windows puts the classes in the opposite
986                    order to the order used in ldap */
987                 v = &in->values[(in->num_values-1)-i];
988
989                 if ((obj_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema, v))) {
990                         SIVAL(blobs[i].data, 0, obj_class->governsID_id);
991                 } else if ((obj_attr = dsdb_attribute_by_lDAPDisplayName_ldb_val(schema, v))) {
992                         SIVAL(blobs[i].data, 0, obj_attr->attributeID_id);
993                 } else {
994                         uint32_t attid;
995                         WERROR werr;
996                         werr = dsdb_schema_pfm_make_attid(schema->prefixmap,
997                                                           (const char *)v->data,
998                                                           &attid);
999                         W_ERROR_NOT_OK_RETURN(werr);
1000                         SIVAL(blobs[i].data, 0, attid);
1001                 }
1002
1003         }
1004
1005
1006         return WERR_OK;
1007 }
1008
1009 static WERROR _dsdb_syntax_OID_obj_ldb_to_drsuapi(struct ldb_context *ldb,
1010                                                   const struct dsdb_schema *schema,
1011                                                   const struct dsdb_attribute *attr,
1012                                                   const struct ldb_message_element *in,
1013                                                   TALLOC_CTX *mem_ctx,
1014                                                   struct drsuapi_DsReplicaAttribute *out)
1015 {
1016         uint32_t i;
1017         DATA_BLOB *blobs;
1018
1019         out->attid= attr->attributeID_id;
1020         out->value_ctr.num_values= in->num_values;
1021         out->value_ctr.values= talloc_array(mem_ctx,
1022                                             struct drsuapi_DsAttributeValue,
1023                                             in->num_values);
1024         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1025
1026         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1027         W_ERROR_HAVE_NO_MEMORY(blobs);
1028
1029         for (i=0; i < in->num_values; i++) {
1030                 const struct dsdb_class *obj_class;
1031
1032                 out->value_ctr.values[i].blob= &blobs[i];
1033
1034                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
1035                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1036
1037                 /* in DRS windows puts the classes in the opposite
1038                    order to the order used in ldap */
1039                 obj_class = dsdb_class_by_lDAPDisplayName(schema,
1040                                                           (const char *)in->values[(in->num_values-1)-i].data);
1041                 if (!obj_class) {
1042                         return WERR_FOOBAR;
1043                 }
1044                 SIVAL(blobs[i].data, 0, obj_class->governsID_id);
1045         }
1046
1047
1048         return WERR_OK;
1049 }
1050
1051 static WERROR _dsdb_syntax_OID_attr_ldb_to_drsuapi(struct ldb_context *ldb,
1052                                                    const struct dsdb_schema *schema,
1053                                                    const struct dsdb_attribute *attr,
1054                                                    const struct ldb_message_element *in,
1055                                                    TALLOC_CTX *mem_ctx,
1056                                                    struct drsuapi_DsReplicaAttribute *out)
1057 {
1058         uint32_t i;
1059         DATA_BLOB *blobs;
1060
1061         out->attid= attr->attributeID_id;
1062         out->value_ctr.num_values= in->num_values;
1063         out->value_ctr.values= talloc_array(mem_ctx,
1064                                             struct drsuapi_DsAttributeValue,
1065                                             in->num_values);
1066         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1067
1068         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1069         W_ERROR_HAVE_NO_MEMORY(blobs);
1070
1071         for (i=0; i < in->num_values; i++) {
1072                 const struct dsdb_attribute *obj_attr;
1073
1074                 out->value_ctr.values[i].blob= &blobs[i];
1075
1076                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
1077                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1078
1079                 obj_attr = dsdb_attribute_by_lDAPDisplayName(schema, (const char *)in->values[i].data);
1080                 if (!obj_attr) {
1081                         return WERR_FOOBAR;
1082                 }
1083                 SIVAL(blobs[i].data, 0, obj_attr->attributeID_id);
1084         }
1085
1086
1087         return WERR_OK;
1088 }
1089
1090 static WERROR _dsdb_syntax_OID_oid_ldb_to_drsuapi(struct ldb_context *ldb,
1091                                                   const struct dsdb_schema *schema,
1092                                                   const struct dsdb_attribute *attr,
1093                                                   const struct ldb_message_element *in,
1094                                                   TALLOC_CTX *mem_ctx,
1095                                                   struct drsuapi_DsReplicaAttribute *out)
1096 {
1097         uint32_t i;
1098         DATA_BLOB *blobs;
1099
1100         out->attid= attr->attributeID_id;
1101         out->value_ctr.num_values= in->num_values;
1102         out->value_ctr.values= talloc_array(mem_ctx,
1103                                             struct drsuapi_DsAttributeValue,
1104                                             in->num_values);
1105         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1106
1107         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1108         W_ERROR_HAVE_NO_MEMORY(blobs);
1109
1110         for (i=0; i < in->num_values; i++) {
1111                 uint32_t attid;
1112                 WERROR status;
1113
1114                 out->value_ctr.values[i].blob= &blobs[i];
1115
1116                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
1117                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1118
1119                 status = dsdb_schema_pfm_make_attid(schema->prefixmap,
1120                                                     (const char *)in->values[i].data,
1121                                                     &attid);
1122                 W_ERROR_NOT_OK_RETURN(status);
1123
1124                 SIVAL(blobs[i].data, 0, attid);
1125         }
1126
1127         return WERR_OK;
1128 }
1129
1130 static WERROR dsdb_syntax_OID_drsuapi_to_ldb(struct ldb_context *ldb, 
1131                                              const struct dsdb_schema *schema,
1132                                              const struct dsdb_attribute *attr,
1133                                              const struct drsuapi_DsReplicaAttribute *in,
1134                                              TALLOC_CTX *mem_ctx,
1135                                              struct ldb_message_element *out)
1136 {
1137         switch (attr->attributeID_id) {
1138         case DRSUAPI_ATTRIBUTE_objectClass:
1139         case DRSUAPI_ATTRIBUTE_subClassOf:
1140         case DRSUAPI_ATTRIBUTE_auxiliaryClass:
1141         case DRSUAPI_ATTRIBUTE_systemAuxiliaryClass:
1142         case DRSUAPI_ATTRIBUTE_systemPossSuperiors:
1143         case DRSUAPI_ATTRIBUTE_possSuperiors:
1144                 return _dsdb_syntax_OID_obj_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
1145         case DRSUAPI_ATTRIBUTE_systemMustContain:
1146         case DRSUAPI_ATTRIBUTE_systemMayContain:        
1147         case DRSUAPI_ATTRIBUTE_mustContain:
1148         case DRSUAPI_ATTRIBUTE_rDNAttId:
1149         case DRSUAPI_ATTRIBUTE_transportAddressAttribute:
1150         case DRSUAPI_ATTRIBUTE_mayContain:
1151                 return _dsdb_syntax_OID_attr_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
1152         case DRSUAPI_ATTRIBUTE_governsID:
1153         case DRSUAPI_ATTRIBUTE_attributeID:
1154         case DRSUAPI_ATTRIBUTE_attributeSyntax:
1155                 return _dsdb_syntax_OID_oid_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
1156         }
1157
1158         DEBUG(0,(__location__ ": Unknown handling for attributeID_id for %s\n",
1159                  attr->lDAPDisplayName));
1160         return _dsdb_syntax_auto_OID_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
1161 }
1162
1163 static WERROR dsdb_syntax_OID_ldb_to_drsuapi(struct ldb_context *ldb, 
1164                                              const struct dsdb_schema *schema,
1165                                              const struct dsdb_attribute *attr,
1166                                              const struct ldb_message_element *in,
1167                                              TALLOC_CTX *mem_ctx,
1168                                              struct drsuapi_DsReplicaAttribute *out)
1169 {
1170         if (attr->attributeID_id == 0xFFFFFFFF) {
1171                 return WERR_FOOBAR;
1172         }
1173
1174         switch (attr->attributeID_id) {
1175         case DRSUAPI_ATTRIBUTE_objectClass:
1176         case DRSUAPI_ATTRIBUTE_subClassOf:
1177         case DRSUAPI_ATTRIBUTE_auxiliaryClass:
1178         case DRSUAPI_ATTRIBUTE_systemAuxiliaryClass:
1179         case DRSUAPI_ATTRIBUTE_systemPossSuperiors:
1180         case DRSUAPI_ATTRIBUTE_possSuperiors:
1181                 return _dsdb_syntax_OID_obj_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
1182         case DRSUAPI_ATTRIBUTE_systemMustContain:
1183         case DRSUAPI_ATTRIBUTE_systemMayContain:        
1184         case DRSUAPI_ATTRIBUTE_mustContain:
1185         case DRSUAPI_ATTRIBUTE_rDNAttId:
1186         case DRSUAPI_ATTRIBUTE_transportAddressAttribute:
1187         case DRSUAPI_ATTRIBUTE_mayContain:
1188                 return _dsdb_syntax_OID_attr_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
1189         case DRSUAPI_ATTRIBUTE_governsID:
1190         case DRSUAPI_ATTRIBUTE_attributeID:
1191         case DRSUAPI_ATTRIBUTE_attributeSyntax:
1192                 return _dsdb_syntax_OID_oid_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
1193         }
1194
1195         DEBUG(0,(__location__ ": Unknown handling for attributeID_id for %s\n",
1196                  attr->lDAPDisplayName));
1197
1198         return _dsdb_syntax_auto_OID_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
1199 }
1200
1201 static WERROR dsdb_syntax_UNICODE_drsuapi_to_ldb(struct ldb_context *ldb, 
1202                                                  const struct dsdb_schema *schema,
1203                                                  const struct dsdb_attribute *attr,
1204                                                  const struct drsuapi_DsReplicaAttribute *in,
1205                                                  TALLOC_CTX *mem_ctx,
1206                                                  struct ldb_message_element *out)
1207 {
1208         uint32_t i;
1209
1210         out->flags      = 0;
1211         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1212         W_ERROR_HAVE_NO_MEMORY(out->name);
1213
1214         out->num_values = in->value_ctr.num_values;
1215         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1216         W_ERROR_HAVE_NO_MEMORY(out->values);
1217
1218         for (i=0; i < out->num_values; i++) {
1219                 char *str;
1220
1221                 if (in->value_ctr.values[i].blob == NULL) {
1222                         return WERR_FOOBAR;
1223                 }
1224
1225                 if (in->value_ctr.values[i].blob->length == 0) {
1226                         return WERR_FOOBAR;
1227                 }
1228
1229                 if (!convert_string_talloc_convenience(out->values, 
1230                                                 schema->iconv_convenience, 
1231                                                                         CH_UTF16, CH_UNIX,
1232                                             in->value_ctr.values[i].blob->data,
1233                                             in->value_ctr.values[i].blob->length,
1234                                             (void **)&str, NULL, false)) {
1235                         return WERR_FOOBAR;
1236                 }
1237
1238                 out->values[i] = data_blob_string_const(str);
1239         }
1240
1241         return WERR_OK;
1242 }
1243
1244 static WERROR dsdb_syntax_UNICODE_ldb_to_drsuapi(struct ldb_context *ldb, 
1245                                                  const struct dsdb_schema *schema,
1246                                                  const struct dsdb_attribute *attr,
1247                                                  const struct ldb_message_element *in,
1248                                                  TALLOC_CTX *mem_ctx,
1249                                                  struct drsuapi_DsReplicaAttribute *out)
1250 {
1251         uint32_t i;
1252         DATA_BLOB *blobs;
1253
1254         if (attr->attributeID_id == 0xFFFFFFFF) {
1255                 return WERR_FOOBAR;
1256         }
1257
1258         out->attid                      = attr->attributeID_id;
1259         out->value_ctr.num_values       = in->num_values;
1260         out->value_ctr.values           = talloc_array(mem_ctx,
1261                                                        struct drsuapi_DsAttributeValue,
1262                                                        in->num_values);
1263         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1264
1265         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1266         W_ERROR_HAVE_NO_MEMORY(blobs);
1267
1268         for (i=0; i < in->num_values; i++) {
1269                 out->value_ctr.values[i].blob   = &blobs[i];
1270
1271                 if (!convert_string_talloc_convenience(blobs,
1272                         schema->iconv_convenience, CH_UNIX, CH_UTF16,
1273                         in->values[i].data, in->values[i].length,
1274                         (void **)&blobs[i].data, &blobs[i].length, false)) {
1275                                 return WERR_FOOBAR;
1276                 }
1277         }
1278
1279         return WERR_OK;
1280 }
1281
1282
1283 WERROR dsdb_syntax_one_DN_drsuapi_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, 
1284                                          const struct dsdb_syntax *syntax, 
1285                                          struct smb_iconv_convenience *iconv_convenience,
1286                                          const DATA_BLOB *in, DATA_BLOB *out)
1287 {
1288         struct drsuapi_DsReplicaObjectIdentifier3 id3;
1289         enum ndr_err_code ndr_err;
1290         DATA_BLOB guid_blob;
1291         struct ldb_dn *dn;
1292         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1293         int ret;
1294         NTSTATUS status;
1295
1296         if (!tmp_ctx) {
1297                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1298         }
1299         
1300         if (in == NULL) {
1301                 talloc_free(tmp_ctx);
1302                 return WERR_FOOBAR;
1303         }
1304         
1305         if (in->length == 0) {
1306                 talloc_free(tmp_ctx);
1307                 return WERR_FOOBAR;
1308         }
1309         
1310         
1311         /* windows sometimes sends an extra two pad bytes here */
1312         ndr_err = ndr_pull_struct_blob(in,
1313                                        tmp_ctx, iconv_convenience, &id3,
1314                                        (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3);
1315         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1316                 status = ndr_map_error2ntstatus(ndr_err);
1317                 talloc_free(tmp_ctx);
1318                 return ntstatus_to_werror(status);
1319         }
1320         
1321         dn = ldb_dn_new(tmp_ctx, ldb, id3.dn);
1322         if (!dn) {
1323                 talloc_free(tmp_ctx);
1324                 /* If this fails, it must be out of memory, as it does not do much parsing */
1325                 W_ERROR_HAVE_NO_MEMORY(dn);
1326         }
1327
1328         if (!GUID_all_zero(&id3.guid)) {
1329                 status = GUID_to_ndr_blob(&id3.guid, tmp_ctx, &guid_blob);
1330                 if (!NT_STATUS_IS_OK(status)) {
1331                         talloc_free(tmp_ctx);
1332                         return ntstatus_to_werror(status);
1333                 }
1334         
1335                 ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
1336                 if (ret != LDB_SUCCESS) {
1337                         talloc_free(tmp_ctx);
1338                         return WERR_FOOBAR;
1339                 }
1340                 talloc_free(guid_blob.data);
1341         }
1342         
1343         if (id3.__ndr_size_sid) {
1344                 DATA_BLOB sid_blob;
1345                 ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, iconv_convenience, &id3.sid,
1346                                                (ndr_push_flags_fn_t)ndr_push_dom_sid);
1347                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1348                         status = ndr_map_error2ntstatus(ndr_err);
1349                         talloc_free(tmp_ctx);
1350                         return ntstatus_to_werror(status);
1351                 }
1352                 
1353                 ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
1354                 if (ret != LDB_SUCCESS) {
1355                         talloc_free(tmp_ctx);
1356                         return WERR_FOOBAR;
1357                 }
1358         }
1359         
1360         *out = data_blob_string_const(ldb_dn_get_extended_linearized(mem_ctx, dn, 1));
1361         talloc_free(tmp_ctx);
1362         return WERR_OK;
1363 }
1364
1365 static WERROR dsdb_syntax_DN_drsuapi_to_ldb(struct ldb_context *ldb, 
1366                                             const struct dsdb_schema *schema,
1367                                             const struct dsdb_attribute *attr,
1368                                             const struct drsuapi_DsReplicaAttribute *in,
1369                                             TALLOC_CTX *mem_ctx,
1370                                             struct ldb_message_element *out)
1371 {
1372         uint32_t i;
1373
1374         out->flags      = 0;
1375         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1376         W_ERROR_HAVE_NO_MEMORY(out->name);
1377
1378         out->num_values = in->value_ctr.num_values;
1379         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1380         W_ERROR_HAVE_NO_MEMORY(out->values);
1381
1382         for (i=0; i < out->num_values; i++) {
1383                 WERROR status = dsdb_syntax_one_DN_drsuapi_to_ldb(out->values, ldb, attr->syntax, 
1384                                                                   schema->iconv_convenience, 
1385                                                                   in->value_ctr.values[i].blob, 
1386                                                                   &out->values[i]);
1387                 if (!W_ERROR_IS_OK(status)) {
1388                         return status;
1389                 }
1390                                                   
1391         }
1392
1393         return WERR_OK;
1394 }
1395
1396 static WERROR dsdb_syntax_DN_ldb_to_drsuapi(struct ldb_context *ldb, 
1397                                             const struct dsdb_schema *schema,
1398                                             const struct dsdb_attribute *attr,
1399                                             const struct ldb_message_element *in,
1400                                             TALLOC_CTX *mem_ctx,
1401                                             struct drsuapi_DsReplicaAttribute *out)
1402 {
1403         uint32_t i;
1404         DATA_BLOB *blobs;
1405
1406         if (attr->attributeID_id == 0xFFFFFFFF) {
1407                 return WERR_FOOBAR;
1408         }
1409
1410         out->attid                      = attr->attributeID_id;
1411         out->value_ctr.num_values       = in->num_values;
1412         out->value_ctr.values           = talloc_array(mem_ctx,
1413                                                        struct drsuapi_DsAttributeValue,
1414                                                        in->num_values);
1415         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1416
1417         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1418         W_ERROR_HAVE_NO_MEMORY(blobs);
1419
1420         for (i=0; i < in->num_values; i++) {
1421                 struct drsuapi_DsReplicaObjectIdentifier3 id3;
1422                 enum ndr_err_code ndr_err;
1423                 const DATA_BLOB *sid_blob;
1424                 struct ldb_dn *dn;
1425                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1426                 NTSTATUS status;
1427
1428                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1429
1430                 out->value_ctr.values[i].blob   = &blobs[i];
1431
1432                 dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &in->values[i]);
1433
1434                 W_ERROR_HAVE_NO_MEMORY(dn);
1435
1436                 ZERO_STRUCT(id3);
1437
1438                 status = dsdb_get_extended_dn_guid(dn, &id3.guid, "GUID");
1439                 if (!NT_STATUS_IS_OK(status) &&
1440                     !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1441                         talloc_free(tmp_ctx);
1442                         return ntstatus_to_werror(status);
1443                 }
1444
1445                 sid_blob = ldb_dn_get_extended_component(dn, "SID");
1446                 if (sid_blob) {
1447                         
1448                         ndr_err = ndr_pull_struct_blob_all(sid_blob, 
1449                                                            tmp_ctx, schema->iconv_convenience, &id3.sid,
1450                                                            (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1451                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1452                                 status = ndr_map_error2ntstatus(ndr_err);
1453                                 talloc_free(tmp_ctx);
1454                                 return ntstatus_to_werror(status);
1455                         }
1456                 }
1457
1458                 id3.dn = ldb_dn_get_linearized(dn);
1459
1460                 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
1461                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1462                         status = ndr_map_error2ntstatus(ndr_err);
1463                         talloc_free(tmp_ctx);
1464                         return ntstatus_to_werror(status);
1465                 }
1466                 talloc_free(tmp_ctx);
1467         }
1468
1469         return WERR_OK;
1470 }
1471
1472
1473
1474 static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(struct ldb_context *ldb, 
1475                                                    const struct dsdb_schema *schema,
1476                                                    const struct dsdb_attribute *attr,
1477                                                    const struct drsuapi_DsReplicaAttribute *in,
1478                                                    TALLOC_CTX *mem_ctx,
1479                                                    struct ldb_message_element *out)
1480 {
1481         uint32_t i;
1482         int ret;
1483
1484         out->flags      = 0;
1485         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1486         W_ERROR_HAVE_NO_MEMORY(out->name);
1487
1488         out->num_values = in->value_ctr.num_values;
1489         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1490         W_ERROR_HAVE_NO_MEMORY(out->values);
1491
1492         for (i=0; i < out->num_values; i++) {
1493                 struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
1494                 enum ndr_err_code ndr_err;
1495                 DATA_BLOB guid_blob;
1496                 struct ldb_dn *dn;
1497                 struct dsdb_dn *dsdb_dn;
1498                 NTSTATUS status;
1499                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1500                 if (!tmp_ctx) {
1501                         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1502                 }
1503
1504                 if (in->value_ctr.values[i].blob == NULL) {
1505                         talloc_free(tmp_ctx);
1506                         return WERR_FOOBAR;
1507                 }
1508
1509                 if (in->value_ctr.values[i].blob->length == 0) {
1510                         talloc_free(tmp_ctx);
1511                         return WERR_FOOBAR;
1512                 }
1513
1514                 
1515                 /* windows sometimes sends an extra two pad bytes here */
1516                 ndr_err = ndr_pull_struct_blob(in->value_ctr.values[i].blob,
1517                                                tmp_ctx, schema->iconv_convenience, &id3,
1518                                                (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3Binary);
1519                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1520                         status = ndr_map_error2ntstatus(ndr_err);
1521                         talloc_free(tmp_ctx);
1522                         return ntstatus_to_werror(status);
1523                 }
1524
1525                 dn = ldb_dn_new(tmp_ctx, ldb, id3.dn);
1526                 if (!dn) {
1527                         talloc_free(tmp_ctx);
1528                         /* If this fails, it must be out of memory, as it does not do much parsing */
1529                         W_ERROR_HAVE_NO_MEMORY(dn);
1530                 }
1531
1532                 status = GUID_to_ndr_blob(&id3.guid, tmp_ctx, &guid_blob);
1533                 if (!NT_STATUS_IS_OK(status)) {
1534                         talloc_free(tmp_ctx);
1535                         return ntstatus_to_werror(status);
1536                 }
1537
1538                 ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
1539                 if (ret != LDB_SUCCESS) {
1540                         talloc_free(tmp_ctx);
1541                         return WERR_FOOBAR;
1542                 }
1543
1544                 talloc_free(guid_blob.data);
1545
1546                 if (id3.__ndr_size_sid) {
1547                         DATA_BLOB sid_blob;
1548                         ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, schema->iconv_convenience, &id3.sid,
1549                                                        (ndr_push_flags_fn_t)ndr_push_dom_sid);
1550                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1551                                 status = ndr_map_error2ntstatus(ndr_err);
1552                                 talloc_free(tmp_ctx);
1553                                 return ntstatus_to_werror(status);
1554                         }
1555
1556                         ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
1557                         if (ret != LDB_SUCCESS) {
1558                                 talloc_free(tmp_ctx);
1559                                 return WERR_FOOBAR;
1560                         }
1561                 }
1562
1563                 /* set binary stuff */
1564                 dsdb_dn = dsdb_dn_construct(tmp_ctx, dn, id3.binary, attr->syntax->ldap_oid);
1565                 if (!dsdb_dn) {
1566                         /* If this fails, it must be out of memory, we know the ldap_oid is valid */
1567                         talloc_free(tmp_ctx);
1568                         W_ERROR_HAVE_NO_MEMORY(dsdb_dn);
1569                 }
1570                 out->values[i] = data_blob_string_const(dsdb_dn_get_extended_linearized(out->values, dsdb_dn, 1));
1571                 talloc_free(tmp_ctx);
1572         }
1573
1574         return WERR_OK;
1575 }
1576
1577 static WERROR dsdb_syntax_DN_BINARY_ldb_to_drsuapi(struct ldb_context *ldb, 
1578                                                    const struct dsdb_schema *schema,
1579                                                    const struct dsdb_attribute *attr,
1580                                                    const struct ldb_message_element *in,
1581                                                    TALLOC_CTX *mem_ctx,
1582                                                    struct drsuapi_DsReplicaAttribute *out)
1583 {
1584         uint32_t i;
1585         DATA_BLOB *blobs;
1586
1587         if (attr->attributeID_id == 0xFFFFFFFF) {
1588                 return WERR_FOOBAR;
1589         }
1590
1591         out->attid                      = attr->attributeID_id;
1592         out->value_ctr.num_values       = in->num_values;
1593         out->value_ctr.values           = talloc_array(mem_ctx,
1594                                                        struct drsuapi_DsAttributeValue,
1595                                                        in->num_values);
1596         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1597
1598         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1599         W_ERROR_HAVE_NO_MEMORY(blobs);
1600
1601         for (i=0; i < in->num_values; i++) {
1602                 struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
1603                 enum ndr_err_code ndr_err;
1604                 const DATA_BLOB *sid_blob;
1605                 struct dsdb_dn *dsdb_dn;
1606                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1607                 NTSTATUS status;
1608
1609                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1610
1611                 out->value_ctr.values[i].blob   = &blobs[i];
1612
1613                 dsdb_dn = dsdb_dn_parse(tmp_ctx, ldb, &in->values[i], attr->syntax->ldap_oid);
1614
1615                 if (!dsdb_dn) {
1616                         talloc_free(tmp_ctx);
1617                         return ntstatus_to_werror(NT_STATUS_INVALID_PARAMETER);
1618                 }
1619
1620                 ZERO_STRUCT(id3);
1621
1622                 status = dsdb_get_extended_dn_guid(dsdb_dn->dn, &id3.guid, "GUID");
1623                 if (!NT_STATUS_IS_OK(status) &&
1624                     !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1625                         talloc_free(tmp_ctx);
1626                         return ntstatus_to_werror(status);
1627                 }
1628
1629                 sid_blob = ldb_dn_get_extended_component(dsdb_dn->dn, "SID");
1630                 if (sid_blob) {
1631                         
1632                         ndr_err = ndr_pull_struct_blob_all(sid_blob, 
1633                                                            tmp_ctx, schema->iconv_convenience, &id3.sid,
1634                                                            (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1635                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1636                                 status = ndr_map_error2ntstatus(ndr_err);
1637                                 talloc_free(tmp_ctx);
1638                                 return ntstatus_to_werror(status);
1639                         }
1640                 }
1641
1642                 id3.dn = ldb_dn_get_linearized(dsdb_dn->dn);
1643
1644                 /* get binary stuff */
1645                 id3.binary = dsdb_dn->extra_part;
1646
1647                 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3Binary);
1648                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1649                         status = ndr_map_error2ntstatus(ndr_err);
1650                         talloc_free(tmp_ctx);
1651                         return ntstatus_to_werror(status);
1652                 }
1653                 talloc_free(tmp_ctx);
1654         }
1655
1656         return WERR_OK;
1657 }
1658
1659 static WERROR dsdb_syntax_DN_STRING_drsuapi_to_ldb(struct ldb_context *ldb,
1660                                                    const struct dsdb_schema *schema,
1661                                                    const struct dsdb_attribute *attr,
1662                                                    const struct drsuapi_DsReplicaAttribute *in,
1663                                                    TALLOC_CTX *mem_ctx,
1664                                                    struct ldb_message_element *out)
1665 {
1666         return dsdb_syntax_DN_BINARY_drsuapi_to_ldb(ldb,
1667                                                     schema,
1668                                                     attr,
1669                                                     in,
1670                                                     mem_ctx,
1671                                                     out);
1672 }
1673
1674 static WERROR dsdb_syntax_DN_STRING_ldb_to_drsuapi(struct ldb_context *ldb,
1675                                                    const struct dsdb_schema *schema,
1676                                                    const struct dsdb_attribute *attr,
1677                                                    const struct ldb_message_element *in,
1678                                                    TALLOC_CTX *mem_ctx,
1679                                                    struct drsuapi_DsReplicaAttribute *out)
1680 {
1681         return dsdb_syntax_DN_BINARY_ldb_to_drsuapi(ldb,
1682                                                     schema,
1683                                                     attr,
1684                                                     in,
1685                                                     mem_ctx,
1686                                                     out);
1687 }
1688
1689 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb(struct ldb_context *ldb, 
1690                                                               const struct dsdb_schema *schema,
1691                                                               const struct dsdb_attribute *attr,
1692                                                               const struct drsuapi_DsReplicaAttribute *in,
1693                                                               TALLOC_CTX *mem_ctx,
1694                                                               struct ldb_message_element *out)
1695 {
1696         uint32_t i;
1697
1698         out->flags      = 0;
1699         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1700         W_ERROR_HAVE_NO_MEMORY(out->name);
1701
1702         out->num_values = in->value_ctr.num_values;
1703         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1704         W_ERROR_HAVE_NO_MEMORY(out->values);
1705
1706         for (i=0; i < out->num_values; i++) {
1707                 uint32_t len;
1708                 char *str;
1709
1710                 if (in->value_ctr.values[i].blob == NULL) {
1711                         return WERR_FOOBAR;
1712                 }
1713
1714                 if (in->value_ctr.values[i].blob->length < 4) {
1715                         return WERR_FOOBAR;
1716                 }
1717
1718                 len = IVAL(in->value_ctr.values[i].blob->data, 0);
1719
1720                 if (len != in->value_ctr.values[i].blob->length) {
1721                         return WERR_FOOBAR;
1722                 }
1723
1724                 if (!convert_string_talloc_convenience(out->values, schema->iconv_convenience, CH_UTF16, CH_UNIX,
1725                                             in->value_ctr.values[i].blob->data+4,
1726                                             in->value_ctr.values[i].blob->length-4,
1727                                             (void **)&str, NULL, false)) {
1728                         return WERR_FOOBAR;
1729                 }
1730
1731                 out->values[i] = data_blob_string_const(str);
1732         }
1733
1734         return WERR_OK;
1735 }
1736
1737 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi(struct ldb_context *ldb, 
1738                                                               const struct dsdb_schema *schema,
1739                                                               const struct dsdb_attribute *attr,
1740                                                               const struct ldb_message_element *in,
1741                                                               TALLOC_CTX *mem_ctx,
1742                                                               struct drsuapi_DsReplicaAttribute *out)
1743 {
1744         uint32_t i;
1745         DATA_BLOB *blobs;
1746
1747         if (attr->attributeID_id == 0xFFFFFFFF) {
1748                 return WERR_FOOBAR;
1749         }
1750
1751         out->attid                      = attr->attributeID_id;
1752         out->value_ctr.num_values       = in->num_values;
1753         out->value_ctr.values           = talloc_array(mem_ctx,
1754                                                        struct drsuapi_DsAttributeValue,
1755                                                        in->num_values);
1756         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1757
1758         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1759         W_ERROR_HAVE_NO_MEMORY(blobs);
1760
1761         for (i=0; i < in->num_values; i++) {
1762                 uint8_t *data;
1763                 size_t ret;
1764
1765                 out->value_ctr.values[i].blob   = &blobs[i];
1766
1767                 if (!convert_string_talloc_convenience(blobs, schema->iconv_convenience, CH_UNIX, CH_UTF16,
1768                                             in->values[i].data,
1769                                             in->values[i].length,
1770                                             (void **)&data, &ret, false)) {
1771                         return WERR_FOOBAR;
1772                 }
1773
1774                 blobs[i] = data_blob_talloc(blobs, NULL, 4 + ret);
1775                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1776
1777                 SIVAL(blobs[i].data, 0, 4 + ret);
1778
1779                 if (ret > 0) {
1780                         memcpy(blobs[i].data + 4, data, ret);
1781                         talloc_free(data);
1782                 }
1783         }
1784
1785         return WERR_OK;
1786 }
1787
1788 #define OMOBJECTCLASS(val) { .length = sizeof(val) - 1, .data = discard_const_p(uint8_t, val) }
1789
1790 static const struct dsdb_syntax dsdb_syntaxes[] = {
1791         {
1792                 .name                   = "Boolean",
1793                 .ldap_oid               = LDB_SYNTAX_BOOLEAN,
1794                 .oMSyntax               = 1,
1795                 .attributeSyntax_oid    = "2.5.5.8",
1796                 .drsuapi_to_ldb         = dsdb_syntax_BOOL_drsuapi_to_ldb,
1797                 .ldb_to_drsuapi         = dsdb_syntax_BOOL_ldb_to_drsuapi,
1798                 .validate_ldb           = dsdb_syntax_BOOL_validate_ldb,
1799                 .equality               = "booleanMatch",
1800                 .comment                = "Boolean" 
1801         },{
1802                 .name                   = "Integer",
1803                 .ldap_oid               = LDB_SYNTAX_INTEGER,
1804                 .oMSyntax               = 2,
1805                 .attributeSyntax_oid    = "2.5.5.9",
1806                 .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
1807                 .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
1808                 .validate_ldb           = dsdb_syntax_INT32_validate_ldb,
1809                 .equality               = "integerMatch",
1810                 .comment                = "Integer",
1811                 .ldb_syntax             = LDB_SYNTAX_SAMBA_INT32
1812         },{
1813                 .name                   = "String(Octet)",
1814                 .ldap_oid               = LDB_SYNTAX_OCTET_STRING,
1815                 .oMSyntax               = 4,
1816                 .attributeSyntax_oid    = "2.5.5.10",
1817                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1818                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1819                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1820                 .equality               = "octetStringMatch",
1821                 .comment                = "Octet String",
1822         },{
1823                 .name                   = "String(Sid)",
1824                 .ldap_oid               = LDB_SYNTAX_OCTET_STRING,
1825                 .oMSyntax               = 4,
1826                 .attributeSyntax_oid    = "2.5.5.17",
1827                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1828                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1829                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1830                 .equality               = "octetStringMatch",
1831                 .comment                = "Octet String - Security Identifier (SID)",
1832                 .ldb_syntax             = LDB_SYNTAX_SAMBA_SID
1833         },{
1834                 .name                   = "String(Object-Identifier)",
1835                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.38",
1836                 .oMSyntax               = 6,
1837                 .attributeSyntax_oid    = "2.5.5.2",
1838                 .drsuapi_to_ldb         = dsdb_syntax_OID_drsuapi_to_ldb,
1839                 .ldb_to_drsuapi         = dsdb_syntax_OID_ldb_to_drsuapi,
1840                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1841                 .equality               = "caseIgnoreMatch", /* Would use "objectIdentifierMatch" but most are ldap attribute/class names */
1842                 .comment                = "OID String",
1843                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING
1844         },{
1845                 .name                   = "Enumeration",
1846                 .ldap_oid               = LDB_SYNTAX_INTEGER,
1847                 .oMSyntax               = 10,
1848                 .attributeSyntax_oid    = "2.5.5.9",
1849                 .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
1850                 .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
1851                 .validate_ldb           = dsdb_syntax_INT32_validate_ldb,
1852                 .ldb_syntax             = LDB_SYNTAX_SAMBA_INT32
1853         },{
1854         /* not used in w2k3 forest */
1855                 .name                   = "String(Numeric)",
1856                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.36",
1857                 .oMSyntax               = 18,
1858                 .attributeSyntax_oid    = "2.5.5.6",
1859                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1860                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1861                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1862                 .equality               = "numericStringMatch",
1863                 .substring              = "numericStringSubstringsMatch",
1864                 .comment                = "Numeric String",
1865                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1866         },{
1867                 .name                   = "String(Printable)",
1868                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.44",
1869                 .oMSyntax               = 19,
1870                 .attributeSyntax_oid    = "2.5.5.5",
1871                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1872                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1873                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1874                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
1875         },{
1876                 .name                   = "String(Teletex)",
1877                 .ldap_oid               = "1.2.840.113556.1.4.905",
1878                 .oMSyntax               = 20,
1879                 .attributeSyntax_oid    = "2.5.5.4",
1880                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1881                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1882                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1883                 .equality               = "caseIgnoreMatch",
1884                 .substring              = "caseIgnoreSubstringsMatch",
1885                 .comment                = "Case Insensitive String",
1886                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1887         },{
1888                 .name                   = "String(IA5)",
1889                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.26",
1890                 .oMSyntax               = 22,
1891                 .attributeSyntax_oid    = "2.5.5.5",
1892                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1893                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1894                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1895                 .equality               = "caseExactIA5Match",
1896                 .comment                = "Printable String",
1897                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
1898         },{
1899                 .name                   = "String(UTC-Time)",
1900                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.53",
1901                 .oMSyntax               = 23,
1902                 .attributeSyntax_oid    = "2.5.5.11",
1903                 .drsuapi_to_ldb         = dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb,
1904                 .ldb_to_drsuapi         = dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi,
1905                 .validate_ldb           = dsdb_syntax_NTTIME_UTC_validate_ldb,
1906                 .equality               = "generalizedTimeMatch",
1907                 .comment                = "UTC Time",
1908         },{
1909                 .name                   = "String(Generalized-Time)",
1910                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.24",
1911                 .oMSyntax               = 24,
1912                 .attributeSyntax_oid    = "2.5.5.11",
1913                 .drsuapi_to_ldb         = dsdb_syntax_NTTIME_drsuapi_to_ldb,
1914                 .ldb_to_drsuapi         = dsdb_syntax_NTTIME_ldb_to_drsuapi,
1915                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1916                 .equality               = "generalizedTimeMatch",
1917                 .comment                = "Generalized Time",
1918                 .ldb_syntax             = LDB_SYNTAX_UTC_TIME,
1919         },{
1920         /* not used in w2k3 schema */
1921                 .name                   = "String(Case Sensitive)",
1922                 .ldap_oid               = "1.2.840.113556.1.4.1362",
1923                 .oMSyntax               = 27,
1924                 .attributeSyntax_oid    = "2.5.5.3",
1925                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1926                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1927                 .validate_ldb           = dsdb_syntax_FOOBAR_validate_ldb,
1928         },{
1929                 .name                   = "String(Unicode)",
1930                 .ldap_oid               = LDB_SYNTAX_DIRECTORY_STRING,
1931                 .oMSyntax               = 64,
1932                 .attributeSyntax_oid    = "2.5.5.12",
1933                 .drsuapi_to_ldb         = dsdb_syntax_UNICODE_drsuapi_to_ldb,
1934                 .ldb_to_drsuapi         = dsdb_syntax_UNICODE_ldb_to_drsuapi,
1935                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1936                 .equality               = "caseIgnoreMatch",
1937                 .substring              = "caseIgnoreSubstringsMatch",
1938                 .comment                = "Directory String",
1939         },{
1940                 .name                   = "Interval/LargeInteger",
1941                 .ldap_oid               = "1.2.840.113556.1.4.906",
1942                 .oMSyntax               = 65,
1943                 .attributeSyntax_oid    = "2.5.5.16",
1944                 .drsuapi_to_ldb         = dsdb_syntax_INT64_drsuapi_to_ldb,
1945                 .ldb_to_drsuapi         = dsdb_syntax_INT64_ldb_to_drsuapi,
1946                 .validate_ldb           = dsdb_syntax_INT64_validate_ldb,
1947                 .equality               = "integerMatch",
1948                 .comment                = "Large Integer",
1949                 .ldb_syntax             = LDB_SYNTAX_INTEGER,
1950         },{
1951                 .name                   = "String(NT-Sec-Desc)",
1952                 .ldap_oid               = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1953                 .oMSyntax               = 66,
1954                 .attributeSyntax_oid    = "2.5.5.15",
1955                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1956                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1957                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1958         },{
1959                 .name                   = "Object(DS-DN)",
1960                 .ldap_oid               = LDB_SYNTAX_DN,
1961                 .oMSyntax               = 127,
1962                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x4a"),
1963                 .attributeSyntax_oid    = "2.5.5.1",
1964                 .drsuapi_to_ldb         = dsdb_syntax_DN_drsuapi_to_ldb,
1965                 .ldb_to_drsuapi         = dsdb_syntax_DN_ldb_to_drsuapi,
1966                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1967                 .equality               = "distinguishedNameMatch",
1968                 .comment                = "Object(DS-DN) == a DN",
1969         },{
1970                 .name                   = "Object(DN-Binary)",
1971                 .ldap_oid               = DSDB_SYNTAX_BINARY_DN,
1972                 .oMSyntax               = 127,
1973                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0b"),
1974                 .attributeSyntax_oid    = "2.5.5.7",
1975                 .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
1976                 .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
1977                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1978                 .equality               = "octetStringMatch",
1979                 .comment                = "OctetString: Binary+DN",
1980         },{
1981         /* not used in w2k3 schema, but used in Exchange schema*/
1982                 .name                   = "Object(OR-Name)",
1983                 .ldap_oid               = DSDB_SYNTAX_OR_NAME,
1984                 .oMSyntax               = 127,
1985                 .oMObjectClass          = OMOBJECTCLASS("\x56\x06\x01\x02\x05\x0b\x1D"),
1986                 .attributeSyntax_oid    = "2.5.5.7",
1987                 .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
1988                 .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
1989                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
1990                 .equality               = "caseIgnoreMatch",
1991                 .ldb_syntax             = LDB_SYNTAX_DN,
1992         },{
1993         /* 
1994          * TODO: verify if DATA_BLOB is correct here...!
1995          *
1996          *       repsFrom and repsTo are the only attributes using
1997          *       this attribute syntax, but they're not replicated... 
1998          */
1999                 .name                   = "Object(Replica-Link)",
2000                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.40",
2001                 .oMSyntax               = 127,
2002                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x06"),
2003                 .attributeSyntax_oid    = "2.5.5.10",
2004                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2005                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2006                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
2007         },{
2008                 .name                   = "Object(Presentation-Address)",
2009                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.43",
2010                 .oMSyntax               = 127,
2011                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x5c"),
2012                 .attributeSyntax_oid    = "2.5.5.13",
2013                 .drsuapi_to_ldb         = dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb,
2014                 .ldb_to_drsuapi         = dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi,
2015                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
2016                 .comment                = "Presentation Address",
2017                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
2018         },{
2019         /* not used in w2k3 schema */
2020                 .name                   = "Object(Access-Point)",
2021                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.2",
2022                 .oMSyntax               = 127,
2023                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x3e"),
2024                 .attributeSyntax_oid    = "2.5.5.14",
2025                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
2026                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
2027                 .validate_ldb           = dsdb_syntax_FOOBAR_validate_ldb,
2028                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
2029         },{
2030         /* not used in w2k3 schema */
2031                 .name                   = "Object(DN-String)",
2032                 .ldap_oid               = DSDB_SYNTAX_STRING_DN,
2033                 .oMSyntax               = 127,
2034                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0c"),
2035                 .attributeSyntax_oid    = "2.5.5.14",
2036                 .drsuapi_to_ldb         = dsdb_syntax_DN_STRING_drsuapi_to_ldb,
2037                 .ldb_to_drsuapi         = dsdb_syntax_DN_STRING_ldb_to_drsuapi,
2038                 .validate_ldb           = dsdb_syntax_ALLOW_validate_ldb,
2039                 .equality               = "octetStringMatch",
2040                 .comment                = "OctetString: String+DN",
2041         }
2042 };
2043
2044 const struct dsdb_syntax *find_syntax_map_by_ad_oid(const char *ad_oid) 
2045 {
2046         int i;
2047         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
2048                 if (strcasecmp(ad_oid, dsdb_syntaxes[i].attributeSyntax_oid) == 0) {
2049                         return &dsdb_syntaxes[i];
2050                 }
2051         }
2052         return NULL;
2053 }
2054
2055 const struct dsdb_syntax *find_syntax_map_by_ad_syntax(int oMSyntax) 
2056 {
2057         int i;
2058         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
2059                 if (oMSyntax == dsdb_syntaxes[i].oMSyntax) {
2060                         return &dsdb_syntaxes[i];
2061                 }
2062         }
2063         return NULL;
2064 }
2065
2066 const struct dsdb_syntax *find_syntax_map_by_standard_oid(const char *standard_oid) 
2067 {
2068         int i;
2069         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
2070                 if (strcasecmp(standard_oid, dsdb_syntaxes[i].ldap_oid) == 0) {
2071                         return &dsdb_syntaxes[i];
2072                 }
2073         }
2074         return NULL;
2075 }
2076 const struct dsdb_syntax *dsdb_syntax_for_attribute(const struct dsdb_attribute *attr)
2077 {
2078         uint32_t i;
2079
2080         for (i=0; i < ARRAY_SIZE(dsdb_syntaxes); i++) {
2081                 if (attr->oMSyntax != dsdb_syntaxes[i].oMSyntax) continue;
2082
2083                 if (attr->oMObjectClass.length != dsdb_syntaxes[i].oMObjectClass.length) continue;
2084
2085                 if (attr->oMObjectClass.length) {
2086                         int ret;
2087                         ret = memcmp(attr->oMObjectClass.data,
2088                                      dsdb_syntaxes[i].oMObjectClass.data,
2089                                      attr->oMObjectClass.length);
2090                         if (ret != 0) continue;
2091                 }
2092
2093                 if (strcmp(attr->attributeSyntax_oid, dsdb_syntaxes[i].attributeSyntax_oid) != 0) continue;
2094
2095                 return &dsdb_syntaxes[i];
2096         }
2097
2098         return NULL;
2099 }
2100
2101 WERROR dsdb_attribute_drsuapi_to_ldb(struct ldb_context *ldb, 
2102                                      const struct dsdb_schema *schema,
2103                                      const struct drsuapi_DsReplicaAttribute *in,
2104                                      TALLOC_CTX *mem_ctx,
2105                                      struct ldb_message_element *out)
2106 {
2107         const struct dsdb_attribute *sa;
2108
2109         sa = dsdb_attribute_by_attributeID_id(schema, in->attid);
2110         if (!sa) {
2111                 return WERR_FOOBAR;
2112         }
2113
2114         return sa->syntax->drsuapi_to_ldb(ldb, schema, sa, in, mem_ctx, out);
2115 }
2116
2117 WERROR dsdb_attribute_ldb_to_drsuapi(struct ldb_context *ldb, 
2118                                      const struct dsdb_schema *schema,
2119                                      const struct ldb_message_element *in,
2120                                      TALLOC_CTX *mem_ctx,
2121                                      struct drsuapi_DsReplicaAttribute *out)
2122 {
2123         const struct dsdb_attribute *sa;
2124
2125         sa = dsdb_attribute_by_lDAPDisplayName(schema, in->name);
2126         if (!sa) {
2127                 return WERR_FOOBAR;
2128         }
2129
2130         return sa->syntax->ldb_to_drsuapi(ldb, schema, sa, in, mem_ctx, out);
2131 }
2132
2133 WERROR dsdb_attribute_validate_ldb(struct ldb_context *ldb,
2134                                    const struct dsdb_schema *schema,
2135                                    const struct ldb_message_element *in)
2136 {
2137         const struct dsdb_attribute *sa;
2138
2139         sa = dsdb_attribute_by_lDAPDisplayName(schema, in->name);
2140         if (!sa) {
2141                 return WERR_DS_ATTRIBUTE_TYPE_UNDEFINED;
2142         }
2143
2144         return sa->syntax->validate_ldb(ldb, schema, sa, in);
2145 }