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