a93cdfaaa913591b77d2e4d832ddfbfefae8ef58
[metze/samba/wip.git] / source4 / dsdb / schema / schema_syntax.c
1 /*
2    Unix SMB/CIFS mplementation.
3    DSDB schema syntaxes
4
5    Copyright (C) Stefan Metzmacher <metze@samba.org> 2006
6    Copyright (C) Simo Sorce 2005
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
22 */
23 #include "includes.h"
24 #include "dsdb/samdb/samdb.h"
25 #include "librpc/gen_ndr/ndr_drsuapi.h"
26 #include "librpc/gen_ndr/ndr_security.h"
27 #include "librpc/gen_ndr/ndr_misc.h"
28 #include <ldb.h>
29 #include <ldb_errors.h>
30 #include "system/time.h"
31 #include "../lib/util/charset/charset.h"
32 #include "librpc/ndr/libndr.h"
33 #include "../lib/util/asn1.h"
34
35 /**
36  * Initialize dsdb_syntax_ctx with default values
37  * for common cases.
38  */
39 void dsdb_syntax_ctx_init(struct dsdb_syntax_ctx *ctx,
40                           struct ldb_context *ldb,
41                           const struct dsdb_schema *schema)
42 {
43         ctx->ldb        = ldb;
44         ctx->schema     = schema;
45
46         /*
47          * 'true' will keep current behavior,
48          * i.e. attributeID_id will be returned by default
49          */
50         ctx->is_schema_nc = true;
51
52         ctx->pfm_remote = NULL;
53 }
54
55
56 /**
57  * Returns ATTID for DRS attribute.
58  *
59  * ATTID depends on whether we are replicating
60  * Schema NC or msDs-IntId is set for schemaAttribute
61  * for the attribute.
62  */
63 uint32_t dsdb_attribute_get_attid(const struct dsdb_attribute *attr,
64                                   bool for_schema_nc)
65 {
66         if (!for_schema_nc && attr->msDS_IntId) {
67                 return attr->msDS_IntId;
68         }
69
70         return attr->attributeID_id;
71 }
72
73 /**
74  * Map an ATTID from remote DC to a local ATTID
75  * using remote prefixMap
76  */
77 static bool dsdb_syntax_attid_from_remote_attid(const struct dsdb_syntax_ctx *ctx,
78                                                 TALLOC_CTX *mem_ctx,
79                                                 uint32_t id_remote,
80                                                 uint32_t *id_local)
81 {
82         WERROR werr;
83         const char *oid;
84
85         /*
86          * map remote ATTID to local directly in case
87          * of no remote prefixMap (during provision for instance)
88          */
89         if (!ctx->pfm_remote) {
90                 *id_local = id_remote;
91                 return true;
92         }
93
94         werr = dsdb_schema_pfm_oid_from_attid(ctx->pfm_remote, id_remote, mem_ctx, &oid);
95         if (!W_ERROR_IS_OK(werr)) {
96                 DEBUG(0,("ATTID->OID failed (%s) for: 0x%08X\n", win_errstr(werr), id_remote));
97                 return false;
98         }
99
100         werr = dsdb_schema_pfm_make_attid(ctx->schema->prefixmap, oid, id_local);
101         if (!W_ERROR_IS_OK(werr)) {
102                 DEBUG(0,("OID->ATTID failed (%s) for: %s\n", win_errstr(werr), oid));
103                 return false;
104         }
105
106         return true;
107 }
108
109 static WERROR dsdb_syntax_FOOBAR_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
110                                                 const struct dsdb_attribute *attr,
111                                                 const struct drsuapi_DsReplicaAttribute *in,
112                                                 TALLOC_CTX *mem_ctx,
113                                                 struct ldb_message_element *out)
114 {
115         unsigned int i;
116
117         out->flags      = 0;
118         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
119         W_ERROR_HAVE_NO_MEMORY(out->name);
120
121         out->num_values = in->value_ctr.num_values;
122         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
123         W_ERROR_HAVE_NO_MEMORY(out->values);
124
125         for (i=0; i < out->num_values; i++) {
126                 char *str;
127
128                 if (in->value_ctr.values[i].blob == NULL) {
129                         return WERR_FOOBAR;
130                 }
131
132                 str = talloc_asprintf(out->values, "%s: not implemented",
133                                       attr->syntax->name);
134                 W_ERROR_HAVE_NO_MEMORY(str);
135
136                 out->values[i] = data_blob_string_const(str);
137         }
138
139         return WERR_OK;
140 }
141
142 static WERROR dsdb_syntax_FOOBAR_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
143                                                 const struct dsdb_attribute *attr,
144                                                 const struct ldb_message_element *in,
145                                                 TALLOC_CTX *mem_ctx,
146                                                 struct drsuapi_DsReplicaAttribute *out)
147 {
148         return WERR_FOOBAR;
149 }
150
151 static WERROR dsdb_syntax_FOOBAR_validate_ldb(const struct dsdb_syntax_ctx *ctx,
152                                               const struct dsdb_attribute *attr,
153                                               const struct ldb_message_element *in)
154 {
155         return WERR_FOOBAR;
156 }
157
158 static WERROR dsdb_syntax_BOOL_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
159                                               const struct dsdb_attribute *attr,
160                                               const struct drsuapi_DsReplicaAttribute *in,
161                                               TALLOC_CTX *mem_ctx,
162                                               struct ldb_message_element *out)
163 {
164         unsigned int i;
165
166         out->flags      = 0;
167         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
168         W_ERROR_HAVE_NO_MEMORY(out->name);
169
170         out->num_values = in->value_ctr.num_values;
171         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
172         W_ERROR_HAVE_NO_MEMORY(out->values);
173
174         for (i=0; i < out->num_values; i++) {
175                 uint32_t v;
176                 char *str;
177
178                 if (in->value_ctr.values[i].blob == NULL) {
179                         return WERR_FOOBAR;
180                 }
181
182                 if (in->value_ctr.values[i].blob->length != 4) {
183                         return WERR_FOOBAR;
184                 }
185
186                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
187
188                 if (v != 0) {
189                         str = talloc_strdup(out->values, "TRUE");
190                         W_ERROR_HAVE_NO_MEMORY(str);
191                 } else {
192                         str = talloc_strdup(out->values, "FALSE");
193                         W_ERROR_HAVE_NO_MEMORY(str);
194                 }
195
196                 out->values[i] = data_blob_string_const(str);
197         }
198
199         return WERR_OK;
200 }
201
202 static WERROR dsdb_syntax_BOOL_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
203                                               const struct dsdb_attribute *attr,
204                                               const struct ldb_message_element *in,
205                                               TALLOC_CTX *mem_ctx,
206                                               struct drsuapi_DsReplicaAttribute *out)
207 {
208         unsigned int i;
209         DATA_BLOB *blobs;
210
211         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
212                 return WERR_FOOBAR;
213         }
214
215         out->attid                      = dsdb_attribute_get_attid(attr,
216                                                                    ctx->is_schema_nc);
217         out->value_ctr.num_values       = in->num_values;
218         out->value_ctr.values           = talloc_array(mem_ctx,
219                                                        struct drsuapi_DsAttributeValue,
220                                                        in->num_values);
221         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
222
223         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
224         W_ERROR_HAVE_NO_MEMORY(blobs);
225
226         for (i=0; i < in->num_values; i++) {
227                 out->value_ctr.values[i].blob   = &blobs[i];
228
229                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
230                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
231
232                 if (strcmp("TRUE", (const char *)in->values[i].data) == 0) {
233                         SIVAL(blobs[i].data, 0, 0x00000001);
234                 } else if (strcmp("FALSE", (const char *)in->values[i].data) == 0) {
235                         SIVAL(blobs[i].data, 0, 0x00000000);
236                 } else {
237                         return WERR_FOOBAR;
238                 }
239         }
240
241         return WERR_OK;
242 }
243
244 static WERROR dsdb_syntax_BOOL_validate_ldb(const struct dsdb_syntax_ctx *ctx,
245                                             const struct dsdb_attribute *attr,
246                                             const struct ldb_message_element *in)
247 {
248         unsigned int i;
249
250         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
251                 return WERR_FOOBAR;
252         }
253
254         for (i=0; i < in->num_values; i++) {
255                 int t, f;
256
257                 if (in->values[i].length == 0) {
258                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
259                 }
260
261                 t = strncmp("TRUE",
262                             (const char *)in->values[i].data,
263                             in->values[i].length);
264                 f = strncmp("FALSE",
265                             (const char *)in->values[i].data,
266                             in->values[i].length);
267
268                 if (t != 0 && f != 0) {
269                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
270                 }
271         }
272
273         return WERR_OK;
274 }
275
276 static WERROR dsdb_syntax_INT32_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
277                                                const struct dsdb_attribute *attr,
278                                                const struct drsuapi_DsReplicaAttribute *in,
279                                                TALLOC_CTX *mem_ctx,
280                                                struct ldb_message_element *out)
281 {
282         unsigned int i;
283
284         out->flags      = 0;
285         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
286         W_ERROR_HAVE_NO_MEMORY(out->name);
287
288         out->num_values = in->value_ctr.num_values;
289         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
290         W_ERROR_HAVE_NO_MEMORY(out->values);
291
292         for (i=0; i < out->num_values; i++) {
293                 int32_t v;
294                 char *str;
295
296                 if (in->value_ctr.values[i].blob == NULL) {
297                         return WERR_FOOBAR;
298                 }
299
300                 if (in->value_ctr.values[i].blob->length != 4) {
301                         return WERR_FOOBAR;
302                 }
303
304                 v = IVALS(in->value_ctr.values[i].blob->data, 0);
305
306                 str = talloc_asprintf(out->values, "%d", v);
307                 W_ERROR_HAVE_NO_MEMORY(str);
308
309                 out->values[i] = data_blob_string_const(str);
310         }
311
312         return WERR_OK;
313 }
314
315 static WERROR dsdb_syntax_INT32_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
316                                                const struct dsdb_attribute *attr,
317                                                const struct ldb_message_element *in,
318                                                TALLOC_CTX *mem_ctx,
319                                                struct drsuapi_DsReplicaAttribute *out)
320 {
321         unsigned int i;
322         DATA_BLOB *blobs;
323
324         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
325                 return WERR_FOOBAR;
326         }
327
328         out->attid                      = dsdb_attribute_get_attid(attr,
329                                                                    ctx->is_schema_nc);
330         out->value_ctr.num_values       = in->num_values;
331         out->value_ctr.values           = talloc_array(mem_ctx,
332                                                        struct drsuapi_DsAttributeValue,
333                                                        in->num_values);
334         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
335
336         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
337         W_ERROR_HAVE_NO_MEMORY(blobs);
338
339         for (i=0; i < in->num_values; i++) {
340                 int32_t v;
341
342                 out->value_ctr.values[i].blob   = &blobs[i];
343
344                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
345                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
346
347                 /* We've to use "strtoll" here to have the intended overflows.
348                  * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
349                 v = (int32_t) strtoll((char *)in->values[i].data, NULL, 0);
350
351                 SIVALS(blobs[i].data, 0, v);
352         }
353
354         return WERR_OK;
355 }
356
357 static WERROR dsdb_syntax_INT32_validate_ldb(const struct dsdb_syntax_ctx *ctx,
358                                              const struct dsdb_attribute *attr,
359                                              const struct ldb_message_element *in)
360 {
361         unsigned int i;
362
363         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
364                 return WERR_FOOBAR;
365         }
366
367         for (i=0; i < in->num_values; i++) {
368                 long v;
369                 char buf[sizeof("-2147483648")];
370                 char *end = NULL;
371
372                 ZERO_STRUCT(buf);
373                 if (in->values[i].length >= sizeof(buf)) {
374                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
375                 }
376
377                 memcpy(buf, in->values[i].data, in->values[i].length);
378                 errno = 0;
379                 v = strtol(buf, &end, 10);
380                 if (errno != 0) {
381                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
382                 }
383                 if (end && end[0] != '\0') {
384                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
385                 }
386
387                 if (attr->rangeLower) {
388                         if ((int32_t)v < (int32_t)*attr->rangeLower) {
389                                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
390                         }
391                 }
392
393                 if (attr->rangeUpper) {
394                         if ((int32_t)v > (int32_t)*attr->rangeUpper) {
395                                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
396                         }
397                 }
398         }
399
400         return WERR_OK;
401 }
402
403 static WERROR dsdb_syntax_INT64_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
404                                                const struct dsdb_attribute *attr,
405                                                const struct drsuapi_DsReplicaAttribute *in,
406                                                TALLOC_CTX *mem_ctx,
407                                                struct ldb_message_element *out)
408 {
409         unsigned int i;
410
411         out->flags      = 0;
412         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
413         W_ERROR_HAVE_NO_MEMORY(out->name);
414
415         out->num_values = in->value_ctr.num_values;
416         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
417         W_ERROR_HAVE_NO_MEMORY(out->values);
418
419         for (i=0; i < out->num_values; i++) {
420                 int64_t v;
421                 char *str;
422
423                 if (in->value_ctr.values[i].blob == NULL) {
424                         return WERR_FOOBAR;
425                 }
426
427                 if (in->value_ctr.values[i].blob->length != 8) {
428                         return WERR_FOOBAR;
429                 }
430
431                 v = BVALS(in->value_ctr.values[i].blob->data, 0);
432
433                 str = talloc_asprintf(out->values, "%lld", (long long int)v);
434                 W_ERROR_HAVE_NO_MEMORY(str);
435
436                 out->values[i] = data_blob_string_const(str);
437         }
438
439         return WERR_OK;
440 }
441
442 static WERROR dsdb_syntax_INT64_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
443                                                const struct dsdb_attribute *attr,
444                                                const struct ldb_message_element *in,
445                                                TALLOC_CTX *mem_ctx,
446                                                struct drsuapi_DsReplicaAttribute *out)
447 {
448         unsigned int i;
449         DATA_BLOB *blobs;
450
451         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
452                 return WERR_FOOBAR;
453         }
454
455         out->attid                      = dsdb_attribute_get_attid(attr,
456                                                                    ctx->is_schema_nc);
457         out->value_ctr.num_values       = in->num_values;
458         out->value_ctr.values           = talloc_array(mem_ctx,
459                                                        struct drsuapi_DsAttributeValue,
460                                                        in->num_values);
461         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
462
463         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
464         W_ERROR_HAVE_NO_MEMORY(blobs);
465
466         for (i=0; i < in->num_values; i++) {
467                 int64_t v;
468
469                 out->value_ctr.values[i].blob   = &blobs[i];
470
471                 blobs[i] = data_blob_talloc(blobs, NULL, 8);
472                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
473
474                 v = strtoll((const char *)in->values[i].data, NULL, 10);
475
476                 SBVALS(blobs[i].data, 0, v);
477         }
478
479         return WERR_OK;
480 }
481
482 static WERROR dsdb_syntax_INT64_validate_ldb(const struct dsdb_syntax_ctx *ctx,
483                                              const struct dsdb_attribute *attr,
484                                              const struct ldb_message_element *in)
485 {
486         unsigned int i;
487
488         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
489                 return WERR_FOOBAR;
490         }
491
492         for (i=0; i < in->num_values; i++) {
493                 long long v;
494                 char buf[sizeof("-9223372036854775808")];
495                 char *end = NULL;
496
497                 ZERO_STRUCT(buf);
498                 if (in->values[i].length >= sizeof(buf)) {
499                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
500                 }
501                 memcpy(buf, in->values[i].data, in->values[i].length);
502
503                 errno = 0;
504                 v = strtoll(buf, &end, 10);
505                 if (errno != 0) {
506                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
507                 }
508                 if (end && end[0] != '\0') {
509                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
510                 }
511
512                 if (attr->rangeLower) {
513                         if ((int64_t)v < (int64_t)*attr->rangeLower) {
514                                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
515                         }
516                 }
517
518                 if (attr->rangeUpper) {
519                         if ((int64_t)v > (int64_t)*attr->rangeUpper) {
520                                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
521                         }
522                 }
523         }
524
525         return WERR_OK;
526 }
527 static WERROR dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
528                                                     const struct dsdb_attribute *attr,
529                                                     const struct drsuapi_DsReplicaAttribute *in,
530                                                     TALLOC_CTX *mem_ctx,
531                                                     struct ldb_message_element *out)
532 {
533         unsigned int i;
534
535         out->flags      = 0;
536         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
537         W_ERROR_HAVE_NO_MEMORY(out->name);
538
539         out->num_values = in->value_ctr.num_values;
540         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
541         W_ERROR_HAVE_NO_MEMORY(out->values);
542
543         for (i=0; i < out->num_values; i++) {
544                 NTTIME v;
545                 time_t t;
546                 char *str;
547
548                 if (in->value_ctr.values[i].blob == NULL) {
549                         return WERR_FOOBAR;
550                 }
551
552                 if (in->value_ctr.values[i].blob->length != 8) {
553                         return WERR_FOOBAR;
554                 }
555
556                 v = BVAL(in->value_ctr.values[i].blob->data, 0);
557                 v *= 10000000;
558                 t = nt_time_to_unix(v);
559
560                 /*
561                  * NOTE: On a w2k3 server you can set a GeneralizedTime string
562                  *       via LDAP, but you get back an UTCTime string,
563                  *       but via DRSUAPI you get back the NTTIME_1sec value
564                  *       that represents the GeneralizedTime value!
565                  *
566                  *       So if we store the UTCTime string in our ldb
567                  *       we'll loose information!
568                  */
569                 str = ldb_timestring_utc(out->values, t);
570                 W_ERROR_HAVE_NO_MEMORY(str);
571                 out->values[i] = data_blob_string_const(str);
572         }
573
574         return WERR_OK;
575 }
576
577 static WERROR dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
578                                                     const struct dsdb_attribute *attr,
579                                                     const struct ldb_message_element *in,
580                                                     TALLOC_CTX *mem_ctx,
581                                                     struct drsuapi_DsReplicaAttribute *out)
582 {
583         unsigned int i;
584         DATA_BLOB *blobs;
585
586         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
587                 return WERR_FOOBAR;
588         }
589
590         out->attid                      = dsdb_attribute_get_attid(attr,
591                                                                    ctx->is_schema_nc);
592         out->value_ctr.num_values       = in->num_values;
593         out->value_ctr.values           = talloc_array(mem_ctx,
594                                                        struct drsuapi_DsAttributeValue,
595                                                        in->num_values);
596         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
597
598         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
599         W_ERROR_HAVE_NO_MEMORY(blobs);
600
601         for (i=0; i < in->num_values; i++) {
602                 NTTIME v;
603                 time_t t;
604
605                 out->value_ctr.values[i].blob   = &blobs[i];
606
607                 blobs[i] = data_blob_talloc(blobs, NULL, 8);
608                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
609
610                 t = ldb_string_utc_to_time((const char *)in->values[i].data);
611                 unix_to_nt_time(&v, t);
612                 v /= 10000000;
613
614                 SBVAL(blobs[i].data, 0, v);
615         }
616
617         return WERR_OK;
618 }
619
620 static WERROR dsdb_syntax_NTTIME_UTC_validate_ldb(const struct dsdb_syntax_ctx *ctx,
621                                                   const struct dsdb_attribute *attr,
622                                                   const struct ldb_message_element *in)
623 {
624         unsigned int i;
625
626         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
627                 return WERR_FOOBAR;
628         }
629
630         for (i=0; i < in->num_values; i++) {
631                 time_t t;
632                 char buf[sizeof("090826075717Z")];
633
634                 ZERO_STRUCT(buf);
635                 if (in->values[i].length >= sizeof(buf)) {
636                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
637                 }
638                 memcpy(buf, in->values[i].data, in->values[i].length);
639
640                 t = ldb_string_utc_to_time(buf);
641                 if (t == 0) {
642                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
643                 }
644
645                 if (attr->rangeLower) {
646                         if ((int32_t)t < (int32_t)*attr->rangeLower) {
647                                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
648                         }
649                 }
650
651                 if (attr->rangeUpper) {
652                         if ((int32_t)t > (int32_t)*attr->rangeLower) {
653                                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
654                         }
655                 }
656
657                 /*
658                  * TODO: verify the comment in the
659                  * dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb() function!
660                  */
661         }
662
663         return WERR_OK;
664 }
665
666 static WERROR dsdb_syntax_NTTIME_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
667                                                 const struct dsdb_attribute *attr,
668                                                 const struct drsuapi_DsReplicaAttribute *in,
669                                                 TALLOC_CTX *mem_ctx,
670                                                 struct ldb_message_element *out)
671 {
672         unsigned int i;
673
674         out->flags      = 0;
675         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
676         W_ERROR_HAVE_NO_MEMORY(out->name);
677
678         out->num_values = in->value_ctr.num_values;
679         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
680         W_ERROR_HAVE_NO_MEMORY(out->values);
681
682         for (i=0; i < out->num_values; i++) {
683                 NTTIME v;
684                 time_t t;
685                 char *str;
686
687                 if (in->value_ctr.values[i].blob == NULL) {
688                         return WERR_FOOBAR;
689                 }
690
691                 if (in->value_ctr.values[i].blob->length != 8) {
692                         return WERR_FOOBAR;
693                 }
694
695                 v = BVAL(in->value_ctr.values[i].blob->data, 0);
696                 v *= 10000000;
697                 t = nt_time_to_unix(v);
698
699                 str = ldb_timestring(out->values, t);
700                 W_ERROR_HAVE_NO_MEMORY(str);
701
702                 out->values[i] = data_blob_string_const(str);
703         }
704
705         return WERR_OK;
706 }
707
708 static WERROR dsdb_syntax_NTTIME_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
709                                                 const struct dsdb_attribute *attr,
710                                                 const struct ldb_message_element *in,
711                                                 TALLOC_CTX *mem_ctx,
712                                                 struct drsuapi_DsReplicaAttribute *out)
713 {
714         unsigned int i;
715         DATA_BLOB *blobs;
716
717         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
718                 return WERR_FOOBAR;
719         }
720
721         out->attid                      = dsdb_attribute_get_attid(attr,
722                                                                    ctx->is_schema_nc);
723         out->value_ctr.num_values       = in->num_values;
724         out->value_ctr.values           = talloc_array(mem_ctx,
725                                                        struct drsuapi_DsAttributeValue,
726                                                        in->num_values);
727         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
728
729         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
730         W_ERROR_HAVE_NO_MEMORY(blobs);
731
732         for (i=0; i < in->num_values; i++) {
733                 NTTIME v;
734                 time_t t;
735                 int ret;
736
737                 out->value_ctr.values[i].blob   = &blobs[i];
738
739                 blobs[i] = data_blob_talloc(blobs, NULL, 8);
740                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
741
742                 ret = ldb_val_to_time(&in->values[i], &t);
743                 if (ret != LDB_SUCCESS) {
744                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
745                 }
746                 unix_to_nt_time(&v, t);
747                 v /= 10000000;
748
749                 SBVAL(blobs[i].data, 0, v);
750         }
751
752         return WERR_OK;
753 }
754
755 static WERROR dsdb_syntax_NTTIME_validate_ldb(const struct dsdb_syntax_ctx *ctx,
756                                               const struct dsdb_attribute *attr,
757                                               const struct ldb_message_element *in)
758 {
759         unsigned int i;
760
761         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
762                 return WERR_FOOBAR;
763         }
764
765         for (i=0; i < in->num_values; i++) {
766                 time_t t;
767                 int ret;
768
769                 ret = ldb_val_to_time(&in->values[i], &t);
770                 if (ret != LDB_SUCCESS) {
771                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
772                 }
773
774                 if (attr->rangeLower) {
775                         if ((int32_t)t < (int32_t)*attr->rangeLower) {
776                                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
777                         }
778                 }
779
780                 if (attr->rangeUpper) {
781                         if ((int32_t)t > (int32_t)*attr->rangeLower) {
782                                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
783                         }
784                 }
785         }
786
787         return WERR_OK;
788 }
789
790 static WERROR dsdb_syntax_DATA_BLOB_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
791                                                    const struct dsdb_attribute *attr,
792                                                    const struct drsuapi_DsReplicaAttribute *in,
793                                                    TALLOC_CTX *mem_ctx,
794                                                    struct ldb_message_element *out)
795 {
796         unsigned int i;
797
798         out->flags      = 0;
799         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
800         W_ERROR_HAVE_NO_MEMORY(out->name);
801
802         out->num_values = in->value_ctr.num_values;
803         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
804         W_ERROR_HAVE_NO_MEMORY(out->values);
805
806         for (i=0; i < out->num_values; i++) {
807                 if (in->value_ctr.values[i].blob == NULL) {
808                         return WERR_FOOBAR;
809                 }
810
811                 if (in->value_ctr.values[i].blob->length == 0) {
812                         return WERR_FOOBAR;
813                 }
814
815                 out->values[i] = data_blob_dup_talloc(out->values,
816                                                       in->value_ctr.values[i].blob);
817                 W_ERROR_HAVE_NO_MEMORY(out->values[i].data);
818         }
819
820         return WERR_OK;
821 }
822
823 static WERROR dsdb_syntax_DATA_BLOB_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
824                                                    const struct dsdb_attribute *attr,
825                                                    const struct ldb_message_element *in,
826                                                    TALLOC_CTX *mem_ctx,
827                                                    struct drsuapi_DsReplicaAttribute *out)
828 {
829         unsigned int i;
830         DATA_BLOB *blobs;
831
832         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
833                 return WERR_FOOBAR;
834         }
835
836         out->attid                      = dsdb_attribute_get_attid(attr,
837                                                                    ctx->is_schema_nc);
838         out->value_ctr.num_values       = in->num_values;
839         out->value_ctr.values           = talloc_array(mem_ctx,
840                                                        struct drsuapi_DsAttributeValue,
841                                                        in->num_values);
842         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
843
844         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
845         W_ERROR_HAVE_NO_MEMORY(blobs);
846
847         for (i=0; i < in->num_values; i++) {
848                 out->value_ctr.values[i].blob   = &blobs[i];
849
850                 blobs[i] = data_blob_dup_talloc(blobs, &in->values[i]);
851                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
852         }
853
854         return WERR_OK;
855 }
856
857 static WERROR dsdb_syntax_DATA_BLOB_validate_one_val(const struct dsdb_syntax_ctx *ctx,
858                                                      const struct dsdb_attribute *attr,
859                                                      const struct ldb_val *val)
860 {
861         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
862                 return WERR_FOOBAR;
863         }
864
865         if (attr->rangeLower) {
866                 if ((uint32_t)val->length < (uint32_t)*attr->rangeLower) {
867                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
868                 }
869         }
870
871         if (attr->rangeUpper) {
872                 if ((uint32_t)val->length > (uint32_t)*attr->rangeUpper) {
873                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
874                 }
875         }
876
877         return WERR_OK;
878 }
879
880 static WERROR dsdb_syntax_DATA_BLOB_validate_ldb(const struct dsdb_syntax_ctx *ctx,
881                                                  const struct dsdb_attribute *attr,
882                                                  const struct ldb_message_element *in)
883 {
884         unsigned int i;
885         WERROR status;
886
887         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
888                 return WERR_FOOBAR;
889         }
890
891         for (i=0; i < in->num_values; i++) {
892                 if (in->values[i].length == 0) {
893                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
894                 }
895
896                 status = dsdb_syntax_DATA_BLOB_validate_one_val(ctx,
897                                                                 attr,
898                                                                 &in->values[i]);
899                 if (!W_ERROR_IS_OK(status)) {
900                         return status;
901                 }
902         }
903
904         return WERR_OK;
905 }
906
907 static WERROR _dsdb_syntax_auto_OID_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
908                                                    const struct dsdb_attribute *attr,
909                                                    const struct drsuapi_DsReplicaAttribute *in,
910                                                    TALLOC_CTX *mem_ctx,
911                                                    struct ldb_message_element *out)
912 {
913         unsigned int i;
914
915         out->flags      = 0;
916         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
917         W_ERROR_HAVE_NO_MEMORY(out->name);
918
919         out->num_values = in->value_ctr.num_values;
920         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
921         W_ERROR_HAVE_NO_MEMORY(out->values);
922
923         for (i=0; i < out->num_values; i++) {
924                 uint32_t v;
925                 const struct dsdb_class *c;
926                 const struct dsdb_attribute *a;
927                 const char *str = NULL;
928
929                 if (in->value_ctr.values[i].blob == NULL) {
930                         return WERR_FOOBAR;
931                 }
932
933                 if (in->value_ctr.values[i].blob->length != 4) {
934                         return WERR_FOOBAR;
935                 }
936
937                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
938
939                 if ((c = dsdb_class_by_governsID_id(ctx->schema, v))) {
940                         str = talloc_strdup(out->values, c->lDAPDisplayName);
941                 } else if ((a = dsdb_attribute_by_attributeID_id(ctx->schema, v))) {
942                         str = talloc_strdup(out->values, a->lDAPDisplayName);
943                 } else {
944                         WERROR werr;
945                         SMB_ASSERT(ctx->pfm_remote);
946                         werr = dsdb_schema_pfm_oid_from_attid(ctx->pfm_remote, v,
947                                                               out->values, &str);
948                         W_ERROR_NOT_OK_RETURN(werr);
949                 }
950                 W_ERROR_HAVE_NO_MEMORY(str);
951
952                 /* the values need to be reversed */
953                 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
954         }
955
956         return WERR_OK;
957 }
958
959 static WERROR _dsdb_syntax_OID_obj_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
960                                                   const struct dsdb_attribute *attr,
961                                                   const struct drsuapi_DsReplicaAttribute *in,
962                                                   TALLOC_CTX *mem_ctx,
963                                                   struct ldb_message_element *out)
964 {
965         unsigned int i;
966
967         out->flags      = 0;
968         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
969         W_ERROR_HAVE_NO_MEMORY(out->name);
970
971         out->num_values = in->value_ctr.num_values;
972         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
973         W_ERROR_HAVE_NO_MEMORY(out->values);
974
975         for (i=0; i < out->num_values; i++) {
976                 uint32_t v;
977                 const struct dsdb_class *c;
978                 const char *str;
979
980                 if (in->value_ctr.values[i].blob == NULL) {
981                         return WERR_FOOBAR;
982                 }
983
984                 if (in->value_ctr.values[i].blob->length != 4) {
985                         return WERR_FOOBAR;
986                 }
987
988                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
989
990                 /* convert remote ATTID to local ATTID */
991                 if (!dsdb_syntax_attid_from_remote_attid(ctx, mem_ctx, v, &v)) {
992                         DEBUG(1,(__location__ ": Failed to map remote ATTID to local ATTID!\n"));
993                         return WERR_FOOBAR;
994                 }
995
996                 c = dsdb_class_by_governsID_id(ctx->schema, v);
997                 if (!c) {
998                         DEBUG(1,(__location__ ": Unknown governsID 0x%08X\n", v));
999                         return WERR_FOOBAR;
1000                 }
1001
1002                 str = talloc_strdup(out->values, c->lDAPDisplayName);
1003                 W_ERROR_HAVE_NO_MEMORY(str);
1004
1005                 /* the values need to be reversed */
1006                 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
1007         }
1008
1009         return WERR_OK;
1010 }
1011
1012 static WERROR _dsdb_syntax_OID_attr_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
1013                                                    const struct dsdb_attribute *attr,
1014                                                    const struct drsuapi_DsReplicaAttribute *in,
1015                                                    TALLOC_CTX *mem_ctx,
1016                                                    struct ldb_message_element *out)
1017 {
1018         unsigned int i;
1019
1020         out->flags      = 0;
1021         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1022         W_ERROR_HAVE_NO_MEMORY(out->name);
1023
1024         out->num_values = in->value_ctr.num_values;
1025         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1026         W_ERROR_HAVE_NO_MEMORY(out->values);
1027
1028         for (i=0; i < out->num_values; i++) {
1029                 uint32_t v;
1030                 const struct dsdb_attribute *a;
1031                 const char *str;
1032
1033                 if (in->value_ctr.values[i].blob == NULL) {
1034                         return WERR_FOOBAR;
1035                 }
1036
1037                 if (in->value_ctr.values[i].blob->length != 4) {
1038                         return WERR_FOOBAR;
1039                 }
1040
1041                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
1042
1043                 /* convert remote ATTID to local ATTID */
1044                 if (!dsdb_syntax_attid_from_remote_attid(ctx, mem_ctx, v, &v)) {
1045                         DEBUG(1,(__location__ ": Failed to map remote ATTID to local ATTID!\n"));
1046                         return WERR_FOOBAR;
1047                 }
1048
1049                 a = dsdb_attribute_by_attributeID_id(ctx->schema, v);
1050                 if (!a) {
1051                         DEBUG(1,(__location__ ": Unknown attributeID_id 0x%08X\n", v));
1052                         return WERR_FOOBAR;
1053                 }
1054
1055                 str = talloc_strdup(out->values, a->lDAPDisplayName);
1056                 W_ERROR_HAVE_NO_MEMORY(str);
1057
1058                 /* the values need to be reversed */
1059                 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
1060         }
1061
1062         return WERR_OK;
1063 }
1064
1065 static WERROR _dsdb_syntax_OID_oid_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
1066                                                   const struct dsdb_attribute *attr,
1067                                                   const struct drsuapi_DsReplicaAttribute *in,
1068                                                   TALLOC_CTX *mem_ctx,
1069                                                   struct ldb_message_element *out)
1070 {
1071         unsigned int i;
1072         const struct dsdb_schema_prefixmap *prefixmap;
1073
1074         if (ctx->pfm_remote != NULL) {
1075                 prefixmap = ctx->pfm_remote;
1076         } else {
1077                 prefixmap = ctx->schema->prefixmap;
1078         }
1079         SMB_ASSERT(prefixmap);
1080
1081         out->flags      = 0;
1082         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1083         W_ERROR_HAVE_NO_MEMORY(out->name);
1084
1085         out->num_values = in->value_ctr.num_values;
1086         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1087         W_ERROR_HAVE_NO_MEMORY(out->values);
1088
1089         for (i=0; i < out->num_values; i++) {
1090                 uint32_t attid;
1091                 WERROR status;
1092                 const char *oid;
1093
1094                 if (in->value_ctr.values[i].blob == NULL) {
1095                         return WERR_FOOBAR;
1096                 }
1097
1098                 if (in->value_ctr.values[i].blob->length != 4) {
1099                         return WERR_FOOBAR;
1100                 }
1101
1102                 attid = IVAL(in->value_ctr.values[i].blob->data, 0);
1103
1104                 status = dsdb_schema_pfm_oid_from_attid(prefixmap, attid,
1105                                                         out->values, &oid);
1106                 if (!W_ERROR_IS_OK(status)) {
1107                         DEBUG(0,(__location__ ": Error: Unknown ATTID 0x%08X\n",
1108                                  attid));
1109                         return status;
1110                 }
1111
1112                 out->values[i] = data_blob_string_const(oid);
1113         }
1114
1115         return WERR_OK;
1116 }
1117
1118 static WERROR _dsdb_syntax_auto_OID_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1119                                                    const struct dsdb_attribute *attr,
1120                                                    const struct ldb_message_element *in,
1121                                                    TALLOC_CTX *mem_ctx,
1122                                                    struct drsuapi_DsReplicaAttribute *out)
1123 {
1124         unsigned int i;
1125         DATA_BLOB *blobs;
1126
1127         out->attid= dsdb_attribute_get_attid(attr,
1128                                              ctx->is_schema_nc);
1129         out->value_ctr.num_values= in->num_values;
1130         out->value_ctr.values= talloc_array(mem_ctx,
1131                                             struct drsuapi_DsAttributeValue,
1132                                             in->num_values);
1133         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1134
1135         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1136         W_ERROR_HAVE_NO_MEMORY(blobs);
1137
1138         for (i=0; i < in->num_values; i++) {
1139                 const struct dsdb_class *obj_class;
1140                 const struct dsdb_attribute *obj_attr;
1141                 struct ldb_val *v;
1142
1143                 out->value_ctr.values[i].blob= &blobs[i];
1144
1145                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
1146                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1147
1148                 /* in DRS windows puts the classes in the opposite
1149                    order to the order used in ldap */
1150                 v = &in->values[(in->num_values-1)-i];
1151
1152                 if ((obj_class = dsdb_class_by_lDAPDisplayName_ldb_val(ctx->schema, v))) {
1153                         SIVAL(blobs[i].data, 0, obj_class->governsID_id);
1154                 } else if ((obj_attr = dsdb_attribute_by_lDAPDisplayName_ldb_val(ctx->schema, v))) {
1155                         SIVAL(blobs[i].data, 0, obj_attr->attributeID_id);
1156                 } else {
1157                         uint32_t attid;
1158                         WERROR werr;
1159                         werr = dsdb_schema_pfm_attid_from_oid(ctx->schema->prefixmap,
1160                                                               (const char *)v->data,
1161                                                               &attid);
1162                         W_ERROR_NOT_OK_RETURN(werr);
1163                         SIVAL(blobs[i].data, 0, attid);
1164                 }
1165
1166         }
1167
1168
1169         return WERR_OK;
1170 }
1171
1172 static WERROR _dsdb_syntax_OID_obj_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1173                                                   const struct dsdb_attribute *attr,
1174                                                   const struct ldb_message_element *in,
1175                                                   TALLOC_CTX *mem_ctx,
1176                                                   struct drsuapi_DsReplicaAttribute *out)
1177 {
1178         unsigned int i;
1179         DATA_BLOB *blobs;
1180
1181         out->attid= dsdb_attribute_get_attid(attr,
1182                                              ctx->is_schema_nc);
1183         out->value_ctr.num_values= in->num_values;
1184         out->value_ctr.values= talloc_array(mem_ctx,
1185                                             struct drsuapi_DsAttributeValue,
1186                                             in->num_values);
1187         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1188
1189         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1190         W_ERROR_HAVE_NO_MEMORY(blobs);
1191
1192         for (i=0; i < in->num_values; i++) {
1193                 const struct dsdb_class *obj_class;
1194
1195                 out->value_ctr.values[i].blob= &blobs[i];
1196
1197                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
1198                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1199
1200                 /* in DRS windows puts the classes in the opposite
1201                    order to the order used in ldap */
1202                 obj_class = dsdb_class_by_lDAPDisplayName(ctx->schema,
1203                                                           (const char *)in->values[(in->num_values-1)-i].data);
1204                 if (!obj_class) {
1205                         return WERR_FOOBAR;
1206                 }
1207                 SIVAL(blobs[i].data, 0, obj_class->governsID_id);
1208         }
1209
1210
1211         return WERR_OK;
1212 }
1213
1214 static WERROR _dsdb_syntax_OID_attr_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1215                                                    const struct dsdb_attribute *attr,
1216                                                    const struct ldb_message_element *in,
1217                                                    TALLOC_CTX *mem_ctx,
1218                                                    struct drsuapi_DsReplicaAttribute *out)
1219 {
1220         unsigned int i;
1221         DATA_BLOB *blobs;
1222
1223         out->attid= dsdb_attribute_get_attid(attr,
1224                                              ctx->is_schema_nc);
1225         out->value_ctr.num_values= in->num_values;
1226         out->value_ctr.values= talloc_array(mem_ctx,
1227                                             struct drsuapi_DsAttributeValue,
1228                                             in->num_values);
1229         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1230
1231         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1232         W_ERROR_HAVE_NO_MEMORY(blobs);
1233
1234         for (i=0; i < in->num_values; i++) {
1235                 const struct dsdb_attribute *obj_attr;
1236
1237                 out->value_ctr.values[i].blob= &blobs[i];
1238
1239                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
1240                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1241
1242                 obj_attr = dsdb_attribute_by_lDAPDisplayName(ctx->schema, (const char *)in->values[i].data);
1243                 if (!obj_attr) {
1244                         return WERR_FOOBAR;
1245                 }
1246                 SIVAL(blobs[i].data, 0, obj_attr->attributeID_id);
1247         }
1248
1249
1250         return WERR_OK;
1251 }
1252
1253 static WERROR _dsdb_syntax_OID_oid_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1254                                                   const struct dsdb_attribute *attr,
1255                                                   const struct ldb_message_element *in,
1256                                                   TALLOC_CTX *mem_ctx,
1257                                                   struct drsuapi_DsReplicaAttribute *out)
1258 {
1259         unsigned int i;
1260         DATA_BLOB *blobs;
1261
1262         out->attid= dsdb_attribute_get_attid(attr,
1263                                              ctx->is_schema_nc);
1264         out->value_ctr.num_values= in->num_values;
1265         out->value_ctr.values= talloc_array(mem_ctx,
1266                                             struct drsuapi_DsAttributeValue,
1267                                             in->num_values);
1268         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1269
1270         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1271         W_ERROR_HAVE_NO_MEMORY(blobs);
1272
1273         for (i=0; i < in->num_values; i++) {
1274                 uint32_t attid;
1275                 WERROR status;
1276
1277                 out->value_ctr.values[i].blob= &blobs[i];
1278
1279                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
1280                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1281
1282                 status = dsdb_schema_pfm_attid_from_oid(ctx->schema->prefixmap,
1283                                                         (const char *)in->values[i].data,
1284                                                         &attid);
1285                 W_ERROR_NOT_OK_RETURN(status);
1286
1287                 SIVAL(blobs[i].data, 0, attid);
1288         }
1289
1290         return WERR_OK;
1291 }
1292
1293 static WERROR dsdb_syntax_OID_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
1294                                              const struct dsdb_attribute *attr,
1295                                              const struct drsuapi_DsReplicaAttribute *in,
1296                                              TALLOC_CTX *mem_ctx,
1297                                              struct ldb_message_element *out)
1298 {
1299         WERROR werr;
1300
1301         switch (attr->attributeID_id) {
1302         case DRSUAPI_ATTID_objectClass:
1303         case DRSUAPI_ATTID_subClassOf:
1304         case DRSUAPI_ATTID_auxiliaryClass:
1305         case DRSUAPI_ATTID_systemAuxiliaryClass:
1306         case DRSUAPI_ATTID_systemPossSuperiors:
1307         case DRSUAPI_ATTID_possSuperiors:
1308                 werr = _dsdb_syntax_OID_obj_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
1309                 break;
1310         case DRSUAPI_ATTID_systemMustContain:
1311         case DRSUAPI_ATTID_systemMayContain:
1312         case DRSUAPI_ATTID_mustContain:
1313         case DRSUAPI_ATTID_rDNAttId:
1314         case DRSUAPI_ATTID_transportAddressAttribute:
1315         case DRSUAPI_ATTID_mayContain:
1316                 werr = _dsdb_syntax_OID_attr_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
1317                 break;
1318         case DRSUAPI_ATTID_governsID:
1319         case DRSUAPI_ATTID_attributeID:
1320         case DRSUAPI_ATTID_attributeSyntax:
1321                 werr = _dsdb_syntax_OID_oid_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
1322                 break;
1323         default:
1324                 DEBUG(0,(__location__ ": Unknown handling for attributeID_id for %s\n",
1325                          attr->lDAPDisplayName));
1326                 return _dsdb_syntax_auto_OID_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
1327         }
1328
1329         /* When we are doing the vampire of a schema, we don't want
1330          * the inability to reference an OID to get in the way.
1331          * Otherwise, we won't get the new schema with which to
1332          * understand this */
1333         if (!W_ERROR_IS_OK(werr) && ctx->schema->relax_OID_conversions) {
1334                 return _dsdb_syntax_OID_oid_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
1335         }
1336         return werr;
1337 }
1338
1339 static WERROR dsdb_syntax_OID_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1340                                              const struct dsdb_attribute *attr,
1341                                              const struct ldb_message_element *in,
1342                                              TALLOC_CTX *mem_ctx,
1343                                              struct drsuapi_DsReplicaAttribute *out)
1344 {
1345         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1346                 return WERR_FOOBAR;
1347         }
1348
1349         switch (attr->attributeID_id) {
1350         case DRSUAPI_ATTID_objectClass:
1351         case DRSUAPI_ATTID_subClassOf:
1352         case DRSUAPI_ATTID_auxiliaryClass:
1353         case DRSUAPI_ATTID_systemAuxiliaryClass:
1354         case DRSUAPI_ATTID_systemPossSuperiors:
1355         case DRSUAPI_ATTID_possSuperiors:
1356                 return _dsdb_syntax_OID_obj_ldb_to_drsuapi(ctx, attr, in, mem_ctx, out);
1357         case DRSUAPI_ATTID_systemMustContain:
1358         case DRSUAPI_ATTID_systemMayContain:
1359         case DRSUAPI_ATTID_mustContain:
1360         case DRSUAPI_ATTID_rDNAttId:
1361         case DRSUAPI_ATTID_transportAddressAttribute:
1362         case DRSUAPI_ATTID_mayContain:
1363                 return _dsdb_syntax_OID_attr_ldb_to_drsuapi(ctx, attr, in, mem_ctx, out);
1364         case DRSUAPI_ATTID_governsID:
1365         case DRSUAPI_ATTID_attributeID:
1366         case DRSUAPI_ATTID_attributeSyntax:
1367                 return _dsdb_syntax_OID_oid_ldb_to_drsuapi(ctx, attr, in, mem_ctx, out);
1368         }
1369
1370         DEBUG(0,(__location__ ": Unknown handling for attributeID_id for %s\n",
1371                  attr->lDAPDisplayName));
1372
1373         return _dsdb_syntax_auto_OID_ldb_to_drsuapi(ctx, attr, in, mem_ctx, out);
1374 }
1375
1376 static WERROR _dsdb_syntax_OID_validate_numericoid(const struct dsdb_syntax_ctx *ctx,
1377                                                    const struct dsdb_attribute *attr,
1378                                                    const struct ldb_message_element *in)
1379 {
1380         unsigned int i;
1381         TALLOC_CTX *tmp_ctx;
1382
1383         tmp_ctx = talloc_new(ctx->ldb);
1384         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1385
1386         for (i=0; i < in->num_values; i++) {
1387                 DATA_BLOB blob;
1388                 char *oid_out;
1389                 const char *oid = (const char*)in->values[i].data;
1390
1391                 if (in->values[i].length == 0) {
1392                         talloc_free(tmp_ctx);
1393                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1394                 }
1395
1396                 if (!ber_write_OID_String(tmp_ctx, &blob, oid)) {
1397                         DEBUG(0,("ber_write_OID_String() failed for %s\n", oid));
1398                         talloc_free(tmp_ctx);
1399                         return WERR_INVALID_PARAMETER;
1400                 }
1401
1402                 if (!ber_read_OID_String(tmp_ctx, blob, &oid_out)) {
1403                         DEBUG(0,("ber_read_OID_String() failed for %s\n",
1404                                  hex_encode_talloc(tmp_ctx, blob.data, blob.length)));
1405                         talloc_free(tmp_ctx);
1406                         return WERR_INVALID_PARAMETER;
1407                 }
1408
1409                 if (strcmp(oid, oid_out) != 0) {
1410                         talloc_free(tmp_ctx);
1411                         return WERR_INVALID_PARAMETER;
1412                 }
1413         }
1414
1415         talloc_free(tmp_ctx);
1416         return WERR_OK;
1417 }
1418
1419 static WERROR dsdb_syntax_OID_validate_ldb(const struct dsdb_syntax_ctx *ctx,
1420                                            const struct dsdb_attribute *attr,
1421                                            const struct ldb_message_element *in)
1422 {
1423         WERROR status;
1424         struct drsuapi_DsReplicaAttribute drs_tmp;
1425         struct ldb_message_element ldb_tmp;
1426         TALLOC_CTX *tmp_ctx;
1427
1428         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1429                 return WERR_FOOBAR;
1430         }
1431
1432         switch (attr->attributeID_id) {
1433         case DRSUAPI_ATTID_governsID:
1434         case DRSUAPI_ATTID_attributeID:
1435         case DRSUAPI_ATTID_attributeSyntax:
1436                 return _dsdb_syntax_OID_validate_numericoid(ctx, attr, in);
1437         }
1438
1439         /*
1440          * TODO: optimize and verify this code
1441          */
1442
1443         tmp_ctx = talloc_new(ctx->ldb);
1444         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1445
1446         status = dsdb_syntax_OID_ldb_to_drsuapi(ctx,
1447                                                 attr,
1448                                                 in,
1449                                                 tmp_ctx,
1450                                                 &drs_tmp);
1451         if (!W_ERROR_IS_OK(status)) {
1452                 talloc_free(tmp_ctx);
1453                 return status;
1454         }
1455
1456         status = dsdb_syntax_OID_drsuapi_to_ldb(ctx,
1457                                                 attr,
1458                                                 &drs_tmp,
1459                                                 tmp_ctx,
1460                                                 &ldb_tmp);
1461         if (!W_ERROR_IS_OK(status)) {
1462                 talloc_free(tmp_ctx);
1463                 return status;
1464         }
1465
1466         talloc_free(tmp_ctx);
1467         return WERR_OK;
1468 }
1469
1470 static WERROR dsdb_syntax_UNICODE_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
1471                                                  const struct dsdb_attribute *attr,
1472                                                  const struct drsuapi_DsReplicaAttribute *in,
1473                                                  TALLOC_CTX *mem_ctx,
1474                                                  struct ldb_message_element *out)
1475 {
1476         unsigned int i;
1477
1478         out->flags      = 0;
1479         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1480         W_ERROR_HAVE_NO_MEMORY(out->name);
1481
1482         out->num_values = in->value_ctr.num_values;
1483         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1484         W_ERROR_HAVE_NO_MEMORY(out->values);
1485
1486         for (i=0; i < out->num_values; i++) {
1487                 size_t converted_size = 0;
1488                 char *str;
1489
1490                 if (in->value_ctr.values[i].blob == NULL) {
1491                         return WERR_FOOBAR;
1492                 }
1493
1494                 if (in->value_ctr.values[i].blob->length == 0) {
1495                         return WERR_FOOBAR;
1496                 }
1497
1498                 if (!convert_string_talloc(out->values,
1499                                            CH_UTF16, CH_UNIX,
1500                                            in->value_ctr.values[i].blob->data,
1501                                            in->value_ctr.values[i].blob->length,
1502                                            (void **)&str, &converted_size)) {
1503                         return WERR_FOOBAR;
1504                 }
1505
1506                 out->values[i] = data_blob_string_const(str);
1507         }
1508
1509         return WERR_OK;
1510 }
1511
1512 static WERROR dsdb_syntax_UNICODE_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1513                                                  const struct dsdb_attribute *attr,
1514                                                  const struct ldb_message_element *in,
1515                                                  TALLOC_CTX *mem_ctx,
1516                                                  struct drsuapi_DsReplicaAttribute *out)
1517 {
1518         unsigned int i;
1519         DATA_BLOB *blobs;
1520
1521         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1522                 return WERR_FOOBAR;
1523         }
1524
1525         out->attid                      = dsdb_attribute_get_attid(attr,
1526                                                                    ctx->is_schema_nc);
1527         out->value_ctr.num_values       = in->num_values;
1528         out->value_ctr.values           = talloc_array(mem_ctx,
1529                                                        struct drsuapi_DsAttributeValue,
1530                                                        in->num_values);
1531         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1532
1533         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1534         W_ERROR_HAVE_NO_MEMORY(blobs);
1535
1536         for (i=0; i < in->num_values; i++) {
1537                 out->value_ctr.values[i].blob   = &blobs[i];
1538
1539                 if (!convert_string_talloc(blobs,
1540                                            CH_UNIX, CH_UTF16,
1541                                            in->values[i].data, in->values[i].length,
1542                                            (void **)&blobs[i].data, &blobs[i].length)) {
1543                         return WERR_FOOBAR;
1544                 }
1545         }
1546
1547         return WERR_OK;
1548 }
1549
1550 static WERROR dsdb_syntax_UNICODE_validate_one_val(const struct dsdb_syntax_ctx *ctx,
1551                                                    const struct dsdb_attribute *attr,
1552                                                    const struct ldb_val *val)
1553 {
1554         void *dst = NULL;
1555         size_t size;
1556         bool ok;
1557
1558         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1559                 return WERR_FOOBAR;
1560         }
1561
1562         ok = convert_string_talloc(ctx->ldb,
1563                                    CH_UNIX, CH_UTF16,
1564                                    val->data,
1565                                    val->length,
1566                                    (void **)&dst,
1567                                    &size);
1568         TALLOC_FREE(dst);
1569         if (!ok) {
1570                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1571         }
1572
1573         if (attr->rangeLower) {
1574                 if ((size/2) < *attr->rangeLower) {
1575                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1576                 }
1577         }
1578
1579         if (attr->rangeUpper) {
1580                 if ((size/2) > *attr->rangeUpper) {
1581                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1582                 }
1583         }
1584
1585         return WERR_OK;
1586 }
1587
1588 static WERROR dsdb_syntax_UNICODE_validate_ldb(const struct dsdb_syntax_ctx *ctx,
1589                                                const struct dsdb_attribute *attr,
1590                                                const struct ldb_message_element *in)
1591 {
1592         WERROR status;
1593         unsigned int i;
1594
1595         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1596                 return WERR_FOOBAR;
1597         }
1598
1599         for (i=0; i < in->num_values; i++) {
1600                 if (in->values[i].length == 0) {
1601                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1602                 }
1603
1604                 status = dsdb_syntax_UNICODE_validate_one_val(ctx,
1605                                                               attr,
1606                                                               &in->values[i]);
1607                 if (!W_ERROR_IS_OK(status)) {
1608                         return status;
1609                 }
1610         }
1611
1612         return WERR_OK;
1613 }
1614
1615 static WERROR dsdb_syntax_one_DN_drsuapi_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
1616                                                 const struct dsdb_syntax *syntax,
1617                                                 const DATA_BLOB *in, DATA_BLOB *out)
1618 {
1619         struct drsuapi_DsReplicaObjectIdentifier3 id3;
1620         enum ndr_err_code ndr_err;
1621         DATA_BLOB guid_blob;
1622         struct ldb_dn *dn;
1623         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1624         int ret;
1625         NTSTATUS status;
1626
1627         if (!tmp_ctx) {
1628                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1629         }
1630
1631         if (in == NULL) {
1632                 talloc_free(tmp_ctx);
1633                 return WERR_FOOBAR;
1634         }
1635
1636         if (in->length == 0) {
1637                 talloc_free(tmp_ctx);
1638                 return WERR_FOOBAR;
1639         }
1640
1641
1642         /* windows sometimes sends an extra two pad bytes here */
1643         ndr_err = ndr_pull_struct_blob(in,
1644                                        tmp_ctx, &id3,
1645                                        (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3);
1646         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1647                 status = ndr_map_error2ntstatus(ndr_err);
1648                 talloc_free(tmp_ctx);
1649                 return ntstatus_to_werror(status);
1650         }
1651
1652         dn = ldb_dn_new(tmp_ctx, ldb, id3.dn);
1653         if (!dn) {
1654                 talloc_free(tmp_ctx);
1655                 /* If this fails, it must be out of memory, as it does not do much parsing */
1656                 W_ERROR_HAVE_NO_MEMORY(dn);
1657         }
1658
1659         if (!GUID_all_zero(&id3.guid)) {
1660                 status = GUID_to_ndr_blob(&id3.guid, tmp_ctx, &guid_blob);
1661                 if (!NT_STATUS_IS_OK(status)) {
1662                         talloc_free(tmp_ctx);
1663                         return ntstatus_to_werror(status);
1664                 }
1665
1666                 ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
1667                 if (ret != LDB_SUCCESS) {
1668                         talloc_free(tmp_ctx);
1669                         return WERR_FOOBAR;
1670                 }
1671                 talloc_free(guid_blob.data);
1672         }
1673
1674         if (id3.__ndr_size_sid) {
1675                 DATA_BLOB sid_blob;
1676                 ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, &id3.sid,
1677                                                (ndr_push_flags_fn_t)ndr_push_dom_sid);
1678                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1679                         status = ndr_map_error2ntstatus(ndr_err);
1680                         talloc_free(tmp_ctx);
1681                         return ntstatus_to_werror(status);
1682                 }
1683
1684                 ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
1685                 if (ret != LDB_SUCCESS) {
1686                         talloc_free(tmp_ctx);
1687                         return WERR_FOOBAR;
1688                 }
1689         }
1690
1691         *out = data_blob_string_const(ldb_dn_get_extended_linearized(mem_ctx, dn, 1));
1692         talloc_free(tmp_ctx);
1693         return WERR_OK;
1694 }
1695
1696 static WERROR dsdb_syntax_DN_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
1697                                             const struct dsdb_attribute *attr,
1698                                             const struct drsuapi_DsReplicaAttribute *in,
1699                                             TALLOC_CTX *mem_ctx,
1700                                             struct ldb_message_element *out)
1701 {
1702         unsigned int i;
1703
1704         out->flags      = 0;
1705         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1706         W_ERROR_HAVE_NO_MEMORY(out->name);
1707
1708         out->num_values = in->value_ctr.num_values;
1709         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1710         W_ERROR_HAVE_NO_MEMORY(out->values);
1711
1712         for (i=0; i < out->num_values; i++) {
1713                 WERROR status = dsdb_syntax_one_DN_drsuapi_to_ldb(out->values, ctx->ldb, attr->syntax,
1714                                                                   in->value_ctr.values[i].blob,
1715                                                                   &out->values[i]);
1716                 if (!W_ERROR_IS_OK(status)) {
1717                         return status;
1718                 }
1719
1720         }
1721
1722         return WERR_OK;
1723 }
1724
1725 static WERROR dsdb_syntax_DN_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1726                                             const struct dsdb_attribute *attr,
1727                                             const struct ldb_message_element *in,
1728                                             TALLOC_CTX *mem_ctx,
1729                                             struct drsuapi_DsReplicaAttribute *out)
1730 {
1731         unsigned int i;
1732         DATA_BLOB *blobs;
1733
1734         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1735                 return WERR_FOOBAR;
1736         }
1737
1738         out->attid                      = dsdb_attribute_get_attid(attr,
1739                                                                    ctx->is_schema_nc);
1740         out->value_ctr.num_values       = in->num_values;
1741         out->value_ctr.values           = talloc_array(mem_ctx,
1742                                                        struct drsuapi_DsAttributeValue,
1743                                                        in->num_values);
1744         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1745
1746         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1747         W_ERROR_HAVE_NO_MEMORY(blobs);
1748
1749         for (i=0; i < in->num_values; i++) {
1750                 struct drsuapi_DsReplicaObjectIdentifier3 id3;
1751                 enum ndr_err_code ndr_err;
1752                 struct ldb_dn *dn;
1753                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1754                 NTSTATUS status;
1755
1756                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1757
1758                 out->value_ctr.values[i].blob   = &blobs[i];
1759
1760                 dn = ldb_dn_from_ldb_val(tmp_ctx, ctx->ldb, &in->values[i]);
1761
1762                 W_ERROR_HAVE_NO_MEMORY(dn);
1763
1764                 ZERO_STRUCT(id3);
1765
1766                 status = dsdb_get_extended_dn_guid(dn, &id3.guid, "GUID");
1767                 if (!NT_STATUS_IS_OK(status) &&
1768                     !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1769                         talloc_free(tmp_ctx);
1770                         return ntstatus_to_werror(status);
1771                 }
1772
1773                 status = dsdb_get_extended_dn_sid(dn, &id3.sid, "SID");
1774                 if (!NT_STATUS_IS_OK(status) &&
1775                     !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1776                         talloc_free(tmp_ctx);
1777                         return ntstatus_to_werror(status);
1778                 }
1779
1780                 id3.dn = ldb_dn_get_linearized(dn);
1781
1782                 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
1783                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1784                         status = ndr_map_error2ntstatus(ndr_err);
1785                         talloc_free(tmp_ctx);
1786                         return ntstatus_to_werror(status);
1787                 }
1788                 talloc_free(tmp_ctx);
1789         }
1790
1791         return WERR_OK;
1792 }
1793
1794 static WERROR dsdb_syntax_DN_validate_one_val(const struct dsdb_syntax_ctx *ctx,
1795                                               const struct dsdb_attribute *attr,
1796                                               const struct ldb_val *val,
1797                                               TALLOC_CTX *mem_ctx,
1798                                               struct dsdb_dn **_dsdb_dn)
1799 {
1800         static const char * const extended_list[] = { "GUID", "SID", NULL };
1801         enum ndr_err_code ndr_err;
1802         struct GUID guid;
1803         struct dom_sid sid;
1804         const DATA_BLOB *sid_blob;
1805         struct dsdb_dn *dsdb_dn;
1806         struct ldb_dn *dn;
1807         char *dn_str;
1808         struct ldb_dn *dn2;
1809         char *dn2_str;
1810         int num_components;
1811         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1812         NTSTATUS status;
1813
1814         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1815
1816         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1817                 return WERR_FOOBAR;
1818         }
1819
1820         dsdb_dn = dsdb_dn_parse(tmp_ctx, ctx->ldb, val,
1821                                 attr->syntax->ldap_oid);
1822         if (!dsdb_dn) {
1823                 talloc_free(tmp_ctx);
1824                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1825         }
1826         dn = dsdb_dn->dn;
1827
1828         dn2 = ldb_dn_copy(tmp_ctx, dn);
1829         if (dn == NULL) {
1830                 talloc_free(tmp_ctx);
1831                 return WERR_NOMEM;
1832         }
1833
1834         num_components = ldb_dn_get_comp_num(dn);
1835
1836         status = dsdb_get_extended_dn_guid(dn, &guid, "GUID");
1837         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1838                 num_components++;
1839         } else if (!NT_STATUS_IS_OK(status)) {
1840                 talloc_free(tmp_ctx);
1841                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1842         }
1843
1844         sid_blob = ldb_dn_get_extended_component(dn, "SID");
1845         if (sid_blob) {
1846                 num_components++;
1847                 ndr_err = ndr_pull_struct_blob_all(sid_blob,
1848                                                    tmp_ctx,
1849                                                    &sid,
1850                                                    (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1851                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1852                         talloc_free(tmp_ctx);
1853                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1854                 }
1855         }
1856
1857         /* Do not allow links to the RootDSE */
1858         if (num_components == 0) {
1859                 talloc_free(tmp_ctx);
1860                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1861         }
1862
1863         /*
1864          * We need to check that only "GUID" and "SID" are
1865          * specified as extended components, we do that
1866          * by comparing the dn's after removing all components
1867          * from one dn and only the allowed subset from the other
1868          * one.
1869          */
1870         ldb_dn_extended_filter(dn, extended_list);
1871
1872         dn_str = ldb_dn_get_extended_linearized(tmp_ctx, dn, 0);
1873         if (dn_str == NULL) {
1874                 talloc_free(tmp_ctx);
1875                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1876         }
1877         dn2_str = ldb_dn_get_extended_linearized(tmp_ctx, dn2, 0);
1878         if (dn2_str == NULL) {
1879                 talloc_free(tmp_ctx);
1880                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1881         }
1882
1883         if (strcmp(dn_str, dn2_str) != 0) {
1884                 talloc_free(tmp_ctx);
1885                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1886         }
1887
1888         *_dsdb_dn = talloc_move(mem_ctx, &dsdb_dn);
1889         talloc_free(tmp_ctx);
1890         return WERR_OK;
1891 }
1892
1893 static WERROR dsdb_syntax_DN_validate_ldb(const struct dsdb_syntax_ctx *ctx,
1894                                           const struct dsdb_attribute *attr,
1895                                           const struct ldb_message_element *in)
1896 {
1897         unsigned int i;
1898
1899         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1900                 return WERR_FOOBAR;
1901         }
1902
1903         for (i=0; i < in->num_values; i++) {
1904                 WERROR status;
1905                 struct dsdb_dn *dsdb_dn;
1906                 TALLOC_CTX *tmp_ctx = talloc_new(ctx->ldb);
1907                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1908
1909                 status = dsdb_syntax_DN_validate_one_val(ctx,
1910                                                          attr,
1911                                                          &in->values[i],
1912                                                          tmp_ctx, &dsdb_dn);
1913                 if (!W_ERROR_IS_OK(status)) {
1914                         talloc_free(tmp_ctx);
1915                         return status;
1916                 }
1917
1918                 if (dsdb_dn->dn_format != DSDB_NORMAL_DN) {
1919                         talloc_free(tmp_ctx);
1920                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1921                 }
1922
1923                 talloc_free(tmp_ctx);
1924         }
1925
1926         return WERR_OK;
1927 }
1928
1929 static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
1930                                                    const struct dsdb_attribute *attr,
1931                                                    const struct drsuapi_DsReplicaAttribute *in,
1932                                                    TALLOC_CTX *mem_ctx,
1933                                                    struct ldb_message_element *out)
1934 {
1935         unsigned int i;
1936         int ret;
1937
1938         out->flags      = 0;
1939         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1940         W_ERROR_HAVE_NO_MEMORY(out->name);
1941
1942         out->num_values = in->value_ctr.num_values;
1943         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1944         W_ERROR_HAVE_NO_MEMORY(out->values);
1945
1946         for (i=0; i < out->num_values; i++) {
1947                 struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
1948                 enum ndr_err_code ndr_err;
1949                 DATA_BLOB guid_blob;
1950                 struct ldb_dn *dn;
1951                 struct dsdb_dn *dsdb_dn;
1952                 NTSTATUS status;
1953                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1954                 if (!tmp_ctx) {
1955                         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1956                 }
1957
1958                 if (in->value_ctr.values[i].blob == NULL) {
1959                         talloc_free(tmp_ctx);
1960                         return WERR_FOOBAR;
1961                 }
1962
1963                 if (in->value_ctr.values[i].blob->length == 0) {
1964                         talloc_free(tmp_ctx);
1965                         return WERR_FOOBAR;
1966                 }
1967
1968
1969                 /* windows sometimes sends an extra two pad bytes here */
1970                 ndr_err = ndr_pull_struct_blob(in->value_ctr.values[i].blob,
1971                                                tmp_ctx, &id3,
1972                                                (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3Binary);
1973                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1974                         status = ndr_map_error2ntstatus(ndr_err);
1975                         talloc_free(tmp_ctx);
1976                         return ntstatus_to_werror(status);
1977                 }
1978
1979                 dn = ldb_dn_new(tmp_ctx, ctx->ldb, id3.dn);
1980                 if (!dn) {
1981                         talloc_free(tmp_ctx);
1982                         /* If this fails, it must be out of memory, as it does not do much parsing */
1983                         W_ERROR_HAVE_NO_MEMORY(dn);
1984                 }
1985
1986                 if (!GUID_all_zero(&id3.guid)) {
1987                         status = GUID_to_ndr_blob(&id3.guid, tmp_ctx, &guid_blob);
1988                         if (!NT_STATUS_IS_OK(status)) {
1989                                 talloc_free(tmp_ctx);
1990                                 return ntstatus_to_werror(status);
1991                         }
1992
1993                         ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
1994                         if (ret != LDB_SUCCESS) {
1995                                 talloc_free(tmp_ctx);
1996                                 return WERR_FOOBAR;
1997                         }
1998                         talloc_free(guid_blob.data);
1999                 }
2000
2001                 if (id3.__ndr_size_sid) {
2002                         DATA_BLOB sid_blob;
2003                         ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, &id3.sid,
2004                                                        (ndr_push_flags_fn_t)ndr_push_dom_sid);
2005                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2006                                 status = ndr_map_error2ntstatus(ndr_err);
2007                                 talloc_free(tmp_ctx);
2008                                 return ntstatus_to_werror(status);
2009                         }
2010
2011                         ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
2012                         if (ret != LDB_SUCCESS) {
2013                                 talloc_free(tmp_ctx);
2014                                 return WERR_FOOBAR;
2015                         }
2016                 }
2017
2018                 /* set binary stuff */
2019                 dsdb_dn = dsdb_dn_construct(tmp_ctx, dn, id3.binary, attr->syntax->ldap_oid);
2020                 if (!dsdb_dn) {
2021                         /* If this fails, it must be out of memory, we know the ldap_oid is valid */
2022                         talloc_free(tmp_ctx);
2023                         W_ERROR_HAVE_NO_MEMORY(dsdb_dn);
2024                 }
2025                 out->values[i] = data_blob_string_const(dsdb_dn_get_extended_linearized(out->values, dsdb_dn, 1));
2026                 talloc_free(tmp_ctx);
2027         }
2028
2029         return WERR_OK;
2030 }
2031
2032 static WERROR dsdb_syntax_DN_BINARY_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
2033                                                    const struct dsdb_attribute *attr,
2034                                                    const struct ldb_message_element *in,
2035                                                    TALLOC_CTX *mem_ctx,
2036                                                    struct drsuapi_DsReplicaAttribute *out)
2037 {
2038         unsigned int i;
2039         DATA_BLOB *blobs;
2040
2041         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
2042                 return WERR_FOOBAR;
2043         }
2044
2045         out->attid                      = dsdb_attribute_get_attid(attr,
2046                                                                    ctx->is_schema_nc);
2047         out->value_ctr.num_values       = in->num_values;
2048         out->value_ctr.values           = talloc_array(mem_ctx,
2049                                                        struct drsuapi_DsAttributeValue,
2050                                                        in->num_values);
2051         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
2052
2053         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
2054         W_ERROR_HAVE_NO_MEMORY(blobs);
2055
2056         for (i=0; i < in->num_values; i++) {
2057                 struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
2058                 enum ndr_err_code ndr_err;
2059                 const DATA_BLOB *sid_blob;
2060                 struct dsdb_dn *dsdb_dn;
2061                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
2062                 NTSTATUS status;
2063
2064                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
2065
2066                 out->value_ctr.values[i].blob   = &blobs[i];
2067
2068                 dsdb_dn = dsdb_dn_parse(tmp_ctx, ctx->ldb, &in->values[i], attr->syntax->ldap_oid);
2069
2070                 if (!dsdb_dn) {
2071                         talloc_free(tmp_ctx);
2072                         return ntstatus_to_werror(NT_STATUS_INVALID_PARAMETER);
2073                 }
2074
2075                 ZERO_STRUCT(id3);
2076
2077                 status = dsdb_get_extended_dn_guid(dsdb_dn->dn, &id3.guid, "GUID");
2078                 if (!NT_STATUS_IS_OK(status) &&
2079                     !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2080                         talloc_free(tmp_ctx);
2081                         return ntstatus_to_werror(status);
2082                 }
2083
2084                 sid_blob = ldb_dn_get_extended_component(dsdb_dn->dn, "SID");
2085                 if (sid_blob) {
2086
2087                         ndr_err = ndr_pull_struct_blob_all(sid_blob,
2088                                                            tmp_ctx, &id3.sid,
2089                                                            (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
2090                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2091                                 status = ndr_map_error2ntstatus(ndr_err);
2092                                 talloc_free(tmp_ctx);
2093                                 return ntstatus_to_werror(status);
2094                         }
2095                 }
2096
2097                 id3.dn = ldb_dn_get_linearized(dsdb_dn->dn);
2098
2099                 /* get binary stuff */
2100                 id3.binary = dsdb_dn->extra_part;
2101
2102                 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3Binary);
2103                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2104                         status = ndr_map_error2ntstatus(ndr_err);
2105                         talloc_free(tmp_ctx);
2106                         return ntstatus_to_werror(status);
2107                 }
2108                 talloc_free(tmp_ctx);
2109         }
2110
2111         return WERR_OK;
2112 }
2113
2114 static WERROR dsdb_syntax_DN_BINARY_validate_ldb(const struct dsdb_syntax_ctx *ctx,
2115                                                  const struct dsdb_attribute *attr,
2116                                                  const struct ldb_message_element *in)
2117 {
2118         unsigned int i;
2119
2120         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
2121                 return WERR_FOOBAR;
2122         }
2123
2124         for (i=0; i < in->num_values; i++) {
2125                 WERROR status;
2126                 struct dsdb_dn *dsdb_dn;
2127                 TALLOC_CTX *tmp_ctx = talloc_new(ctx->ldb);
2128                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
2129
2130                 status = dsdb_syntax_DN_validate_one_val(ctx,
2131                                                          attr,
2132                                                          &in->values[i],
2133                                                          tmp_ctx, &dsdb_dn);
2134                 if (!W_ERROR_IS_OK(status)) {
2135                         talloc_free(tmp_ctx);
2136                         return status;
2137                 }
2138
2139                 if (dsdb_dn->dn_format != DSDB_BINARY_DN) {
2140                         talloc_free(tmp_ctx);
2141                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
2142                 }
2143
2144                 status = dsdb_syntax_DATA_BLOB_validate_one_val(ctx,
2145                                                                 attr,
2146                                                                 &dsdb_dn->extra_part);
2147                 if (!W_ERROR_IS_OK(status)) {
2148                         talloc_free(tmp_ctx);
2149                         return status;
2150                 }
2151
2152                 talloc_free(tmp_ctx);
2153         }
2154
2155         return WERR_OK;
2156 }
2157
2158 static WERROR dsdb_syntax_DN_STRING_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
2159                                                    const struct dsdb_attribute *attr,
2160                                                    const struct drsuapi_DsReplicaAttribute *in,
2161                                                    TALLOC_CTX *mem_ctx,
2162                                                    struct ldb_message_element *out)
2163 {
2164         return dsdb_syntax_DN_BINARY_drsuapi_to_ldb(ctx,
2165                                                     attr,
2166                                                     in,
2167                                                     mem_ctx,
2168                                                     out);
2169 }
2170
2171 static WERROR dsdb_syntax_DN_STRING_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
2172                                                    const struct dsdb_attribute *attr,
2173                                                    const struct ldb_message_element *in,
2174                                                    TALLOC_CTX *mem_ctx,
2175                                                    struct drsuapi_DsReplicaAttribute *out)
2176 {
2177         return dsdb_syntax_DN_BINARY_ldb_to_drsuapi(ctx,
2178                                                     attr,
2179                                                     in,
2180                                                     mem_ctx,
2181                                                     out);
2182 }
2183
2184 static WERROR dsdb_syntax_DN_STRING_validate_ldb(const struct dsdb_syntax_ctx *ctx,
2185                                                  const struct dsdb_attribute *attr,
2186                                                  const struct ldb_message_element *in)
2187 {
2188         unsigned int i;
2189
2190         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
2191                 return WERR_FOOBAR;
2192         }
2193
2194         for (i=0; i < in->num_values; i++) {
2195                 WERROR status;
2196                 struct dsdb_dn *dsdb_dn;
2197                 TALLOC_CTX *tmp_ctx = talloc_new(ctx->ldb);
2198                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
2199
2200                 status = dsdb_syntax_DN_validate_one_val(ctx,
2201                                                          attr,
2202                                                          &in->values[i],
2203                                                          tmp_ctx, &dsdb_dn);
2204                 if (!W_ERROR_IS_OK(status)) {
2205                         talloc_free(tmp_ctx);
2206                         return status;
2207                 }
2208
2209                 if (dsdb_dn->dn_format != DSDB_STRING_DN) {
2210                         talloc_free(tmp_ctx);
2211                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
2212                 }
2213
2214                 status = dsdb_syntax_UNICODE_validate_one_val(ctx,
2215                                                               attr,
2216                                                               &dsdb_dn->extra_part);
2217                 if (!W_ERROR_IS_OK(status)) {
2218                         talloc_free(tmp_ctx);
2219                         return status;
2220                 }
2221
2222                 talloc_free(tmp_ctx);
2223         }
2224
2225         return WERR_OK;
2226 }
2227
2228 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
2229                                                               const struct dsdb_attribute *attr,
2230                                                               const struct drsuapi_DsReplicaAttribute *in,
2231                                                               TALLOC_CTX *mem_ctx,
2232                                                               struct ldb_message_element *out)
2233 {
2234         unsigned int i;
2235
2236         out->flags      = 0;
2237         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
2238         W_ERROR_HAVE_NO_MEMORY(out->name);
2239
2240         out->num_values = in->value_ctr.num_values;
2241         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
2242         W_ERROR_HAVE_NO_MEMORY(out->values);
2243
2244         for (i=0; i < out->num_values; i++) {
2245                 size_t len;
2246                 size_t converted_size = 0;
2247                 char *str;
2248
2249                 if (in->value_ctr.values[i].blob == NULL) {
2250                         return WERR_FOOBAR;
2251                 }
2252
2253                 if (in->value_ctr.values[i].blob->length < 4) {
2254                         return WERR_FOOBAR;
2255                 }
2256
2257                 len = IVAL(in->value_ctr.values[i].blob->data, 0);
2258
2259                 if (len != in->value_ctr.values[i].blob->length) {
2260                         return WERR_FOOBAR;
2261                 }
2262
2263                 if (!convert_string_talloc(out->values, CH_UTF16, CH_UNIX,
2264                                            in->value_ctr.values[i].blob->data+4,
2265                                            in->value_ctr.values[i].blob->length-4,
2266                                            (void **)&str, &converted_size)) {
2267                         return WERR_FOOBAR;
2268                 }
2269
2270                 out->values[i] = data_blob_string_const(str);
2271         }
2272
2273         return WERR_OK;
2274 }
2275
2276 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
2277                                                               const struct dsdb_attribute *attr,
2278                                                               const struct ldb_message_element *in,
2279                                                               TALLOC_CTX *mem_ctx,
2280                                                               struct drsuapi_DsReplicaAttribute *out)
2281 {
2282         unsigned int i;
2283         DATA_BLOB *blobs;
2284
2285         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
2286                 return WERR_FOOBAR;
2287         }
2288
2289         out->attid                      = dsdb_attribute_get_attid(attr,
2290                                                                    ctx->is_schema_nc);
2291         out->value_ctr.num_values       = in->num_values;
2292         out->value_ctr.values           = talloc_array(mem_ctx,
2293                                                        struct drsuapi_DsAttributeValue,
2294                                                        in->num_values);
2295         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
2296
2297         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
2298         W_ERROR_HAVE_NO_MEMORY(blobs);
2299
2300         for (i=0; i < in->num_values; i++) {
2301                 uint8_t *data;
2302                 size_t ret;
2303
2304                 out->value_ctr.values[i].blob   = &blobs[i];
2305
2306                 if (!convert_string_talloc(blobs, CH_UNIX, CH_UTF16,
2307                                            in->values[i].data,
2308                                            in->values[i].length,
2309                                            (void **)&data, &ret)) {
2310                         return WERR_FOOBAR;
2311                 }
2312
2313                 blobs[i] = data_blob_talloc(blobs, NULL, 4 + ret);
2314                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
2315
2316                 SIVAL(blobs[i].data, 0, 4 + ret);
2317
2318                 if (ret > 0) {
2319                         memcpy(blobs[i].data + 4, data, ret);
2320                         talloc_free(data);
2321                 }
2322         }
2323
2324         return WERR_OK;
2325 }
2326
2327 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_validate_ldb(const struct dsdb_syntax_ctx *ctx,
2328                                                             const struct dsdb_attribute *attr,
2329                                                             const struct ldb_message_element *in)
2330 {
2331         return dsdb_syntax_UNICODE_validate_ldb(ctx,
2332                                                 attr,
2333                                                 in);
2334 }
2335
2336 #define OMOBJECTCLASS(val) { .length = sizeof(val) - 1, .data = discard_const_p(uint8_t, val) }
2337
2338 static const struct dsdb_syntax dsdb_syntaxes[] = {
2339         {
2340                 .name                   = "Boolean",
2341                 .ldap_oid               = LDB_SYNTAX_BOOLEAN,
2342                 .oMSyntax               = 1,
2343                 .attributeSyntax_oid    = "2.5.5.8",
2344                 .drsuapi_to_ldb         = dsdb_syntax_BOOL_drsuapi_to_ldb,
2345                 .ldb_to_drsuapi         = dsdb_syntax_BOOL_ldb_to_drsuapi,
2346                 .validate_ldb           = dsdb_syntax_BOOL_validate_ldb,
2347                 .equality               = "booleanMatch",
2348                 .comment                = "Boolean"
2349         },{
2350                 .name                   = "Integer",
2351                 .ldap_oid               = LDB_SYNTAX_INTEGER,
2352                 .oMSyntax               = 2,
2353                 .attributeSyntax_oid    = "2.5.5.9",
2354                 .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
2355                 .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
2356                 .validate_ldb           = dsdb_syntax_INT32_validate_ldb,
2357                 .equality               = "integerMatch",
2358                 .comment                = "Integer",
2359                 .ldb_syntax             = LDB_SYNTAX_SAMBA_INT32
2360         },{
2361                 .name                   = "String(Octet)",
2362                 .ldap_oid               = LDB_SYNTAX_OCTET_STRING,
2363                 .oMSyntax               = 4,
2364                 .attributeSyntax_oid    = "2.5.5.10",
2365                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2366                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2367                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2368                 .equality               = "octetStringMatch",
2369                 .comment                = "Octet String",
2370         },{
2371                 .name                   = "String(Sid)",
2372                 .ldap_oid               = LDB_SYNTAX_OCTET_STRING,
2373                 .oMSyntax               = 4,
2374                 .attributeSyntax_oid    = "2.5.5.17",
2375                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2376                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2377                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2378                 .equality               = "octetStringMatch",
2379                 .comment                = "Octet String - Security Identifier (SID)",
2380                 .ldb_syntax             = LDB_SYNTAX_SAMBA_SID
2381         },{
2382                 .name                   = "String(Object-Identifier)",
2383                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.38",
2384                 .oMSyntax               = 6,
2385                 .attributeSyntax_oid    = "2.5.5.2",
2386                 .drsuapi_to_ldb         = dsdb_syntax_OID_drsuapi_to_ldb,
2387                 .ldb_to_drsuapi         = dsdb_syntax_OID_ldb_to_drsuapi,
2388                 .validate_ldb           = dsdb_syntax_OID_validate_ldb,
2389                 .equality               = "caseIgnoreMatch", /* Would use "objectIdentifierMatch" but most are ldap attribute/class names */
2390                 .comment                = "OID String",
2391                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING
2392         },{
2393                 .name                   = "Enumeration",
2394                 .ldap_oid               = LDB_SYNTAX_INTEGER,
2395                 .oMSyntax               = 10,
2396                 .attributeSyntax_oid    = "2.5.5.9",
2397                 .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
2398                 .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
2399                 .validate_ldb           = dsdb_syntax_INT32_validate_ldb,
2400                 .ldb_syntax             = LDB_SYNTAX_SAMBA_INT32
2401         },{
2402         /* not used in w2k3 forest */
2403                 .name                   = "String(Numeric)",
2404                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.36",
2405                 .oMSyntax               = 18,
2406                 .attributeSyntax_oid    = "2.5.5.6",
2407                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2408                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2409                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2410                 .equality               = "numericStringMatch",
2411                 .substring              = "numericStringSubstringsMatch",
2412                 .comment                = "Numeric String",
2413                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
2414         },{
2415                 .name                   = "String(Printable)",
2416                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.44",
2417                 .oMSyntax               = 19,
2418                 .attributeSyntax_oid    = "2.5.5.5",
2419                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2420                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2421                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2422                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
2423         },{
2424                 .name                   = "String(Teletex)",
2425                 .ldap_oid               = "1.2.840.113556.1.4.905",
2426                 .oMSyntax               = 20,
2427                 .attributeSyntax_oid    = "2.5.5.4",
2428                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2429                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2430                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2431                 .equality               = "caseIgnoreMatch",
2432                 .substring              = "caseIgnoreSubstringsMatch",
2433                 .comment                = "Case Insensitive String",
2434                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
2435         },{
2436                 .name                   = "String(IA5)",
2437                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.26",
2438                 .oMSyntax               = 22,
2439                 .attributeSyntax_oid    = "2.5.5.5",
2440                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2441                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2442                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2443                 .equality               = "caseExactIA5Match",
2444                 .comment                = "Printable String",
2445                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
2446         },{
2447                 .name                   = "String(UTC-Time)",
2448                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.53",
2449                 .oMSyntax               = 23,
2450                 .attributeSyntax_oid    = "2.5.5.11",
2451                 .drsuapi_to_ldb         = dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb,
2452                 .ldb_to_drsuapi         = dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi,
2453                 .validate_ldb           = dsdb_syntax_NTTIME_UTC_validate_ldb,
2454                 .equality               = "generalizedTimeMatch",
2455                 .comment                = "UTC Time",
2456         },{
2457                 .name                   = "String(Generalized-Time)",
2458                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.24",
2459                 .oMSyntax               = 24,
2460                 .attributeSyntax_oid    = "2.5.5.11",
2461                 .drsuapi_to_ldb         = dsdb_syntax_NTTIME_drsuapi_to_ldb,
2462                 .ldb_to_drsuapi         = dsdb_syntax_NTTIME_ldb_to_drsuapi,
2463                 .validate_ldb           = dsdb_syntax_NTTIME_validate_ldb,
2464                 .equality               = "generalizedTimeMatch",
2465                 .comment                = "Generalized Time",
2466                 .ldb_syntax             = LDB_SYNTAX_UTC_TIME,
2467         },{
2468         /* not used in w2k3 schema */
2469                 .name                   = "String(Case Sensitive)",
2470                 .ldap_oid               = "1.2.840.113556.1.4.1362",
2471                 .oMSyntax               = 27,
2472                 .attributeSyntax_oid    = "2.5.5.3",
2473                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2474                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2475                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2476                 .equality               = "caseExactMatch",
2477                 .substring              = "caseExactSubstringsMatch",
2478                 /* TODO (kim): according to LDAP rfc we should be using same comparison
2479                  * as Directory String (LDB_SYNTAX_DIRECTORY_STRING), but case sensitive.
2480                  * But according to ms docs binary compare should do the job:
2481                  * http://msdn.microsoft.com/en-us/library/cc223200(v=PROT.10).aspx */
2482                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
2483         },{
2484                 .name                   = "String(Unicode)",
2485                 .ldap_oid               = LDB_SYNTAX_DIRECTORY_STRING,
2486                 .oMSyntax               = 64,
2487                 .attributeSyntax_oid    = "2.5.5.12",
2488                 .drsuapi_to_ldb         = dsdb_syntax_UNICODE_drsuapi_to_ldb,
2489                 .ldb_to_drsuapi         = dsdb_syntax_UNICODE_ldb_to_drsuapi,
2490                 .validate_ldb           = dsdb_syntax_UNICODE_validate_ldb,
2491                 .equality               = "caseIgnoreMatch",
2492                 .substring              = "caseIgnoreSubstringsMatch",
2493                 .comment                = "Directory String",
2494         },{
2495                 .name                   = "Interval/LargeInteger",
2496                 .ldap_oid               = "1.2.840.113556.1.4.906",
2497                 .oMSyntax               = 65,
2498                 .attributeSyntax_oid    = "2.5.5.16",
2499                 .drsuapi_to_ldb         = dsdb_syntax_INT64_drsuapi_to_ldb,
2500                 .ldb_to_drsuapi         = dsdb_syntax_INT64_ldb_to_drsuapi,
2501                 .validate_ldb           = dsdb_syntax_INT64_validate_ldb,
2502                 .equality               = "integerMatch",
2503                 .comment                = "Large Integer",
2504                 .ldb_syntax             = LDB_SYNTAX_INTEGER,
2505         },{
2506                 .name                   = "String(NT-Sec-Desc)",
2507                 .ldap_oid               = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
2508                 .oMSyntax               = 66,
2509                 .attributeSyntax_oid    = "2.5.5.15",
2510                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2511                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2512                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2513         },{
2514                 .name                   = "Object(DS-DN)",
2515                 .ldap_oid               = LDB_SYNTAX_DN,
2516                 .oMSyntax               = 127,
2517                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x4a"),
2518                 .attributeSyntax_oid    = "2.5.5.1",
2519                 .drsuapi_to_ldb         = dsdb_syntax_DN_drsuapi_to_ldb,
2520                 .ldb_to_drsuapi         = dsdb_syntax_DN_ldb_to_drsuapi,
2521                 .validate_ldb           = dsdb_syntax_DN_validate_ldb,
2522                 .equality               = "distinguishedNameMatch",
2523                 .comment                = "Object(DS-DN) == a DN",
2524         },{
2525                 .name                   = "Object(DN-Binary)",
2526                 .ldap_oid               = DSDB_SYNTAX_BINARY_DN,
2527                 .oMSyntax               = 127,
2528                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0b"),
2529                 .attributeSyntax_oid    = "2.5.5.7",
2530                 .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
2531                 .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
2532                 .validate_ldb           = dsdb_syntax_DN_BINARY_validate_ldb,
2533                 .equality               = "octetStringMatch",
2534                 .comment                = "OctetString: Binary+DN",
2535         },{
2536         /* not used in w2k3 schema, but used in Exchange schema*/
2537                 .name                   = "Object(OR-Name)",
2538                 .ldap_oid               = DSDB_SYNTAX_OR_NAME,
2539                 .oMSyntax               = 127,
2540                 .oMObjectClass          = OMOBJECTCLASS("\x56\x06\x01\x02\x05\x0b\x1D"),
2541                 .attributeSyntax_oid    = "2.5.5.7",
2542                 .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
2543                 .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
2544                 .validate_ldb           = dsdb_syntax_DN_BINARY_validate_ldb,
2545                 .equality               = "caseIgnoreMatch",
2546                 .ldb_syntax             = LDB_SYNTAX_DN,
2547         },{
2548         /*
2549          * TODO: verify if DATA_BLOB is correct here...!
2550          *
2551          *       repsFrom and repsTo are the only attributes using
2552          *       this attribute syntax, but they're not replicated...
2553          */
2554                 .name                   = "Object(Replica-Link)",
2555                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.40",
2556                 .oMSyntax               = 127,
2557                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x06"),
2558                 .attributeSyntax_oid    = "2.5.5.10",
2559                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2560                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2561                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2562         },{
2563                 .name                   = "Object(Presentation-Address)",
2564                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.43",
2565                 .oMSyntax               = 127,
2566                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x5c"),
2567                 .attributeSyntax_oid    = "2.5.5.13",
2568                 .drsuapi_to_ldb         = dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb,
2569                 .ldb_to_drsuapi         = dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi,
2570                 .validate_ldb           = dsdb_syntax_PRESENTATION_ADDRESS_validate_ldb,
2571                 .comment                = "Presentation Address",
2572                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
2573         },{
2574         /* not used in w2k3 schema */
2575                 .name                   = "Object(Access-Point)",
2576                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.2",
2577                 .oMSyntax               = 127,
2578                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x3e"),
2579                 .attributeSyntax_oid    = "2.5.5.14",
2580                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
2581                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
2582                 .validate_ldb           = dsdb_syntax_FOOBAR_validate_ldb,
2583                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
2584         },{
2585         /* not used in w2k3 schema */
2586                 .name                   = "Object(DN-String)",
2587                 .ldap_oid               = DSDB_SYNTAX_STRING_DN,
2588                 .oMSyntax               = 127,
2589                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0c"),
2590                 .attributeSyntax_oid    = "2.5.5.14",
2591                 .drsuapi_to_ldb         = dsdb_syntax_DN_STRING_drsuapi_to_ldb,
2592                 .ldb_to_drsuapi         = dsdb_syntax_DN_STRING_ldb_to_drsuapi,
2593                 .validate_ldb           = dsdb_syntax_DN_STRING_validate_ldb,
2594                 .equality               = "octetStringMatch",
2595                 .comment                = "OctetString: String+DN",
2596         }
2597 };
2598
2599 const struct dsdb_syntax *find_syntax_map_by_ad_oid(const char *ad_oid)
2600 {
2601         unsigned int i;
2602         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
2603                 if (strcasecmp(ad_oid, dsdb_syntaxes[i].attributeSyntax_oid) == 0) {
2604                         return &dsdb_syntaxes[i];
2605                 }
2606         }
2607         return NULL;
2608 }
2609
2610 const struct dsdb_syntax *find_syntax_map_by_ad_syntax(int oMSyntax)
2611 {
2612         unsigned int i;
2613         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
2614                 if (oMSyntax == dsdb_syntaxes[i].oMSyntax) {
2615                         return &dsdb_syntaxes[i];
2616                 }
2617         }
2618         return NULL;
2619 }
2620
2621 const struct dsdb_syntax *find_syntax_map_by_standard_oid(const char *standard_oid)
2622 {
2623         unsigned int i;
2624         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
2625                 if (strcasecmp(standard_oid, dsdb_syntaxes[i].ldap_oid) == 0) {
2626                         return &dsdb_syntaxes[i];
2627                 }
2628         }
2629         return NULL;
2630 }
2631
2632 const struct dsdb_syntax *dsdb_syntax_for_attribute(const struct dsdb_attribute *attr)
2633 {
2634         unsigned int i;
2635
2636         for (i=0; i < ARRAY_SIZE(dsdb_syntaxes); i++) {
2637                 if (attr->oMSyntax != dsdb_syntaxes[i].oMSyntax) continue;
2638
2639                 if (attr->oMObjectClass.length != dsdb_syntaxes[i].oMObjectClass.length) continue;
2640
2641                 if (attr->oMObjectClass.length) {
2642                         int ret;
2643                         ret = memcmp(attr->oMObjectClass.data,
2644                                      dsdb_syntaxes[i].oMObjectClass.data,
2645                                      attr->oMObjectClass.length);
2646                         if (ret != 0) continue;
2647                 }
2648
2649                 if (strcmp(attr->attributeSyntax_oid, dsdb_syntaxes[i].attributeSyntax_oid) != 0) continue;
2650
2651                 return &dsdb_syntaxes[i];
2652         }
2653
2654         return NULL;
2655 }
2656
2657 WERROR dsdb_attribute_drsuapi_to_ldb(struct ldb_context *ldb,
2658                                      const struct dsdb_schema *schema,
2659                                      const struct dsdb_schema_prefixmap *pfm_remote,
2660                                      const struct drsuapi_DsReplicaAttribute *in,
2661                                      TALLOC_CTX *mem_ctx,
2662                                      struct ldb_message_element *out)
2663 {
2664         const struct dsdb_attribute *sa;
2665         struct dsdb_syntax_ctx syntax_ctx;
2666         uint32_t attid_local;
2667
2668         /* use default syntax conversion context */
2669         dsdb_syntax_ctx_init(&syntax_ctx, ldb, schema);
2670         syntax_ctx.pfm_remote = pfm_remote;
2671
2672         switch (dsdb_pfm_get_attid_type(in->attid)) {
2673         case DSDB_ATTID_TYPE_PFM:
2674                 /* map remote ATTID to local ATTID */
2675                 if (!dsdb_syntax_attid_from_remote_attid(&syntax_ctx, mem_ctx, in->attid, &attid_local)) {
2676                         DEBUG(0,(__location__ ": Can't find local ATTID for 0x%08X\n",
2677                                  in->attid));
2678                         return WERR_FOOBAR;
2679                 }
2680                 break;
2681         case DSDB_ATTID_TYPE_INTID:
2682                 /* use IntId value directly */
2683                 attid_local = in->attid;
2684                 break;
2685         default:
2686                 /* we should never get here */
2687                 DEBUG(0,(__location__ ": Invalid ATTID type passed for conversion - 0x%08X\n",
2688                          in->attid));
2689                 return WERR_INVALID_PARAMETER;
2690         }
2691
2692         sa = dsdb_attribute_by_attributeID_id(schema, attid_local);
2693         if (!sa) {
2694                 DEBUG(1,(__location__ ": Unknown attributeID_id 0x%08X\n", in->attid));
2695                 return WERR_FOOBAR;
2696         }
2697
2698         return sa->syntax->drsuapi_to_ldb(&syntax_ctx, sa, in, mem_ctx, out);
2699 }
2700
2701 WERROR dsdb_attribute_ldb_to_drsuapi(struct ldb_context *ldb,
2702                                      const struct dsdb_schema *schema,
2703                                      const struct ldb_message_element *in,
2704                                      TALLOC_CTX *mem_ctx,
2705                                      struct drsuapi_DsReplicaAttribute *out)
2706 {
2707         const struct dsdb_attribute *sa;
2708         struct dsdb_syntax_ctx syntax_ctx;
2709
2710         sa = dsdb_attribute_by_lDAPDisplayName(schema, in->name);
2711         if (!sa) {
2712                 return WERR_FOOBAR;
2713         }
2714
2715         /* use default syntax conversion context */
2716         dsdb_syntax_ctx_init(&syntax_ctx, ldb, schema);
2717
2718         return sa->syntax->ldb_to_drsuapi(&syntax_ctx, sa, in, mem_ctx, out);
2719 }
2720