dsdb: fixed special case of zero NTTIME
[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                 if (v == 0) {
558                         /* special case for 1601 zero timestamp */
559                         out->values[i] = data_blob_string_const("16010101000000.0Z");
560                         continue;
561                 }
562                 v *= 10000000;
563                 t = nt_time_to_unix(v);
564
565                 /*
566                  * NOTE: On a w2k3 server you can set a GeneralizedTime string
567                  *       via LDAP, but you get back an UTCTime string,
568                  *       but via DRSUAPI you get back the NTTIME_1sec value
569                  *       that represents the GeneralizedTime value!
570                  *
571                  *       So if we store the UTCTime string in our ldb
572                  *       we'll loose information!
573                  */
574                 str = ldb_timestring_utc(out->values, t);
575                 W_ERROR_HAVE_NO_MEMORY(str);
576                 out->values[i] = data_blob_string_const(str);
577         }
578
579         return WERR_OK;
580 }
581
582 static WERROR dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
583                                                     const struct dsdb_attribute *attr,
584                                                     const struct ldb_message_element *in,
585                                                     TALLOC_CTX *mem_ctx,
586                                                     struct drsuapi_DsReplicaAttribute *out)
587 {
588         unsigned int i;
589         DATA_BLOB *blobs;
590
591         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
592                 return WERR_FOOBAR;
593         }
594
595         out->attid                      = dsdb_attribute_get_attid(attr,
596                                                                    ctx->is_schema_nc);
597         out->value_ctr.num_values       = in->num_values;
598         out->value_ctr.values           = talloc_array(mem_ctx,
599                                                        struct drsuapi_DsAttributeValue,
600                                                        in->num_values);
601         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
602
603         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
604         W_ERROR_HAVE_NO_MEMORY(blobs);
605
606         for (i=0; i < in->num_values; i++) {
607                 NTTIME v;
608                 time_t t;
609
610                 out->value_ctr.values[i].blob   = &blobs[i];
611
612                 blobs[i] = data_blob_talloc(blobs, NULL, 8);
613                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
614
615                 if (ldb_val_string_cmp("16010101000000.0Z", &in->values[i]) == 0) {
616                         SBVALS(blobs[i].data, 0, 0);
617                         continue;
618                 }
619
620                 t = ldb_string_utc_to_time((const char *)in->values[i].data);
621                 unix_to_nt_time(&v, t);
622                 v /= 10000000;
623
624                 SBVAL(blobs[i].data, 0, v);
625         }
626
627         return WERR_OK;
628 }
629
630 static WERROR dsdb_syntax_NTTIME_UTC_validate_ldb(const struct dsdb_syntax_ctx *ctx,
631                                                   const struct dsdb_attribute *attr,
632                                                   const struct ldb_message_element *in)
633 {
634         unsigned int i;
635
636         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
637                 return WERR_FOOBAR;
638         }
639
640         for (i=0; i < in->num_values; i++) {
641                 time_t t;
642                 char buf[sizeof("090826075717Z")];
643
644                 ZERO_STRUCT(buf);
645                 if (in->values[i].length >= sizeof(buf)) {
646                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
647                 }
648                 memcpy(buf, in->values[i].data, in->values[i].length);
649
650                 t = ldb_string_utc_to_time(buf);
651                 if (t == 0) {
652                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
653                 }
654
655                 if (attr->rangeLower) {
656                         if ((int32_t)t < (int32_t)*attr->rangeLower) {
657                                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
658                         }
659                 }
660
661                 if (attr->rangeUpper) {
662                         if ((int32_t)t > (int32_t)*attr->rangeLower) {
663                                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
664                         }
665                 }
666
667                 /*
668                  * TODO: verify the comment in the
669                  * dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb() function!
670                  */
671         }
672
673         return WERR_OK;
674 }
675
676 static WERROR dsdb_syntax_NTTIME_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
677                                                 const struct dsdb_attribute *attr,
678                                                 const struct drsuapi_DsReplicaAttribute *in,
679                                                 TALLOC_CTX *mem_ctx,
680                                                 struct ldb_message_element *out)
681 {
682         unsigned int i;
683
684         out->flags      = 0;
685         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
686         W_ERROR_HAVE_NO_MEMORY(out->name);
687
688         out->num_values = in->value_ctr.num_values;
689         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
690         W_ERROR_HAVE_NO_MEMORY(out->values);
691
692         for (i=0; i < out->num_values; i++) {
693                 NTTIME v;
694                 time_t t;
695                 char *str;
696
697                 if (in->value_ctr.values[i].blob == NULL) {
698                         return WERR_FOOBAR;
699                 }
700
701                 if (in->value_ctr.values[i].blob->length != 8) {
702                         return WERR_FOOBAR;
703                 }
704
705                 v = BVAL(in->value_ctr.values[i].blob->data, 0);
706                 if (v == 0) {
707                         /* special case for 1601 zero timestamp */
708                         out->values[i] = data_blob_string_const("16010101000000.0Z");
709                         continue;
710                 }
711                 v *= 10000000;
712                 t = nt_time_to_unix(v);
713
714                 str = ldb_timestring(out->values, t);
715                 W_ERROR_HAVE_NO_MEMORY(str);
716
717                 out->values[i] = data_blob_string_const(str);
718         }
719
720         return WERR_OK;
721 }
722
723 static WERROR dsdb_syntax_NTTIME_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
724                                                 const struct dsdb_attribute *attr,
725                                                 const struct ldb_message_element *in,
726                                                 TALLOC_CTX *mem_ctx,
727                                                 struct drsuapi_DsReplicaAttribute *out)
728 {
729         unsigned int i;
730         DATA_BLOB *blobs;
731
732         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
733                 return WERR_FOOBAR;
734         }
735
736         out->attid                      = dsdb_attribute_get_attid(attr,
737                                                                    ctx->is_schema_nc);
738         out->value_ctr.num_values       = in->num_values;
739         out->value_ctr.values           = talloc_array(mem_ctx,
740                                                        struct drsuapi_DsAttributeValue,
741                                                        in->num_values);
742         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
743
744         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
745         W_ERROR_HAVE_NO_MEMORY(blobs);
746
747         for (i=0; i < in->num_values; i++) {
748                 NTTIME v;
749                 time_t t;
750                 int ret;
751
752                 out->value_ctr.values[i].blob   = &blobs[i];
753
754                 blobs[i] = data_blob_talloc(blobs, NULL, 8);
755                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
756
757                 if (ldb_val_string_cmp("16010101000000.0Z", &in->values[i]) == 0) {
758                         SBVALS(blobs[i].data, 0, 0);
759                         continue;
760                 }
761
762                 ret = ldb_val_to_time(&in->values[i], &t);
763                 if (ret != LDB_SUCCESS) {
764                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
765                 }
766                 unix_to_nt_time(&v, t);
767                 v /= 10000000;
768
769                 SBVAL(blobs[i].data, 0, v);
770         }
771
772         return WERR_OK;
773 }
774
775 static WERROR dsdb_syntax_NTTIME_validate_ldb(const struct dsdb_syntax_ctx *ctx,
776                                               const struct dsdb_attribute *attr,
777                                               const struct ldb_message_element *in)
778 {
779         unsigned int i;
780
781         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
782                 return WERR_FOOBAR;
783         }
784
785         for (i=0; i < in->num_values; i++) {
786                 time_t t;
787                 int ret;
788
789                 ret = ldb_val_to_time(&in->values[i], &t);
790                 if (ret != LDB_SUCCESS) {
791                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
792                 }
793
794                 if (attr->rangeLower) {
795                         if ((int32_t)t < (int32_t)*attr->rangeLower) {
796                                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
797                         }
798                 }
799
800                 if (attr->rangeUpper) {
801                         if ((int32_t)t > (int32_t)*attr->rangeLower) {
802                                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
803                         }
804                 }
805         }
806
807         return WERR_OK;
808 }
809
810 static WERROR dsdb_syntax_DATA_BLOB_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
811                                                    const struct dsdb_attribute *attr,
812                                                    const struct drsuapi_DsReplicaAttribute *in,
813                                                    TALLOC_CTX *mem_ctx,
814                                                    struct ldb_message_element *out)
815 {
816         unsigned int i;
817
818         out->flags      = 0;
819         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
820         W_ERROR_HAVE_NO_MEMORY(out->name);
821
822         out->num_values = in->value_ctr.num_values;
823         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
824         W_ERROR_HAVE_NO_MEMORY(out->values);
825
826         for (i=0; i < out->num_values; i++) {
827                 if (in->value_ctr.values[i].blob == NULL) {
828                         return WERR_FOOBAR;
829                 }
830
831                 if (in->value_ctr.values[i].blob->length == 0) {
832                         return WERR_FOOBAR;
833                 }
834
835                 out->values[i] = data_blob_dup_talloc(out->values,
836                                                       in->value_ctr.values[i].blob);
837                 W_ERROR_HAVE_NO_MEMORY(out->values[i].data);
838         }
839
840         return WERR_OK;
841 }
842
843 static WERROR dsdb_syntax_DATA_BLOB_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
844                                                    const struct dsdb_attribute *attr,
845                                                    const struct ldb_message_element *in,
846                                                    TALLOC_CTX *mem_ctx,
847                                                    struct drsuapi_DsReplicaAttribute *out)
848 {
849         unsigned int i;
850         DATA_BLOB *blobs;
851
852         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
853                 return WERR_FOOBAR;
854         }
855
856         out->attid                      = dsdb_attribute_get_attid(attr,
857                                                                    ctx->is_schema_nc);
858         out->value_ctr.num_values       = in->num_values;
859         out->value_ctr.values           = talloc_array(mem_ctx,
860                                                        struct drsuapi_DsAttributeValue,
861                                                        in->num_values);
862         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
863
864         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
865         W_ERROR_HAVE_NO_MEMORY(blobs);
866
867         for (i=0; i < in->num_values; i++) {
868                 out->value_ctr.values[i].blob   = &blobs[i];
869
870                 blobs[i] = data_blob_dup_talloc(blobs, &in->values[i]);
871                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
872         }
873
874         return WERR_OK;
875 }
876
877 static WERROR dsdb_syntax_DATA_BLOB_validate_one_val(const struct dsdb_syntax_ctx *ctx,
878                                                      const struct dsdb_attribute *attr,
879                                                      const struct ldb_val *val)
880 {
881         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
882                 return WERR_FOOBAR;
883         }
884
885         if (attr->rangeLower) {
886                 if ((uint32_t)val->length < (uint32_t)*attr->rangeLower) {
887                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
888                 }
889         }
890
891         if (attr->rangeUpper) {
892                 if ((uint32_t)val->length > (uint32_t)*attr->rangeUpper) {
893                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
894                 }
895         }
896
897         return WERR_OK;
898 }
899
900 static WERROR dsdb_syntax_DATA_BLOB_validate_ldb(const struct dsdb_syntax_ctx *ctx,
901                                                  const struct dsdb_attribute *attr,
902                                                  const struct ldb_message_element *in)
903 {
904         unsigned int i;
905         WERROR status;
906
907         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
908                 return WERR_FOOBAR;
909         }
910
911         for (i=0; i < in->num_values; i++) {
912                 if (in->values[i].length == 0) {
913                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
914                 }
915
916                 status = dsdb_syntax_DATA_BLOB_validate_one_val(ctx,
917                                                                 attr,
918                                                                 &in->values[i]);
919                 if (!W_ERROR_IS_OK(status)) {
920                         return status;
921                 }
922         }
923
924         return WERR_OK;
925 }
926
927 static WERROR _dsdb_syntax_auto_OID_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
928                                                    const struct dsdb_attribute *attr,
929                                                    const struct drsuapi_DsReplicaAttribute *in,
930                                                    TALLOC_CTX *mem_ctx,
931                                                    struct ldb_message_element *out)
932 {
933         unsigned int i;
934
935         out->flags      = 0;
936         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
937         W_ERROR_HAVE_NO_MEMORY(out->name);
938
939         out->num_values = in->value_ctr.num_values;
940         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
941         W_ERROR_HAVE_NO_MEMORY(out->values);
942
943         for (i=0; i < out->num_values; i++) {
944                 uint32_t v;
945                 const struct dsdb_class *c;
946                 const struct dsdb_attribute *a;
947                 const char *str = NULL;
948
949                 if (in->value_ctr.values[i].blob == NULL) {
950                         return WERR_FOOBAR;
951                 }
952
953                 if (in->value_ctr.values[i].blob->length != 4) {
954                         return WERR_FOOBAR;
955                 }
956
957                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
958
959                 if ((c = dsdb_class_by_governsID_id(ctx->schema, v))) {
960                         str = talloc_strdup(out->values, c->lDAPDisplayName);
961                 } else if ((a = dsdb_attribute_by_attributeID_id(ctx->schema, v))) {
962                         str = talloc_strdup(out->values, a->lDAPDisplayName);
963                 } else {
964                         WERROR werr;
965                         SMB_ASSERT(ctx->pfm_remote);
966                         werr = dsdb_schema_pfm_oid_from_attid(ctx->pfm_remote, v,
967                                                               out->values, &str);
968                         W_ERROR_NOT_OK_RETURN(werr);
969                 }
970                 W_ERROR_HAVE_NO_MEMORY(str);
971
972                 /* the values need to be reversed */
973                 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
974         }
975
976         return WERR_OK;
977 }
978
979 static WERROR _dsdb_syntax_OID_obj_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
980                                                   const struct dsdb_attribute *attr,
981                                                   const struct drsuapi_DsReplicaAttribute *in,
982                                                   TALLOC_CTX *mem_ctx,
983                                                   struct ldb_message_element *out)
984 {
985         unsigned int i;
986
987         out->flags      = 0;
988         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
989         W_ERROR_HAVE_NO_MEMORY(out->name);
990
991         out->num_values = in->value_ctr.num_values;
992         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
993         W_ERROR_HAVE_NO_MEMORY(out->values);
994
995         for (i=0; i < out->num_values; i++) {
996                 uint32_t v;
997                 const struct dsdb_class *c;
998                 const char *str;
999
1000                 if (in->value_ctr.values[i].blob == NULL) {
1001                         return WERR_FOOBAR;
1002                 }
1003
1004                 if (in->value_ctr.values[i].blob->length != 4) {
1005                         return WERR_FOOBAR;
1006                 }
1007
1008                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
1009
1010                 /* convert remote ATTID to local ATTID */
1011                 if (!dsdb_syntax_attid_from_remote_attid(ctx, mem_ctx, v, &v)) {
1012                         DEBUG(1,(__location__ ": Failed to map remote ATTID to local ATTID!\n"));
1013                         return WERR_FOOBAR;
1014                 }
1015
1016                 c = dsdb_class_by_governsID_id(ctx->schema, v);
1017                 if (!c) {
1018                         DEBUG(1,(__location__ ": Unknown governsID 0x%08X\n", v));
1019                         return WERR_FOOBAR;
1020                 }
1021
1022                 str = talloc_strdup(out->values, c->lDAPDisplayName);
1023                 W_ERROR_HAVE_NO_MEMORY(str);
1024
1025                 /* the values need to be reversed */
1026                 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
1027         }
1028
1029         return WERR_OK;
1030 }
1031
1032 static WERROR _dsdb_syntax_OID_attr_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
1033                                                    const struct dsdb_attribute *attr,
1034                                                    const struct drsuapi_DsReplicaAttribute *in,
1035                                                    TALLOC_CTX *mem_ctx,
1036                                                    struct ldb_message_element *out)
1037 {
1038         unsigned int i;
1039
1040         out->flags      = 0;
1041         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1042         W_ERROR_HAVE_NO_MEMORY(out->name);
1043
1044         out->num_values = in->value_ctr.num_values;
1045         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1046         W_ERROR_HAVE_NO_MEMORY(out->values);
1047
1048         for (i=0; i < out->num_values; i++) {
1049                 uint32_t v;
1050                 const struct dsdb_attribute *a;
1051                 const char *str;
1052
1053                 if (in->value_ctr.values[i].blob == NULL) {
1054                         return WERR_FOOBAR;
1055                 }
1056
1057                 if (in->value_ctr.values[i].blob->length != 4) {
1058                         return WERR_FOOBAR;
1059                 }
1060
1061                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
1062
1063                 /* convert remote ATTID to local ATTID */
1064                 if (!dsdb_syntax_attid_from_remote_attid(ctx, mem_ctx, v, &v)) {
1065                         DEBUG(1,(__location__ ": Failed to map remote ATTID to local ATTID!\n"));
1066                         return WERR_FOOBAR;
1067                 }
1068
1069                 a = dsdb_attribute_by_attributeID_id(ctx->schema, v);
1070                 if (!a) {
1071                         DEBUG(1,(__location__ ": Unknown attributeID_id 0x%08X\n", v));
1072                         return WERR_FOOBAR;
1073                 }
1074
1075                 str = talloc_strdup(out->values, a->lDAPDisplayName);
1076                 W_ERROR_HAVE_NO_MEMORY(str);
1077
1078                 /* the values need to be reversed */
1079                 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
1080         }
1081
1082         return WERR_OK;
1083 }
1084
1085 static WERROR _dsdb_syntax_OID_oid_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
1086                                                   const struct dsdb_attribute *attr,
1087                                                   const struct drsuapi_DsReplicaAttribute *in,
1088                                                   TALLOC_CTX *mem_ctx,
1089                                                   struct ldb_message_element *out)
1090 {
1091         unsigned int i;
1092         const struct dsdb_schema_prefixmap *prefixmap;
1093
1094         if (ctx->pfm_remote != NULL) {
1095                 prefixmap = ctx->pfm_remote;
1096         } else {
1097                 prefixmap = ctx->schema->prefixmap;
1098         }
1099         SMB_ASSERT(prefixmap);
1100
1101         out->flags      = 0;
1102         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1103         W_ERROR_HAVE_NO_MEMORY(out->name);
1104
1105         out->num_values = in->value_ctr.num_values;
1106         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1107         W_ERROR_HAVE_NO_MEMORY(out->values);
1108
1109         for (i=0; i < out->num_values; i++) {
1110                 uint32_t attid;
1111                 WERROR status;
1112                 const char *oid;
1113
1114                 if (in->value_ctr.values[i].blob == NULL) {
1115                         return WERR_FOOBAR;
1116                 }
1117
1118                 if (in->value_ctr.values[i].blob->length != 4) {
1119                         return WERR_FOOBAR;
1120                 }
1121
1122                 attid = IVAL(in->value_ctr.values[i].blob->data, 0);
1123
1124                 status = dsdb_schema_pfm_oid_from_attid(prefixmap, attid,
1125                                                         out->values, &oid);
1126                 if (!W_ERROR_IS_OK(status)) {
1127                         DEBUG(0,(__location__ ": Error: Unknown ATTID 0x%08X\n",
1128                                  attid));
1129                         return status;
1130                 }
1131
1132                 out->values[i] = data_blob_string_const(oid);
1133         }
1134
1135         return WERR_OK;
1136 }
1137
1138 static WERROR _dsdb_syntax_auto_OID_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1139                                                    const struct dsdb_attribute *attr,
1140                                                    const struct ldb_message_element *in,
1141                                                    TALLOC_CTX *mem_ctx,
1142                                                    struct drsuapi_DsReplicaAttribute *out)
1143 {
1144         unsigned int i;
1145         DATA_BLOB *blobs;
1146
1147         out->attid= dsdb_attribute_get_attid(attr,
1148                                              ctx->is_schema_nc);
1149         out->value_ctr.num_values= in->num_values;
1150         out->value_ctr.values= talloc_array(mem_ctx,
1151                                             struct drsuapi_DsAttributeValue,
1152                                             in->num_values);
1153         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1154
1155         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1156         W_ERROR_HAVE_NO_MEMORY(blobs);
1157
1158         for (i=0; i < in->num_values; i++) {
1159                 const struct dsdb_class *obj_class;
1160                 const struct dsdb_attribute *obj_attr;
1161                 struct ldb_val *v;
1162
1163                 out->value_ctr.values[i].blob= &blobs[i];
1164
1165                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
1166                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1167
1168                 /* in DRS windows puts the classes in the opposite
1169                    order to the order used in ldap */
1170                 v = &in->values[(in->num_values-1)-i];
1171
1172                 if ((obj_class = dsdb_class_by_lDAPDisplayName_ldb_val(ctx->schema, v))) {
1173                         SIVAL(blobs[i].data, 0, obj_class->governsID_id);
1174                 } else if ((obj_attr = dsdb_attribute_by_lDAPDisplayName_ldb_val(ctx->schema, v))) {
1175                         SIVAL(blobs[i].data, 0, obj_attr->attributeID_id);
1176                 } else {
1177                         uint32_t attid;
1178                         WERROR werr;
1179                         werr = dsdb_schema_pfm_attid_from_oid(ctx->schema->prefixmap,
1180                                                               (const char *)v->data,
1181                                                               &attid);
1182                         W_ERROR_NOT_OK_RETURN(werr);
1183                         SIVAL(blobs[i].data, 0, attid);
1184                 }
1185
1186         }
1187
1188
1189         return WERR_OK;
1190 }
1191
1192 static WERROR _dsdb_syntax_OID_obj_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1193                                                   const struct dsdb_attribute *attr,
1194                                                   const struct ldb_message_element *in,
1195                                                   TALLOC_CTX *mem_ctx,
1196                                                   struct drsuapi_DsReplicaAttribute *out)
1197 {
1198         unsigned int i;
1199         DATA_BLOB *blobs;
1200
1201         out->attid= dsdb_attribute_get_attid(attr,
1202                                              ctx->is_schema_nc);
1203         out->value_ctr.num_values= in->num_values;
1204         out->value_ctr.values= talloc_array(mem_ctx,
1205                                             struct drsuapi_DsAttributeValue,
1206                                             in->num_values);
1207         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1208
1209         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1210         W_ERROR_HAVE_NO_MEMORY(blobs);
1211
1212         for (i=0; i < in->num_values; i++) {
1213                 const struct dsdb_class *obj_class;
1214
1215                 out->value_ctr.values[i].blob= &blobs[i];
1216
1217                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
1218                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1219
1220                 /* in DRS windows puts the classes in the opposite
1221                    order to the order used in ldap */
1222                 obj_class = dsdb_class_by_lDAPDisplayName(ctx->schema,
1223                                                           (const char *)in->values[(in->num_values-1)-i].data);
1224                 if (!obj_class) {
1225                         return WERR_FOOBAR;
1226                 }
1227                 SIVAL(blobs[i].data, 0, obj_class->governsID_id);
1228         }
1229
1230
1231         return WERR_OK;
1232 }
1233
1234 static WERROR _dsdb_syntax_OID_attr_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1235                                                    const struct dsdb_attribute *attr,
1236                                                    const struct ldb_message_element *in,
1237                                                    TALLOC_CTX *mem_ctx,
1238                                                    struct drsuapi_DsReplicaAttribute *out)
1239 {
1240         unsigned int i;
1241         DATA_BLOB *blobs;
1242
1243         out->attid= dsdb_attribute_get_attid(attr,
1244                                              ctx->is_schema_nc);
1245         out->value_ctr.num_values= in->num_values;
1246         out->value_ctr.values= talloc_array(mem_ctx,
1247                                             struct drsuapi_DsAttributeValue,
1248                                             in->num_values);
1249         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1250
1251         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1252         W_ERROR_HAVE_NO_MEMORY(blobs);
1253
1254         for (i=0; i < in->num_values; i++) {
1255                 const struct dsdb_attribute *obj_attr;
1256
1257                 out->value_ctr.values[i].blob= &blobs[i];
1258
1259                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
1260                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1261
1262                 obj_attr = dsdb_attribute_by_lDAPDisplayName(ctx->schema, (const char *)in->values[i].data);
1263                 if (!obj_attr) {
1264                         return WERR_FOOBAR;
1265                 }
1266                 SIVAL(blobs[i].data, 0, obj_attr->attributeID_id);
1267         }
1268
1269
1270         return WERR_OK;
1271 }
1272
1273 static WERROR _dsdb_syntax_OID_oid_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1274                                                   const struct dsdb_attribute *attr,
1275                                                   const struct ldb_message_element *in,
1276                                                   TALLOC_CTX *mem_ctx,
1277                                                   struct drsuapi_DsReplicaAttribute *out)
1278 {
1279         unsigned int i;
1280         DATA_BLOB *blobs;
1281
1282         out->attid= dsdb_attribute_get_attid(attr,
1283                                              ctx->is_schema_nc);
1284         out->value_ctr.num_values= in->num_values;
1285         out->value_ctr.values= talloc_array(mem_ctx,
1286                                             struct drsuapi_DsAttributeValue,
1287                                             in->num_values);
1288         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1289
1290         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1291         W_ERROR_HAVE_NO_MEMORY(blobs);
1292
1293         for (i=0; i < in->num_values; i++) {
1294                 uint32_t attid;
1295                 WERROR status;
1296
1297                 out->value_ctr.values[i].blob= &blobs[i];
1298
1299                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
1300                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1301
1302                 status = dsdb_schema_pfm_attid_from_oid(ctx->schema->prefixmap,
1303                                                         (const char *)in->values[i].data,
1304                                                         &attid);
1305                 W_ERROR_NOT_OK_RETURN(status);
1306
1307                 SIVAL(blobs[i].data, 0, attid);
1308         }
1309
1310         return WERR_OK;
1311 }
1312
1313 static WERROR dsdb_syntax_OID_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
1314                                              const struct dsdb_attribute *attr,
1315                                              const struct drsuapi_DsReplicaAttribute *in,
1316                                              TALLOC_CTX *mem_ctx,
1317                                              struct ldb_message_element *out)
1318 {
1319         WERROR werr;
1320
1321         switch (attr->attributeID_id) {
1322         case DRSUAPI_ATTID_objectClass:
1323         case DRSUAPI_ATTID_subClassOf:
1324         case DRSUAPI_ATTID_auxiliaryClass:
1325         case DRSUAPI_ATTID_systemAuxiliaryClass:
1326         case DRSUAPI_ATTID_systemPossSuperiors:
1327         case DRSUAPI_ATTID_possSuperiors:
1328                 werr = _dsdb_syntax_OID_obj_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
1329                 break;
1330         case DRSUAPI_ATTID_systemMustContain:
1331         case DRSUAPI_ATTID_systemMayContain:
1332         case DRSUAPI_ATTID_mustContain:
1333         case DRSUAPI_ATTID_rDNAttId:
1334         case DRSUAPI_ATTID_transportAddressAttribute:
1335         case DRSUAPI_ATTID_mayContain:
1336                 werr = _dsdb_syntax_OID_attr_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
1337                 break;
1338         case DRSUAPI_ATTID_governsID:
1339         case DRSUAPI_ATTID_attributeID:
1340         case DRSUAPI_ATTID_attributeSyntax:
1341                 werr = _dsdb_syntax_OID_oid_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
1342                 break;
1343         default:
1344                 DEBUG(0,(__location__ ": Unknown handling for attributeID_id for %s\n",
1345                          attr->lDAPDisplayName));
1346                 return _dsdb_syntax_auto_OID_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
1347         }
1348
1349         /* When we are doing the vampire of a schema, we don't want
1350          * the inability to reference an OID to get in the way.
1351          * Otherwise, we won't get the new schema with which to
1352          * understand this */
1353         if (!W_ERROR_IS_OK(werr) && ctx->schema->relax_OID_conversions) {
1354                 return _dsdb_syntax_OID_oid_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
1355         }
1356         return werr;
1357 }
1358
1359 static WERROR dsdb_syntax_OID_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1360                                              const struct dsdb_attribute *attr,
1361                                              const struct ldb_message_element *in,
1362                                              TALLOC_CTX *mem_ctx,
1363                                              struct drsuapi_DsReplicaAttribute *out)
1364 {
1365         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1366                 return WERR_FOOBAR;
1367         }
1368
1369         switch (attr->attributeID_id) {
1370         case DRSUAPI_ATTID_objectClass:
1371         case DRSUAPI_ATTID_subClassOf:
1372         case DRSUAPI_ATTID_auxiliaryClass:
1373         case DRSUAPI_ATTID_systemAuxiliaryClass:
1374         case DRSUAPI_ATTID_systemPossSuperiors:
1375         case DRSUAPI_ATTID_possSuperiors:
1376                 return _dsdb_syntax_OID_obj_ldb_to_drsuapi(ctx, attr, in, mem_ctx, out);
1377         case DRSUAPI_ATTID_systemMustContain:
1378         case DRSUAPI_ATTID_systemMayContain:
1379         case DRSUAPI_ATTID_mustContain:
1380         case DRSUAPI_ATTID_rDNAttId:
1381         case DRSUAPI_ATTID_transportAddressAttribute:
1382         case DRSUAPI_ATTID_mayContain:
1383                 return _dsdb_syntax_OID_attr_ldb_to_drsuapi(ctx, attr, in, mem_ctx, out);
1384         case DRSUAPI_ATTID_governsID:
1385         case DRSUAPI_ATTID_attributeID:
1386         case DRSUAPI_ATTID_attributeSyntax:
1387                 return _dsdb_syntax_OID_oid_ldb_to_drsuapi(ctx, attr, in, mem_ctx, out);
1388         }
1389
1390         DEBUG(0,(__location__ ": Unknown handling for attributeID_id for %s\n",
1391                  attr->lDAPDisplayName));
1392
1393         return _dsdb_syntax_auto_OID_ldb_to_drsuapi(ctx, attr, in, mem_ctx, out);
1394 }
1395
1396 static WERROR _dsdb_syntax_OID_validate_numericoid(const struct dsdb_syntax_ctx *ctx,
1397                                                    const struct dsdb_attribute *attr,
1398                                                    const struct ldb_message_element *in)
1399 {
1400         unsigned int i;
1401         TALLOC_CTX *tmp_ctx;
1402
1403         tmp_ctx = talloc_new(ctx->ldb);
1404         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1405
1406         for (i=0; i < in->num_values; i++) {
1407                 DATA_BLOB blob;
1408                 char *oid_out;
1409                 const char *oid = (const char*)in->values[i].data;
1410
1411                 if (in->values[i].length == 0) {
1412                         talloc_free(tmp_ctx);
1413                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1414                 }
1415
1416                 if (!ber_write_OID_String(tmp_ctx, &blob, oid)) {
1417                         DEBUG(0,("ber_write_OID_String() failed for %s\n", oid));
1418                         talloc_free(tmp_ctx);
1419                         return WERR_INVALID_PARAMETER;
1420                 }
1421
1422                 if (!ber_read_OID_String(tmp_ctx, blob, &oid_out)) {
1423                         DEBUG(0,("ber_read_OID_String() failed for %s\n",
1424                                  hex_encode_talloc(tmp_ctx, blob.data, blob.length)));
1425                         talloc_free(tmp_ctx);
1426                         return WERR_INVALID_PARAMETER;
1427                 }
1428
1429                 if (strcmp(oid, oid_out) != 0) {
1430                         talloc_free(tmp_ctx);
1431                         return WERR_INVALID_PARAMETER;
1432                 }
1433         }
1434
1435         talloc_free(tmp_ctx);
1436         return WERR_OK;
1437 }
1438
1439 static WERROR dsdb_syntax_OID_validate_ldb(const struct dsdb_syntax_ctx *ctx,
1440                                            const struct dsdb_attribute *attr,
1441                                            const struct ldb_message_element *in)
1442 {
1443         WERROR status;
1444         struct drsuapi_DsReplicaAttribute drs_tmp;
1445         struct ldb_message_element ldb_tmp;
1446         TALLOC_CTX *tmp_ctx;
1447
1448         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1449                 return WERR_FOOBAR;
1450         }
1451
1452         switch (attr->attributeID_id) {
1453         case DRSUAPI_ATTID_governsID:
1454         case DRSUAPI_ATTID_attributeID:
1455         case DRSUAPI_ATTID_attributeSyntax:
1456                 return _dsdb_syntax_OID_validate_numericoid(ctx, attr, in);
1457         }
1458
1459         /*
1460          * TODO: optimize and verify this code
1461          */
1462
1463         tmp_ctx = talloc_new(ctx->ldb);
1464         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1465
1466         status = dsdb_syntax_OID_ldb_to_drsuapi(ctx,
1467                                                 attr,
1468                                                 in,
1469                                                 tmp_ctx,
1470                                                 &drs_tmp);
1471         if (!W_ERROR_IS_OK(status)) {
1472                 talloc_free(tmp_ctx);
1473                 return status;
1474         }
1475
1476         status = dsdb_syntax_OID_drsuapi_to_ldb(ctx,
1477                                                 attr,
1478                                                 &drs_tmp,
1479                                                 tmp_ctx,
1480                                                 &ldb_tmp);
1481         if (!W_ERROR_IS_OK(status)) {
1482                 talloc_free(tmp_ctx);
1483                 return status;
1484         }
1485
1486         talloc_free(tmp_ctx);
1487         return WERR_OK;
1488 }
1489
1490 static WERROR dsdb_syntax_UNICODE_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
1491                                                  const struct dsdb_attribute *attr,
1492                                                  const struct drsuapi_DsReplicaAttribute *in,
1493                                                  TALLOC_CTX *mem_ctx,
1494                                                  struct ldb_message_element *out)
1495 {
1496         unsigned int i;
1497
1498         out->flags      = 0;
1499         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1500         W_ERROR_HAVE_NO_MEMORY(out->name);
1501
1502         out->num_values = in->value_ctr.num_values;
1503         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1504         W_ERROR_HAVE_NO_MEMORY(out->values);
1505
1506         for (i=0; i < out->num_values; i++) {
1507                 size_t converted_size = 0;
1508                 char *str;
1509
1510                 if (in->value_ctr.values[i].blob == NULL) {
1511                         return WERR_FOOBAR;
1512                 }
1513
1514                 if (in->value_ctr.values[i].blob->length == 0) {
1515                         return WERR_FOOBAR;
1516                 }
1517
1518                 if (!convert_string_talloc(out->values,
1519                                            CH_UTF16, CH_UNIX,
1520                                            in->value_ctr.values[i].blob->data,
1521                                            in->value_ctr.values[i].blob->length,
1522                                            (void **)&str, &converted_size)) {
1523                         return WERR_FOOBAR;
1524                 }
1525
1526                 out->values[i] = data_blob_string_const(str);
1527         }
1528
1529         return WERR_OK;
1530 }
1531
1532 static WERROR dsdb_syntax_UNICODE_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1533                                                  const struct dsdb_attribute *attr,
1534                                                  const struct ldb_message_element *in,
1535                                                  TALLOC_CTX *mem_ctx,
1536                                                  struct drsuapi_DsReplicaAttribute *out)
1537 {
1538         unsigned int i;
1539         DATA_BLOB *blobs;
1540
1541         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1542                 return WERR_FOOBAR;
1543         }
1544
1545         out->attid                      = dsdb_attribute_get_attid(attr,
1546                                                                    ctx->is_schema_nc);
1547         out->value_ctr.num_values       = in->num_values;
1548         out->value_ctr.values           = talloc_array(mem_ctx,
1549                                                        struct drsuapi_DsAttributeValue,
1550                                                        in->num_values);
1551         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1552
1553         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1554         W_ERROR_HAVE_NO_MEMORY(blobs);
1555
1556         for (i=0; i < in->num_values; i++) {
1557                 out->value_ctr.values[i].blob   = &blobs[i];
1558
1559                 if (!convert_string_talloc(blobs,
1560                                            CH_UNIX, CH_UTF16,
1561                                            in->values[i].data, in->values[i].length,
1562                                            (void **)&blobs[i].data, &blobs[i].length)) {
1563                         return WERR_FOOBAR;
1564                 }
1565         }
1566
1567         return WERR_OK;
1568 }
1569
1570 static WERROR dsdb_syntax_UNICODE_validate_one_val(const struct dsdb_syntax_ctx *ctx,
1571                                                    const struct dsdb_attribute *attr,
1572                                                    const struct ldb_val *val)
1573 {
1574         void *dst = NULL;
1575         size_t size;
1576         bool ok;
1577
1578         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1579                 return WERR_FOOBAR;
1580         }
1581
1582         ok = convert_string_talloc(ctx->ldb,
1583                                    CH_UNIX, CH_UTF16,
1584                                    val->data,
1585                                    val->length,
1586                                    (void **)&dst,
1587                                    &size);
1588         TALLOC_FREE(dst);
1589         if (!ok) {
1590                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1591         }
1592
1593         if (attr->rangeLower) {
1594                 if ((size/2) < *attr->rangeLower) {
1595                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1596                 }
1597         }
1598
1599         if (attr->rangeUpper) {
1600                 if ((size/2) > *attr->rangeUpper) {
1601                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1602                 }
1603         }
1604
1605         return WERR_OK;
1606 }
1607
1608 static WERROR dsdb_syntax_UNICODE_validate_ldb(const struct dsdb_syntax_ctx *ctx,
1609                                                const struct dsdb_attribute *attr,
1610                                                const struct ldb_message_element *in)
1611 {
1612         WERROR status;
1613         unsigned int i;
1614
1615         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1616                 return WERR_FOOBAR;
1617         }
1618
1619         for (i=0; i < in->num_values; i++) {
1620                 if (in->values[i].length == 0) {
1621                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1622                 }
1623
1624                 status = dsdb_syntax_UNICODE_validate_one_val(ctx,
1625                                                               attr,
1626                                                               &in->values[i]);
1627                 if (!W_ERROR_IS_OK(status)) {
1628                         return status;
1629                 }
1630         }
1631
1632         return WERR_OK;
1633 }
1634
1635 static WERROR dsdb_syntax_one_DN_drsuapi_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
1636                                                 const struct dsdb_syntax *syntax,
1637                                                 const DATA_BLOB *in, DATA_BLOB *out)
1638 {
1639         struct drsuapi_DsReplicaObjectIdentifier3 id3;
1640         enum ndr_err_code ndr_err;
1641         DATA_BLOB guid_blob;
1642         struct ldb_dn *dn;
1643         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1644         int ret;
1645         NTSTATUS status;
1646
1647         if (!tmp_ctx) {
1648                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1649         }
1650
1651         if (in == NULL) {
1652                 talloc_free(tmp_ctx);
1653                 return WERR_FOOBAR;
1654         }
1655
1656         if (in->length == 0) {
1657                 talloc_free(tmp_ctx);
1658                 return WERR_FOOBAR;
1659         }
1660
1661
1662         /* windows sometimes sends an extra two pad bytes here */
1663         ndr_err = ndr_pull_struct_blob(in,
1664                                        tmp_ctx, &id3,
1665                                        (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3);
1666         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1667                 status = ndr_map_error2ntstatus(ndr_err);
1668                 talloc_free(tmp_ctx);
1669                 return ntstatus_to_werror(status);
1670         }
1671
1672         dn = ldb_dn_new(tmp_ctx, ldb, id3.dn);
1673         if (!dn) {
1674                 talloc_free(tmp_ctx);
1675                 /* If this fails, it must be out of memory, as it does not do much parsing */
1676                 W_ERROR_HAVE_NO_MEMORY(dn);
1677         }
1678
1679         if (!GUID_all_zero(&id3.guid)) {
1680                 status = GUID_to_ndr_blob(&id3.guid, tmp_ctx, &guid_blob);
1681                 if (!NT_STATUS_IS_OK(status)) {
1682                         talloc_free(tmp_ctx);
1683                         return ntstatus_to_werror(status);
1684                 }
1685
1686                 ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
1687                 if (ret != LDB_SUCCESS) {
1688                         talloc_free(tmp_ctx);
1689                         return WERR_FOOBAR;
1690                 }
1691                 talloc_free(guid_blob.data);
1692         }
1693
1694         if (id3.__ndr_size_sid) {
1695                 DATA_BLOB sid_blob;
1696                 ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, &id3.sid,
1697                                                (ndr_push_flags_fn_t)ndr_push_dom_sid);
1698                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1699                         status = ndr_map_error2ntstatus(ndr_err);
1700                         talloc_free(tmp_ctx);
1701                         return ntstatus_to_werror(status);
1702                 }
1703
1704                 ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
1705                 if (ret != LDB_SUCCESS) {
1706                         talloc_free(tmp_ctx);
1707                         return WERR_FOOBAR;
1708                 }
1709         }
1710
1711         *out = data_blob_string_const(ldb_dn_get_extended_linearized(mem_ctx, dn, 1));
1712         talloc_free(tmp_ctx);
1713         return WERR_OK;
1714 }
1715
1716 static WERROR dsdb_syntax_DN_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
1717                                             const struct dsdb_attribute *attr,
1718                                             const struct drsuapi_DsReplicaAttribute *in,
1719                                             TALLOC_CTX *mem_ctx,
1720                                             struct ldb_message_element *out)
1721 {
1722         unsigned int i;
1723
1724         out->flags      = 0;
1725         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1726         W_ERROR_HAVE_NO_MEMORY(out->name);
1727
1728         out->num_values = in->value_ctr.num_values;
1729         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1730         W_ERROR_HAVE_NO_MEMORY(out->values);
1731
1732         for (i=0; i < out->num_values; i++) {
1733                 WERROR status = dsdb_syntax_one_DN_drsuapi_to_ldb(out->values, ctx->ldb, attr->syntax,
1734                                                                   in->value_ctr.values[i].blob,
1735                                                                   &out->values[i]);
1736                 if (!W_ERROR_IS_OK(status)) {
1737                         return status;
1738                 }
1739
1740         }
1741
1742         return WERR_OK;
1743 }
1744
1745 static WERROR dsdb_syntax_DN_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
1746                                             const struct dsdb_attribute *attr,
1747                                             const struct ldb_message_element *in,
1748                                             TALLOC_CTX *mem_ctx,
1749                                             struct drsuapi_DsReplicaAttribute *out)
1750 {
1751         unsigned int i;
1752         DATA_BLOB *blobs;
1753
1754         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1755                 return WERR_FOOBAR;
1756         }
1757
1758         out->attid                      = dsdb_attribute_get_attid(attr,
1759                                                                    ctx->is_schema_nc);
1760         out->value_ctr.num_values       = in->num_values;
1761         out->value_ctr.values           = talloc_array(mem_ctx,
1762                                                        struct drsuapi_DsAttributeValue,
1763                                                        in->num_values);
1764         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1765
1766         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1767         W_ERROR_HAVE_NO_MEMORY(blobs);
1768
1769         for (i=0; i < in->num_values; i++) {
1770                 struct drsuapi_DsReplicaObjectIdentifier3 id3;
1771                 enum ndr_err_code ndr_err;
1772                 struct ldb_dn *dn;
1773                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1774                 NTSTATUS status;
1775
1776                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1777
1778                 out->value_ctr.values[i].blob   = &blobs[i];
1779
1780                 dn = ldb_dn_from_ldb_val(tmp_ctx, ctx->ldb, &in->values[i]);
1781
1782                 W_ERROR_HAVE_NO_MEMORY(dn);
1783
1784                 ZERO_STRUCT(id3);
1785
1786                 status = dsdb_get_extended_dn_guid(dn, &id3.guid, "GUID");
1787                 if (!NT_STATUS_IS_OK(status) &&
1788                     !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1789                         talloc_free(tmp_ctx);
1790                         return ntstatus_to_werror(status);
1791                 }
1792
1793                 status = dsdb_get_extended_dn_sid(dn, &id3.sid, "SID");
1794                 if (!NT_STATUS_IS_OK(status) &&
1795                     !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1796                         talloc_free(tmp_ctx);
1797                         return ntstatus_to_werror(status);
1798                 }
1799
1800                 id3.dn = ldb_dn_get_linearized(dn);
1801
1802                 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
1803                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1804                         status = ndr_map_error2ntstatus(ndr_err);
1805                         talloc_free(tmp_ctx);
1806                         return ntstatus_to_werror(status);
1807                 }
1808                 talloc_free(tmp_ctx);
1809         }
1810
1811         return WERR_OK;
1812 }
1813
1814 static WERROR dsdb_syntax_DN_validate_one_val(const struct dsdb_syntax_ctx *ctx,
1815                                               const struct dsdb_attribute *attr,
1816                                               const struct ldb_val *val,
1817                                               TALLOC_CTX *mem_ctx,
1818                                               struct dsdb_dn **_dsdb_dn)
1819 {
1820         static const char * const extended_list[] = { "GUID", "SID", NULL };
1821         enum ndr_err_code ndr_err;
1822         struct GUID guid;
1823         struct dom_sid sid;
1824         const DATA_BLOB *sid_blob;
1825         struct dsdb_dn *dsdb_dn;
1826         struct ldb_dn *dn;
1827         char *dn_str;
1828         struct ldb_dn *dn2;
1829         char *dn2_str;
1830         int num_components;
1831         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1832         NTSTATUS status;
1833
1834         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1835
1836         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1837                 return WERR_FOOBAR;
1838         }
1839
1840         dsdb_dn = dsdb_dn_parse(tmp_ctx, ctx->ldb, val,
1841                                 attr->syntax->ldap_oid);
1842         if (!dsdb_dn) {
1843                 talloc_free(tmp_ctx);
1844                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1845         }
1846         dn = dsdb_dn->dn;
1847
1848         dn2 = ldb_dn_copy(tmp_ctx, dn);
1849         if (dn == NULL) {
1850                 talloc_free(tmp_ctx);
1851                 return WERR_NOMEM;
1852         }
1853
1854         num_components = ldb_dn_get_comp_num(dn);
1855
1856         status = dsdb_get_extended_dn_guid(dn, &guid, "GUID");
1857         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1858                 num_components++;
1859         } else if (!NT_STATUS_IS_OK(status)) {
1860                 talloc_free(tmp_ctx);
1861                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1862         }
1863
1864         sid_blob = ldb_dn_get_extended_component(dn, "SID");
1865         if (sid_blob) {
1866                 num_components++;
1867                 ndr_err = ndr_pull_struct_blob_all(sid_blob,
1868                                                    tmp_ctx,
1869                                                    &sid,
1870                                                    (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1871                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1872                         talloc_free(tmp_ctx);
1873                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1874                 }
1875         }
1876
1877         /* Do not allow links to the RootDSE */
1878         if (num_components == 0) {
1879                 talloc_free(tmp_ctx);
1880                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1881         }
1882
1883         /*
1884          * We need to check that only "GUID" and "SID" are
1885          * specified as extended components, we do that
1886          * by comparing the dn's after removing all components
1887          * from one dn and only the allowed subset from the other
1888          * one.
1889          */
1890         ldb_dn_extended_filter(dn, extended_list);
1891
1892         dn_str = ldb_dn_get_extended_linearized(tmp_ctx, dn, 0);
1893         if (dn_str == NULL) {
1894                 talloc_free(tmp_ctx);
1895                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1896         }
1897         dn2_str = ldb_dn_get_extended_linearized(tmp_ctx, dn2, 0);
1898         if (dn2_str == NULL) {
1899                 talloc_free(tmp_ctx);
1900                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1901         }
1902
1903         if (strcmp(dn_str, dn2_str) != 0) {
1904                 talloc_free(tmp_ctx);
1905                 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1906         }
1907
1908         *_dsdb_dn = talloc_move(mem_ctx, &dsdb_dn);
1909         talloc_free(tmp_ctx);
1910         return WERR_OK;
1911 }
1912
1913 static WERROR dsdb_syntax_DN_validate_ldb(const struct dsdb_syntax_ctx *ctx,
1914                                           const struct dsdb_attribute *attr,
1915                                           const struct ldb_message_element *in)
1916 {
1917         unsigned int i;
1918
1919         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
1920                 return WERR_FOOBAR;
1921         }
1922
1923         for (i=0; i < in->num_values; i++) {
1924                 WERROR status;
1925                 struct dsdb_dn *dsdb_dn;
1926                 TALLOC_CTX *tmp_ctx = talloc_new(ctx->ldb);
1927                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1928
1929                 status = dsdb_syntax_DN_validate_one_val(ctx,
1930                                                          attr,
1931                                                          &in->values[i],
1932                                                          tmp_ctx, &dsdb_dn);
1933                 if (!W_ERROR_IS_OK(status)) {
1934                         talloc_free(tmp_ctx);
1935                         return status;
1936                 }
1937
1938                 if (dsdb_dn->dn_format != DSDB_NORMAL_DN) {
1939                         talloc_free(tmp_ctx);
1940                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1941                 }
1942
1943                 talloc_free(tmp_ctx);
1944         }
1945
1946         return WERR_OK;
1947 }
1948
1949 static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
1950                                                    const struct dsdb_attribute *attr,
1951                                                    const struct drsuapi_DsReplicaAttribute *in,
1952                                                    TALLOC_CTX *mem_ctx,
1953                                                    struct ldb_message_element *out)
1954 {
1955         unsigned int i;
1956         int ret;
1957
1958         out->flags      = 0;
1959         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1960         W_ERROR_HAVE_NO_MEMORY(out->name);
1961
1962         out->num_values = in->value_ctr.num_values;
1963         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1964         W_ERROR_HAVE_NO_MEMORY(out->values);
1965
1966         for (i=0; i < out->num_values; i++) {
1967                 struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
1968                 enum ndr_err_code ndr_err;
1969                 DATA_BLOB guid_blob;
1970                 struct ldb_dn *dn;
1971                 struct dsdb_dn *dsdb_dn;
1972                 NTSTATUS status;
1973                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1974                 if (!tmp_ctx) {
1975                         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1976                 }
1977
1978                 if (in->value_ctr.values[i].blob == NULL) {
1979                         talloc_free(tmp_ctx);
1980                         return WERR_FOOBAR;
1981                 }
1982
1983                 if (in->value_ctr.values[i].blob->length == 0) {
1984                         talloc_free(tmp_ctx);
1985                         return WERR_FOOBAR;
1986                 }
1987
1988
1989                 /* windows sometimes sends an extra two pad bytes here */
1990                 ndr_err = ndr_pull_struct_blob(in->value_ctr.values[i].blob,
1991                                                tmp_ctx, &id3,
1992                                                (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3Binary);
1993                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1994                         status = ndr_map_error2ntstatus(ndr_err);
1995                         talloc_free(tmp_ctx);
1996                         return ntstatus_to_werror(status);
1997                 }
1998
1999                 dn = ldb_dn_new(tmp_ctx, ctx->ldb, id3.dn);
2000                 if (!dn) {
2001                         talloc_free(tmp_ctx);
2002                         /* If this fails, it must be out of memory, as it does not do much parsing */
2003                         W_ERROR_HAVE_NO_MEMORY(dn);
2004                 }
2005
2006                 if (!GUID_all_zero(&id3.guid)) {
2007                         status = GUID_to_ndr_blob(&id3.guid, tmp_ctx, &guid_blob);
2008                         if (!NT_STATUS_IS_OK(status)) {
2009                                 talloc_free(tmp_ctx);
2010                                 return ntstatus_to_werror(status);
2011                         }
2012
2013                         ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
2014                         if (ret != LDB_SUCCESS) {
2015                                 talloc_free(tmp_ctx);
2016                                 return WERR_FOOBAR;
2017                         }
2018                         talloc_free(guid_blob.data);
2019                 }
2020
2021                 if (id3.__ndr_size_sid) {
2022                         DATA_BLOB sid_blob;
2023                         ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, &id3.sid,
2024                                                        (ndr_push_flags_fn_t)ndr_push_dom_sid);
2025                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2026                                 status = ndr_map_error2ntstatus(ndr_err);
2027                                 talloc_free(tmp_ctx);
2028                                 return ntstatus_to_werror(status);
2029                         }
2030
2031                         ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
2032                         if (ret != LDB_SUCCESS) {
2033                                 talloc_free(tmp_ctx);
2034                                 return WERR_FOOBAR;
2035                         }
2036                 }
2037
2038                 /* set binary stuff */
2039                 dsdb_dn = dsdb_dn_construct(tmp_ctx, dn, id3.binary, attr->syntax->ldap_oid);
2040                 if (!dsdb_dn) {
2041                         /* If this fails, it must be out of memory, we know the ldap_oid is valid */
2042                         talloc_free(tmp_ctx);
2043                         W_ERROR_HAVE_NO_MEMORY(dsdb_dn);
2044                 }
2045                 out->values[i] = data_blob_string_const(dsdb_dn_get_extended_linearized(out->values, dsdb_dn, 1));
2046                 talloc_free(tmp_ctx);
2047         }
2048
2049         return WERR_OK;
2050 }
2051
2052 static WERROR dsdb_syntax_DN_BINARY_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
2053                                                    const struct dsdb_attribute *attr,
2054                                                    const struct ldb_message_element *in,
2055                                                    TALLOC_CTX *mem_ctx,
2056                                                    struct drsuapi_DsReplicaAttribute *out)
2057 {
2058         unsigned int i;
2059         DATA_BLOB *blobs;
2060
2061         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
2062                 return WERR_FOOBAR;
2063         }
2064
2065         out->attid                      = dsdb_attribute_get_attid(attr,
2066                                                                    ctx->is_schema_nc);
2067         out->value_ctr.num_values       = in->num_values;
2068         out->value_ctr.values           = talloc_array(mem_ctx,
2069                                                        struct drsuapi_DsAttributeValue,
2070                                                        in->num_values);
2071         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
2072
2073         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
2074         W_ERROR_HAVE_NO_MEMORY(blobs);
2075
2076         for (i=0; i < in->num_values; i++) {
2077                 struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
2078                 enum ndr_err_code ndr_err;
2079                 const DATA_BLOB *sid_blob;
2080                 struct dsdb_dn *dsdb_dn;
2081                 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
2082                 NTSTATUS status;
2083
2084                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
2085
2086                 out->value_ctr.values[i].blob   = &blobs[i];
2087
2088                 dsdb_dn = dsdb_dn_parse(tmp_ctx, ctx->ldb, &in->values[i], attr->syntax->ldap_oid);
2089
2090                 if (!dsdb_dn) {
2091                         talloc_free(tmp_ctx);
2092                         return ntstatus_to_werror(NT_STATUS_INVALID_PARAMETER);
2093                 }
2094
2095                 ZERO_STRUCT(id3);
2096
2097                 status = dsdb_get_extended_dn_guid(dsdb_dn->dn, &id3.guid, "GUID");
2098                 if (!NT_STATUS_IS_OK(status) &&
2099                     !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2100                         talloc_free(tmp_ctx);
2101                         return ntstatus_to_werror(status);
2102                 }
2103
2104                 sid_blob = ldb_dn_get_extended_component(dsdb_dn->dn, "SID");
2105                 if (sid_blob) {
2106
2107                         ndr_err = ndr_pull_struct_blob_all(sid_blob,
2108                                                            tmp_ctx, &id3.sid,
2109                                                            (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
2110                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2111                                 status = ndr_map_error2ntstatus(ndr_err);
2112                                 talloc_free(tmp_ctx);
2113                                 return ntstatus_to_werror(status);
2114                         }
2115                 }
2116
2117                 id3.dn = ldb_dn_get_linearized(dsdb_dn->dn);
2118
2119                 /* get binary stuff */
2120                 id3.binary = dsdb_dn->extra_part;
2121
2122                 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3Binary);
2123                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2124                         status = ndr_map_error2ntstatus(ndr_err);
2125                         talloc_free(tmp_ctx);
2126                         return ntstatus_to_werror(status);
2127                 }
2128                 talloc_free(tmp_ctx);
2129         }
2130
2131         return WERR_OK;
2132 }
2133
2134 static WERROR dsdb_syntax_DN_BINARY_validate_ldb(const struct dsdb_syntax_ctx *ctx,
2135                                                  const struct dsdb_attribute *attr,
2136                                                  const struct ldb_message_element *in)
2137 {
2138         unsigned int i;
2139
2140         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
2141                 return WERR_FOOBAR;
2142         }
2143
2144         for (i=0; i < in->num_values; i++) {
2145                 WERROR status;
2146                 struct dsdb_dn *dsdb_dn;
2147                 TALLOC_CTX *tmp_ctx = talloc_new(ctx->ldb);
2148                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
2149
2150                 status = dsdb_syntax_DN_validate_one_val(ctx,
2151                                                          attr,
2152                                                          &in->values[i],
2153                                                          tmp_ctx, &dsdb_dn);
2154                 if (!W_ERROR_IS_OK(status)) {
2155                         talloc_free(tmp_ctx);
2156                         return status;
2157                 }
2158
2159                 if (dsdb_dn->dn_format != DSDB_BINARY_DN) {
2160                         talloc_free(tmp_ctx);
2161                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
2162                 }
2163
2164                 status = dsdb_syntax_DATA_BLOB_validate_one_val(ctx,
2165                                                                 attr,
2166                                                                 &dsdb_dn->extra_part);
2167                 if (!W_ERROR_IS_OK(status)) {
2168                         talloc_free(tmp_ctx);
2169                         return status;
2170                 }
2171
2172                 talloc_free(tmp_ctx);
2173         }
2174
2175         return WERR_OK;
2176 }
2177
2178 static WERROR dsdb_syntax_DN_STRING_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
2179                                                    const struct dsdb_attribute *attr,
2180                                                    const struct drsuapi_DsReplicaAttribute *in,
2181                                                    TALLOC_CTX *mem_ctx,
2182                                                    struct ldb_message_element *out)
2183 {
2184         return dsdb_syntax_DN_BINARY_drsuapi_to_ldb(ctx,
2185                                                     attr,
2186                                                     in,
2187                                                     mem_ctx,
2188                                                     out);
2189 }
2190
2191 static WERROR dsdb_syntax_DN_STRING_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
2192                                                    const struct dsdb_attribute *attr,
2193                                                    const struct ldb_message_element *in,
2194                                                    TALLOC_CTX *mem_ctx,
2195                                                    struct drsuapi_DsReplicaAttribute *out)
2196 {
2197         return dsdb_syntax_DN_BINARY_ldb_to_drsuapi(ctx,
2198                                                     attr,
2199                                                     in,
2200                                                     mem_ctx,
2201                                                     out);
2202 }
2203
2204 static WERROR dsdb_syntax_DN_STRING_validate_ldb(const struct dsdb_syntax_ctx *ctx,
2205                                                  const struct dsdb_attribute *attr,
2206                                                  const struct ldb_message_element *in)
2207 {
2208         unsigned int i;
2209
2210         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
2211                 return WERR_FOOBAR;
2212         }
2213
2214         for (i=0; i < in->num_values; i++) {
2215                 WERROR status;
2216                 struct dsdb_dn *dsdb_dn;
2217                 TALLOC_CTX *tmp_ctx = talloc_new(ctx->ldb);
2218                 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
2219
2220                 status = dsdb_syntax_DN_validate_one_val(ctx,
2221                                                          attr,
2222                                                          &in->values[i],
2223                                                          tmp_ctx, &dsdb_dn);
2224                 if (!W_ERROR_IS_OK(status)) {
2225                         talloc_free(tmp_ctx);
2226                         return status;
2227                 }
2228
2229                 if (dsdb_dn->dn_format != DSDB_STRING_DN) {
2230                         talloc_free(tmp_ctx);
2231                         return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
2232                 }
2233
2234                 status = dsdb_syntax_UNICODE_validate_one_val(ctx,
2235                                                               attr,
2236                                                               &dsdb_dn->extra_part);
2237                 if (!W_ERROR_IS_OK(status)) {
2238                         talloc_free(tmp_ctx);
2239                         return status;
2240                 }
2241
2242                 talloc_free(tmp_ctx);
2243         }
2244
2245         return WERR_OK;
2246 }
2247
2248 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
2249                                                               const struct dsdb_attribute *attr,
2250                                                               const struct drsuapi_DsReplicaAttribute *in,
2251                                                               TALLOC_CTX *mem_ctx,
2252                                                               struct ldb_message_element *out)
2253 {
2254         unsigned int i;
2255
2256         out->flags      = 0;
2257         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
2258         W_ERROR_HAVE_NO_MEMORY(out->name);
2259
2260         out->num_values = in->value_ctr.num_values;
2261         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
2262         W_ERROR_HAVE_NO_MEMORY(out->values);
2263
2264         for (i=0; i < out->num_values; i++) {
2265                 size_t len;
2266                 size_t converted_size = 0;
2267                 char *str;
2268
2269                 if (in->value_ctr.values[i].blob == NULL) {
2270                         return WERR_FOOBAR;
2271                 }
2272
2273                 if (in->value_ctr.values[i].blob->length < 4) {
2274                         return WERR_FOOBAR;
2275                 }
2276
2277                 len = IVAL(in->value_ctr.values[i].blob->data, 0);
2278
2279                 if (len != in->value_ctr.values[i].blob->length) {
2280                         return WERR_FOOBAR;
2281                 }
2282
2283                 if (!convert_string_talloc(out->values, CH_UTF16, CH_UNIX,
2284                                            in->value_ctr.values[i].blob->data+4,
2285                                            in->value_ctr.values[i].blob->length-4,
2286                                            (void **)&str, &converted_size)) {
2287                         return WERR_FOOBAR;
2288                 }
2289
2290                 out->values[i] = data_blob_string_const(str);
2291         }
2292
2293         return WERR_OK;
2294 }
2295
2296 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
2297                                                               const struct dsdb_attribute *attr,
2298                                                               const struct ldb_message_element *in,
2299                                                               TALLOC_CTX *mem_ctx,
2300                                                               struct drsuapi_DsReplicaAttribute *out)
2301 {
2302         unsigned int i;
2303         DATA_BLOB *blobs;
2304
2305         if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
2306                 return WERR_FOOBAR;
2307         }
2308
2309         out->attid                      = dsdb_attribute_get_attid(attr,
2310                                                                    ctx->is_schema_nc);
2311         out->value_ctr.num_values       = in->num_values;
2312         out->value_ctr.values           = talloc_array(mem_ctx,
2313                                                        struct drsuapi_DsAttributeValue,
2314                                                        in->num_values);
2315         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
2316
2317         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
2318         W_ERROR_HAVE_NO_MEMORY(blobs);
2319
2320         for (i=0; i < in->num_values; i++) {
2321                 uint8_t *data;
2322                 size_t ret;
2323
2324                 out->value_ctr.values[i].blob   = &blobs[i];
2325
2326                 if (!convert_string_talloc(blobs, CH_UNIX, CH_UTF16,
2327                                            in->values[i].data,
2328                                            in->values[i].length,
2329                                            (void **)&data, &ret)) {
2330                         return WERR_FOOBAR;
2331                 }
2332
2333                 blobs[i] = data_blob_talloc(blobs, NULL, 4 + ret);
2334                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
2335
2336                 SIVAL(blobs[i].data, 0, 4 + ret);
2337
2338                 if (ret > 0) {
2339                         memcpy(blobs[i].data + 4, data, ret);
2340                         talloc_free(data);
2341                 }
2342         }
2343
2344         return WERR_OK;
2345 }
2346
2347 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_validate_ldb(const struct dsdb_syntax_ctx *ctx,
2348                                                             const struct dsdb_attribute *attr,
2349                                                             const struct ldb_message_element *in)
2350 {
2351         return dsdb_syntax_UNICODE_validate_ldb(ctx,
2352                                                 attr,
2353                                                 in);
2354 }
2355
2356 #define OMOBJECTCLASS(val) { .length = sizeof(val) - 1, .data = discard_const_p(uint8_t, val) }
2357
2358 static const struct dsdb_syntax dsdb_syntaxes[] = {
2359         {
2360                 .name                   = "Boolean",
2361                 .ldap_oid               = LDB_SYNTAX_BOOLEAN,
2362                 .oMSyntax               = 1,
2363                 .attributeSyntax_oid    = "2.5.5.8",
2364                 .drsuapi_to_ldb         = dsdb_syntax_BOOL_drsuapi_to_ldb,
2365                 .ldb_to_drsuapi         = dsdb_syntax_BOOL_ldb_to_drsuapi,
2366                 .validate_ldb           = dsdb_syntax_BOOL_validate_ldb,
2367                 .equality               = "booleanMatch",
2368                 .comment                = "Boolean"
2369         },{
2370                 .name                   = "Integer",
2371                 .ldap_oid               = LDB_SYNTAX_INTEGER,
2372                 .oMSyntax               = 2,
2373                 .attributeSyntax_oid    = "2.5.5.9",
2374                 .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
2375                 .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
2376                 .validate_ldb           = dsdb_syntax_INT32_validate_ldb,
2377                 .equality               = "integerMatch",
2378                 .comment                = "Integer",
2379                 .ldb_syntax             = LDB_SYNTAX_SAMBA_INT32
2380         },{
2381                 .name                   = "String(Octet)",
2382                 .ldap_oid               = LDB_SYNTAX_OCTET_STRING,
2383                 .oMSyntax               = 4,
2384                 .attributeSyntax_oid    = "2.5.5.10",
2385                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2386                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2387                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2388                 .equality               = "octetStringMatch",
2389                 .comment                = "Octet String",
2390         },{
2391                 .name                   = "String(Sid)",
2392                 .ldap_oid               = LDB_SYNTAX_OCTET_STRING,
2393                 .oMSyntax               = 4,
2394                 .attributeSyntax_oid    = "2.5.5.17",
2395                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2396                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2397                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2398                 .equality               = "octetStringMatch",
2399                 .comment                = "Octet String - Security Identifier (SID)",
2400                 .ldb_syntax             = LDB_SYNTAX_SAMBA_SID
2401         },{
2402                 .name                   = "String(Object-Identifier)",
2403                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.38",
2404                 .oMSyntax               = 6,
2405                 .attributeSyntax_oid    = "2.5.5.2",
2406                 .drsuapi_to_ldb         = dsdb_syntax_OID_drsuapi_to_ldb,
2407                 .ldb_to_drsuapi         = dsdb_syntax_OID_ldb_to_drsuapi,
2408                 .validate_ldb           = dsdb_syntax_OID_validate_ldb,
2409                 .equality               = "caseIgnoreMatch", /* Would use "objectIdentifierMatch" but most are ldap attribute/class names */
2410                 .comment                = "OID String",
2411                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING
2412         },{
2413                 .name                   = "Enumeration",
2414                 .ldap_oid               = LDB_SYNTAX_INTEGER,
2415                 .oMSyntax               = 10,
2416                 .attributeSyntax_oid    = "2.5.5.9",
2417                 .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
2418                 .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
2419                 .validate_ldb           = dsdb_syntax_INT32_validate_ldb,
2420                 .ldb_syntax             = LDB_SYNTAX_SAMBA_INT32
2421         },{
2422         /* not used in w2k3 forest */
2423                 .name                   = "String(Numeric)",
2424                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.36",
2425                 .oMSyntax               = 18,
2426                 .attributeSyntax_oid    = "2.5.5.6",
2427                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2428                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2429                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2430                 .equality               = "numericStringMatch",
2431                 .substring              = "numericStringSubstringsMatch",
2432                 .comment                = "Numeric String",
2433                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
2434         },{
2435                 .name                   = "String(Printable)",
2436                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.44",
2437                 .oMSyntax               = 19,
2438                 .attributeSyntax_oid    = "2.5.5.5",
2439                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2440                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2441                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2442                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
2443         },{
2444                 .name                   = "String(Teletex)",
2445                 .ldap_oid               = "1.2.840.113556.1.4.905",
2446                 .oMSyntax               = 20,
2447                 .attributeSyntax_oid    = "2.5.5.4",
2448                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2449                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2450                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2451                 .equality               = "caseIgnoreMatch",
2452                 .substring              = "caseIgnoreSubstringsMatch",
2453                 .comment                = "Case Insensitive String",
2454                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
2455         },{
2456                 .name                   = "String(IA5)",
2457                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.26",
2458                 .oMSyntax               = 22,
2459                 .attributeSyntax_oid    = "2.5.5.5",
2460                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2461                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2462                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2463                 .equality               = "caseExactIA5Match",
2464                 .comment                = "Printable String",
2465                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
2466         },{
2467                 .name                   = "String(UTC-Time)",
2468                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.53",
2469                 .oMSyntax               = 23,
2470                 .attributeSyntax_oid    = "2.5.5.11",
2471                 .drsuapi_to_ldb         = dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb,
2472                 .ldb_to_drsuapi         = dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi,
2473                 .validate_ldb           = dsdb_syntax_NTTIME_UTC_validate_ldb,
2474                 .equality               = "generalizedTimeMatch",
2475                 .comment                = "UTC Time",
2476         },{
2477                 .name                   = "String(Generalized-Time)",
2478                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.24",
2479                 .oMSyntax               = 24,
2480                 .attributeSyntax_oid    = "2.5.5.11",
2481                 .drsuapi_to_ldb         = dsdb_syntax_NTTIME_drsuapi_to_ldb,
2482                 .ldb_to_drsuapi         = dsdb_syntax_NTTIME_ldb_to_drsuapi,
2483                 .validate_ldb           = dsdb_syntax_NTTIME_validate_ldb,
2484                 .equality               = "generalizedTimeMatch",
2485                 .comment                = "Generalized Time",
2486                 .ldb_syntax             = LDB_SYNTAX_UTC_TIME,
2487         },{
2488         /* not used in w2k3 schema */
2489                 .name                   = "String(Case Sensitive)",
2490                 .ldap_oid               = "1.2.840.113556.1.4.1362",
2491                 .oMSyntax               = 27,
2492                 .attributeSyntax_oid    = "2.5.5.3",
2493                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2494                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2495                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2496                 .equality               = "caseExactMatch",
2497                 .substring              = "caseExactSubstringsMatch",
2498                 /* TODO (kim): according to LDAP rfc we should be using same comparison
2499                  * as Directory String (LDB_SYNTAX_DIRECTORY_STRING), but case sensitive.
2500                  * But according to ms docs binary compare should do the job:
2501                  * http://msdn.microsoft.com/en-us/library/cc223200(v=PROT.10).aspx */
2502                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
2503         },{
2504                 .name                   = "String(Unicode)",
2505                 .ldap_oid               = LDB_SYNTAX_DIRECTORY_STRING,
2506                 .oMSyntax               = 64,
2507                 .attributeSyntax_oid    = "2.5.5.12",
2508                 .drsuapi_to_ldb         = dsdb_syntax_UNICODE_drsuapi_to_ldb,
2509                 .ldb_to_drsuapi         = dsdb_syntax_UNICODE_ldb_to_drsuapi,
2510                 .validate_ldb           = dsdb_syntax_UNICODE_validate_ldb,
2511                 .equality               = "caseIgnoreMatch",
2512                 .substring              = "caseIgnoreSubstringsMatch",
2513                 .comment                = "Directory String",
2514         },{
2515                 .name                   = "Interval/LargeInteger",
2516                 .ldap_oid               = "1.2.840.113556.1.4.906",
2517                 .oMSyntax               = 65,
2518                 .attributeSyntax_oid    = "2.5.5.16",
2519                 .drsuapi_to_ldb         = dsdb_syntax_INT64_drsuapi_to_ldb,
2520                 .ldb_to_drsuapi         = dsdb_syntax_INT64_ldb_to_drsuapi,
2521                 .validate_ldb           = dsdb_syntax_INT64_validate_ldb,
2522                 .equality               = "integerMatch",
2523                 .comment                = "Large Integer",
2524                 .ldb_syntax             = LDB_SYNTAX_INTEGER,
2525         },{
2526                 .name                   = "String(NT-Sec-Desc)",
2527                 .ldap_oid               = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
2528                 .oMSyntax               = 66,
2529                 .attributeSyntax_oid    = "2.5.5.15",
2530                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2531                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2532                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2533         },{
2534                 .name                   = "Object(DS-DN)",
2535                 .ldap_oid               = LDB_SYNTAX_DN,
2536                 .oMSyntax               = 127,
2537                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x4a"),
2538                 .attributeSyntax_oid    = "2.5.5.1",
2539                 .drsuapi_to_ldb         = dsdb_syntax_DN_drsuapi_to_ldb,
2540                 .ldb_to_drsuapi         = dsdb_syntax_DN_ldb_to_drsuapi,
2541                 .validate_ldb           = dsdb_syntax_DN_validate_ldb,
2542                 .equality               = "distinguishedNameMatch",
2543                 .comment                = "Object(DS-DN) == a DN",
2544         },{
2545                 .name                   = "Object(DN-Binary)",
2546                 .ldap_oid               = DSDB_SYNTAX_BINARY_DN,
2547                 .oMSyntax               = 127,
2548                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0b"),
2549                 .attributeSyntax_oid    = "2.5.5.7",
2550                 .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
2551                 .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
2552                 .validate_ldb           = dsdb_syntax_DN_BINARY_validate_ldb,
2553                 .equality               = "octetStringMatch",
2554                 .comment                = "OctetString: Binary+DN",
2555         },{
2556         /* not used in w2k3 schema, but used in Exchange schema*/
2557                 .name                   = "Object(OR-Name)",
2558                 .ldap_oid               = DSDB_SYNTAX_OR_NAME,
2559                 .oMSyntax               = 127,
2560                 .oMObjectClass          = OMOBJECTCLASS("\x56\x06\x01\x02\x05\x0b\x1D"),
2561                 .attributeSyntax_oid    = "2.5.5.7",
2562                 .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
2563                 .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
2564                 .validate_ldb           = dsdb_syntax_DN_BINARY_validate_ldb,
2565                 .equality               = "caseIgnoreMatch",
2566                 .ldb_syntax             = LDB_SYNTAX_DN,
2567         },{
2568         /*
2569          * TODO: verify if DATA_BLOB is correct here...!
2570          *
2571          *       repsFrom and repsTo are the only attributes using
2572          *       this attribute syntax, but they're not replicated...
2573          */
2574                 .name                   = "Object(Replica-Link)",
2575                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.40",
2576                 .oMSyntax               = 127,
2577                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x06"),
2578                 .attributeSyntax_oid    = "2.5.5.10",
2579                 .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2580                 .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2581                 .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
2582         },{
2583                 .name                   = "Object(Presentation-Address)",
2584                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.43",
2585                 .oMSyntax               = 127,
2586                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x5c"),
2587                 .attributeSyntax_oid    = "2.5.5.13",
2588                 .drsuapi_to_ldb         = dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb,
2589                 .ldb_to_drsuapi         = dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi,
2590                 .validate_ldb           = dsdb_syntax_PRESENTATION_ADDRESS_validate_ldb,
2591                 .comment                = "Presentation Address",
2592                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
2593         },{
2594         /* not used in w2k3 schema */
2595                 .name                   = "Object(Access-Point)",
2596                 .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.2",
2597                 .oMSyntax               = 127,
2598                 .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x3e"),
2599                 .attributeSyntax_oid    = "2.5.5.14",
2600                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
2601                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
2602                 .validate_ldb           = dsdb_syntax_FOOBAR_validate_ldb,
2603                 .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
2604         },{
2605         /* not used in w2k3 schema */
2606                 .name                   = "Object(DN-String)",
2607                 .ldap_oid               = DSDB_SYNTAX_STRING_DN,
2608                 .oMSyntax               = 127,
2609                 .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0c"),
2610                 .attributeSyntax_oid    = "2.5.5.14",
2611                 .drsuapi_to_ldb         = dsdb_syntax_DN_STRING_drsuapi_to_ldb,
2612                 .ldb_to_drsuapi         = dsdb_syntax_DN_STRING_ldb_to_drsuapi,
2613                 .validate_ldb           = dsdb_syntax_DN_STRING_validate_ldb,
2614                 .equality               = "octetStringMatch",
2615                 .comment                = "OctetString: String+DN",
2616         }
2617 };
2618
2619 const struct dsdb_syntax *find_syntax_map_by_ad_oid(const char *ad_oid)
2620 {
2621         unsigned int i;
2622         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
2623                 if (strcasecmp(ad_oid, dsdb_syntaxes[i].attributeSyntax_oid) == 0) {
2624                         return &dsdb_syntaxes[i];
2625                 }
2626         }
2627         return NULL;
2628 }
2629
2630 const struct dsdb_syntax *find_syntax_map_by_ad_syntax(int oMSyntax)
2631 {
2632         unsigned int i;
2633         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
2634                 if (oMSyntax == dsdb_syntaxes[i].oMSyntax) {
2635                         return &dsdb_syntaxes[i];
2636                 }
2637         }
2638         return NULL;
2639 }
2640
2641 const struct dsdb_syntax *find_syntax_map_by_standard_oid(const char *standard_oid)
2642 {
2643         unsigned int i;
2644         for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
2645                 if (strcasecmp(standard_oid, dsdb_syntaxes[i].ldap_oid) == 0) {
2646                         return &dsdb_syntaxes[i];
2647                 }
2648         }
2649         return NULL;
2650 }
2651
2652 const struct dsdb_syntax *dsdb_syntax_for_attribute(const struct dsdb_attribute *attr)
2653 {
2654         unsigned int i;
2655
2656         for (i=0; i < ARRAY_SIZE(dsdb_syntaxes); i++) {
2657                 if (attr->oMSyntax != dsdb_syntaxes[i].oMSyntax) continue;
2658
2659                 if (attr->oMObjectClass.length != dsdb_syntaxes[i].oMObjectClass.length) continue;
2660
2661                 if (attr->oMObjectClass.length) {
2662                         int ret;
2663                         ret = memcmp(attr->oMObjectClass.data,
2664                                      dsdb_syntaxes[i].oMObjectClass.data,
2665                                      attr->oMObjectClass.length);
2666                         if (ret != 0) continue;
2667                 }
2668
2669                 if (strcmp(attr->attributeSyntax_oid, dsdb_syntaxes[i].attributeSyntax_oid) != 0) continue;
2670
2671                 return &dsdb_syntaxes[i];
2672         }
2673
2674         return NULL;
2675 }
2676
2677 WERROR dsdb_attribute_drsuapi_to_ldb(struct ldb_context *ldb,
2678                                      const struct dsdb_schema *schema,
2679                                      const struct dsdb_schema_prefixmap *pfm_remote,
2680                                      const struct drsuapi_DsReplicaAttribute *in,
2681                                      TALLOC_CTX *mem_ctx,
2682                                      struct ldb_message_element *out)
2683 {
2684         const struct dsdb_attribute *sa;
2685         struct dsdb_syntax_ctx syntax_ctx;
2686         uint32_t attid_local;
2687
2688         /* use default syntax conversion context */
2689         dsdb_syntax_ctx_init(&syntax_ctx, ldb, schema);
2690         syntax_ctx.pfm_remote = pfm_remote;
2691
2692         switch (dsdb_pfm_get_attid_type(in->attid)) {
2693         case DSDB_ATTID_TYPE_PFM:
2694                 /* map remote ATTID to local ATTID */
2695                 if (!dsdb_syntax_attid_from_remote_attid(&syntax_ctx, mem_ctx, in->attid, &attid_local)) {
2696                         DEBUG(0,(__location__ ": Can't find local ATTID for 0x%08X\n",
2697                                  in->attid));
2698                         return WERR_FOOBAR;
2699                 }
2700                 break;
2701         case DSDB_ATTID_TYPE_INTID:
2702                 /* use IntId value directly */
2703                 attid_local = in->attid;
2704                 break;
2705         default:
2706                 /* we should never get here */
2707                 DEBUG(0,(__location__ ": Invalid ATTID type passed for conversion - 0x%08X\n",
2708                          in->attid));
2709                 return WERR_INVALID_PARAMETER;
2710         }
2711
2712         sa = dsdb_attribute_by_attributeID_id(schema, attid_local);
2713         if (!sa) {
2714                 DEBUG(1,(__location__ ": Unknown attributeID_id 0x%08X\n", in->attid));
2715                 return WERR_FOOBAR;
2716         }
2717
2718         return sa->syntax->drsuapi_to_ldb(&syntax_ctx, sa, in, mem_ctx, out);
2719 }
2720
2721 WERROR dsdb_attribute_ldb_to_drsuapi(struct ldb_context *ldb,
2722                                      const struct dsdb_schema *schema,
2723                                      const struct ldb_message_element *in,
2724                                      TALLOC_CTX *mem_ctx,
2725                                      struct drsuapi_DsReplicaAttribute *out)
2726 {
2727         const struct dsdb_attribute *sa;
2728         struct dsdb_syntax_ctx syntax_ctx;
2729
2730         sa = dsdb_attribute_by_lDAPDisplayName(schema, in->name);
2731         if (!sa) {
2732                 return WERR_FOOBAR;
2733         }
2734
2735         /* use default syntax conversion context */
2736         dsdb_syntax_ctx_init(&syntax_ctx, ldb, schema);
2737
2738         return sa->syntax->ldb_to_drsuapi(&syntax_ctx, sa, in, mem_ctx, out);
2739 }
2740