s4:dsdb/schema: add dsdb_syntax_DN_validate_ldb()
[Samba/ekacnet.git] / source4 / dsdb / schema / schema_syntax.c
blob4fdc63ef7bd5e671672970795f6712830726b4ca
1 /*
2 Unix SMB/CIFS mplementation.
3 DSDB schema syntaxes
5 Copyright (C) Stefan Metzmacher <metze@samba.org> 2006
6 Copyright (C) Simo Sorce 2005
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
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.
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.
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/>.
23 #include "includes.h"
24 #include "dsdb/samdb/samdb.h"
25 #include "librpc/gen_ndr/ndr_drsuapi.h"
26 #include "librpc/gen_ndr/ndr_security.h"
27 #include "librpc/gen_ndr/ndr_misc.h"
28 #include "lib/ldb/include/ldb.h"
29 #include "lib/ldb/include/ldb_errors.h"
30 #include "system/time.h"
31 #include "../lib/util/charset/charset.h"
32 #include "librpc/ndr/libndr.h"
34 static WERROR dsdb_syntax_FOOBAR_drsuapi_to_ldb(struct ldb_context *ldb,
35 const struct dsdb_schema *schema,
36 const struct dsdb_attribute *attr,
37 const struct drsuapi_DsReplicaAttribute *in,
38 TALLOC_CTX *mem_ctx,
39 struct ldb_message_element *out)
41 uint32_t i;
43 out->flags = 0;
44 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
45 W_ERROR_HAVE_NO_MEMORY(out->name);
47 out->num_values = in->value_ctr.num_values;
48 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
49 W_ERROR_HAVE_NO_MEMORY(out->values);
51 for (i=0; i < out->num_values; i++) {
52 char *str;
54 if (in->value_ctr.values[i].blob == NULL) {
55 return WERR_FOOBAR;
58 str = talloc_asprintf(out->values, "%s: not implemented",
59 attr->syntax->name);
60 W_ERROR_HAVE_NO_MEMORY(str);
62 out->values[i] = data_blob_string_const(str);
65 return WERR_OK;
68 static WERROR dsdb_syntax_FOOBAR_ldb_to_drsuapi(struct ldb_context *ldb,
69 const struct dsdb_schema *schema,
70 const struct dsdb_attribute *attr,
71 const struct ldb_message_element *in,
72 TALLOC_CTX *mem_ctx,
73 struct drsuapi_DsReplicaAttribute *out)
75 return WERR_FOOBAR;
78 static WERROR dsdb_syntax_FOOBAR_validate_ldb(struct ldb_context *ldb,
79 const struct dsdb_schema *schema,
80 const struct dsdb_attribute *attr,
81 const struct ldb_message_element *in)
83 return WERR_FOOBAR;
86 static WERROR dsdb_syntax_ALLOW_validate_ldb(struct ldb_context *ldb,
87 const struct dsdb_schema *schema,
88 const struct dsdb_attribute *attr,
89 const struct ldb_message_element *in)
91 if (attr->attributeID_id == 0xFFFFFFFF) {
92 return WERR_FOOBAR;
95 return WERR_OK;
98 static WERROR dsdb_syntax_BOOL_drsuapi_to_ldb(struct ldb_context *ldb,
99 const struct dsdb_schema *schema,
100 const struct dsdb_attribute *attr,
101 const struct drsuapi_DsReplicaAttribute *in,
102 TALLOC_CTX *mem_ctx,
103 struct ldb_message_element *out)
105 uint32_t i;
107 out->flags = 0;
108 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
109 W_ERROR_HAVE_NO_MEMORY(out->name);
111 out->num_values = in->value_ctr.num_values;
112 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
113 W_ERROR_HAVE_NO_MEMORY(out->values);
115 for (i=0; i < out->num_values; i++) {
116 uint32_t v;
117 char *str;
119 if (in->value_ctr.values[i].blob == NULL) {
120 return WERR_FOOBAR;
123 if (in->value_ctr.values[i].blob->length != 4) {
124 return WERR_FOOBAR;
127 v = IVAL(in->value_ctr.values[i].blob->data, 0);
129 if (v != 0) {
130 str = talloc_strdup(out->values, "TRUE");
131 W_ERROR_HAVE_NO_MEMORY(str);
132 } else {
133 str = talloc_strdup(out->values, "FALSE");
134 W_ERROR_HAVE_NO_MEMORY(str);
137 out->values[i] = data_blob_string_const(str);
140 return WERR_OK;
143 static WERROR dsdb_syntax_BOOL_ldb_to_drsuapi(struct ldb_context *ldb,
144 const struct dsdb_schema *schema,
145 const struct dsdb_attribute *attr,
146 const struct ldb_message_element *in,
147 TALLOC_CTX *mem_ctx,
148 struct drsuapi_DsReplicaAttribute *out)
150 uint32_t i;
151 DATA_BLOB *blobs;
153 if (attr->attributeID_id == 0xFFFFFFFF) {
154 return WERR_FOOBAR;
157 out->attid = attr->attributeID_id;
158 out->value_ctr.num_values = in->num_values;
159 out->value_ctr.values = talloc_array(mem_ctx,
160 struct drsuapi_DsAttributeValue,
161 in->num_values);
162 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
164 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
165 W_ERROR_HAVE_NO_MEMORY(blobs);
167 for (i=0; i < in->num_values; i++) {
168 out->value_ctr.values[i].blob = &blobs[i];
170 blobs[i] = data_blob_talloc(blobs, NULL, 4);
171 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
173 if (strcmp("TRUE", (const char *)in->values[i].data) == 0) {
174 SIVAL(blobs[i].data, 0, 0x00000001);
175 } else if (strcmp("FALSE", (const char *)in->values[i].data) == 0) {
176 SIVAL(blobs[i].data, 0, 0x00000000);
177 } else {
178 return WERR_FOOBAR;
182 return WERR_OK;
185 static WERROR dsdb_syntax_BOOL_validate_ldb(struct ldb_context *ldb,
186 const struct dsdb_schema *schema,
187 const struct dsdb_attribute *attr,
188 const struct ldb_message_element *in)
190 uint32_t i;
192 if (attr->attributeID_id == 0xFFFFFFFF) {
193 return WERR_FOOBAR;
196 for (i=0; i < in->num_values; i++) {
197 int t, f;
199 t = strncmp("TRUE",
200 (const char *)in->values[i].data,
201 in->values[i].length);
202 f = strncmp("FALSE",
203 (const char *)in->values[i].data,
204 in->values[i].length);
206 if (t != 0 && f != 0) {
207 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
211 return WERR_OK;
214 static WERROR dsdb_syntax_INT32_drsuapi_to_ldb(struct ldb_context *ldb,
215 const struct dsdb_schema *schema,
216 const struct dsdb_attribute *attr,
217 const struct drsuapi_DsReplicaAttribute *in,
218 TALLOC_CTX *mem_ctx,
219 struct ldb_message_element *out)
221 uint32_t i;
223 out->flags = 0;
224 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
225 W_ERROR_HAVE_NO_MEMORY(out->name);
227 out->num_values = in->value_ctr.num_values;
228 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
229 W_ERROR_HAVE_NO_MEMORY(out->values);
231 for (i=0; i < out->num_values; i++) {
232 int32_t v;
233 char *str;
235 if (in->value_ctr.values[i].blob == NULL) {
236 return WERR_FOOBAR;
239 if (in->value_ctr.values[i].blob->length != 4) {
240 return WERR_FOOBAR;
243 v = IVALS(in->value_ctr.values[i].blob->data, 0);
245 str = talloc_asprintf(out->values, "%d", v);
246 W_ERROR_HAVE_NO_MEMORY(str);
248 out->values[i] = data_blob_string_const(str);
251 return WERR_OK;
254 static WERROR dsdb_syntax_INT32_ldb_to_drsuapi(struct ldb_context *ldb,
255 const struct dsdb_schema *schema,
256 const struct dsdb_attribute *attr,
257 const struct ldb_message_element *in,
258 TALLOC_CTX *mem_ctx,
259 struct drsuapi_DsReplicaAttribute *out)
261 uint32_t i;
262 DATA_BLOB *blobs;
264 if (attr->attributeID_id == 0xFFFFFFFF) {
265 return WERR_FOOBAR;
268 out->attid = attr->attributeID_id;
269 out->value_ctr.num_values = in->num_values;
270 out->value_ctr.values = talloc_array(mem_ctx,
271 struct drsuapi_DsAttributeValue,
272 in->num_values);
273 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
275 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
276 W_ERROR_HAVE_NO_MEMORY(blobs);
278 for (i=0; i < in->num_values; i++) {
279 int32_t v;
281 out->value_ctr.values[i].blob = &blobs[i];
283 blobs[i] = data_blob_talloc(blobs, NULL, 4);
284 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
286 /* We've to use "strtoll" here to have the intended overflows.
287 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
288 v = (int32_t) strtoll((char *)in->values[i].data, NULL, 0);
290 SIVALS(blobs[i].data, 0, v);
293 return WERR_OK;
296 static WERROR dsdb_syntax_INT32_validate_ldb(struct ldb_context *ldb,
297 const struct dsdb_schema *schema,
298 const struct dsdb_attribute *attr,
299 const struct ldb_message_element *in)
301 uint32_t i;
303 if (attr->attributeID_id == 0xFFFFFFFF) {
304 return WERR_FOOBAR;
307 for (i=0; i < in->num_values; i++) {
308 long v;
309 char buf[sizeof("-2147483648")];
310 char *end = NULL;
312 ZERO_STRUCT(buf);
313 if (in->values[i].length >= sizeof(buf)) {
314 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
317 memcpy(buf, in->values[i].data, in->values[i].length);
318 errno = 0;
319 v = strtol(buf, &end, 10);
320 if (errno != 0) {
321 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
323 if (end && end[0] != '\0') {
324 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
327 if (attr->rangeLower) {
328 if ((int32_t)v < (int32_t)*attr->rangeLower) {
329 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
333 if (attr->rangeUpper) {
334 if ((int32_t)v > (int32_t)*attr->rangeUpper) {
335 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
340 return WERR_OK;
343 static WERROR dsdb_syntax_INT64_drsuapi_to_ldb(struct ldb_context *ldb,
344 const struct dsdb_schema *schema,
345 const struct dsdb_attribute *attr,
346 const struct drsuapi_DsReplicaAttribute *in,
347 TALLOC_CTX *mem_ctx,
348 struct ldb_message_element *out)
350 uint32_t i;
352 out->flags = 0;
353 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
354 W_ERROR_HAVE_NO_MEMORY(out->name);
356 out->num_values = in->value_ctr.num_values;
357 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
358 W_ERROR_HAVE_NO_MEMORY(out->values);
360 for (i=0; i < out->num_values; i++) {
361 int64_t v;
362 char *str;
364 if (in->value_ctr.values[i].blob == NULL) {
365 return WERR_FOOBAR;
368 if (in->value_ctr.values[i].blob->length != 8) {
369 return WERR_FOOBAR;
372 v = BVALS(in->value_ctr.values[i].blob->data, 0);
374 str = talloc_asprintf(out->values, "%lld", (long long int)v);
375 W_ERROR_HAVE_NO_MEMORY(str);
377 out->values[i] = data_blob_string_const(str);
380 return WERR_OK;
383 static WERROR dsdb_syntax_INT64_ldb_to_drsuapi(struct ldb_context *ldb,
384 const struct dsdb_schema *schema,
385 const struct dsdb_attribute *attr,
386 const struct ldb_message_element *in,
387 TALLOC_CTX *mem_ctx,
388 struct drsuapi_DsReplicaAttribute *out)
390 uint32_t i;
391 DATA_BLOB *blobs;
393 if (attr->attributeID_id == 0xFFFFFFFF) {
394 return WERR_FOOBAR;
397 out->attid = attr->attributeID_id;
398 out->value_ctr.num_values = in->num_values;
399 out->value_ctr.values = talloc_array(mem_ctx,
400 struct drsuapi_DsAttributeValue,
401 in->num_values);
402 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
404 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
405 W_ERROR_HAVE_NO_MEMORY(blobs);
407 for (i=0; i < in->num_values; i++) {
408 int64_t v;
410 out->value_ctr.values[i].blob = &blobs[i];
412 blobs[i] = data_blob_talloc(blobs, NULL, 8);
413 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
415 v = strtoll((const char *)in->values[i].data, NULL, 10);
417 SBVALS(blobs[i].data, 0, v);
420 return WERR_OK;
423 static WERROR dsdb_syntax_INT64_validate_ldb(struct ldb_context *ldb,
424 const struct dsdb_schema *schema,
425 const struct dsdb_attribute *attr,
426 const struct ldb_message_element *in)
428 uint32_t i;
430 if (attr->attributeID_id == 0xFFFFFFFF) {
431 return WERR_FOOBAR;
434 for (i=0; i < in->num_values; i++) {
435 long long v;
436 char buf[sizeof("-9223372036854775808")];
437 char *end = NULL;
439 ZERO_STRUCT(buf);
440 if (in->values[i].length >= sizeof(buf)) {
441 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
443 memcpy(buf, in->values[i].data, in->values[i].length);
445 errno = 0;
446 v = strtoll(buf, &end, 10);
447 if (errno != 0) {
448 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
450 if (end && end[0] != '\0') {
451 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
454 if (attr->rangeLower) {
455 if ((int64_t)v < (int64_t)*attr->rangeLower) {
456 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
460 if (attr->rangeUpper) {
461 if ((int64_t)v > (int64_t)*attr->rangeUpper) {
462 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
467 return WERR_OK;
469 static WERROR dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb(struct ldb_context *ldb,
470 const struct dsdb_schema *schema,
471 const struct dsdb_attribute *attr,
472 const struct drsuapi_DsReplicaAttribute *in,
473 TALLOC_CTX *mem_ctx,
474 struct ldb_message_element *out)
476 uint32_t i;
478 out->flags = 0;
479 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
480 W_ERROR_HAVE_NO_MEMORY(out->name);
482 out->num_values = in->value_ctr.num_values;
483 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
484 W_ERROR_HAVE_NO_MEMORY(out->values);
486 for (i=0; i < out->num_values; i++) {
487 NTTIME v;
488 time_t t;
489 char *str;
491 if (in->value_ctr.values[i].blob == NULL) {
492 return WERR_FOOBAR;
495 if (in->value_ctr.values[i].blob->length != 8) {
496 return WERR_FOOBAR;
499 v = BVAL(in->value_ctr.values[i].blob->data, 0);
500 v *= 10000000;
501 t = nt_time_to_unix(v);
504 * NOTE: On a w2k3 server you can set a GeneralizedTime string
505 * via LDAP, but you get back an UTCTime string,
506 * but via DRSUAPI you get back the NTTIME_1sec value
507 * that represents the GeneralizedTime value!
509 * So if we store the UTCTime string in our ldb
510 * we'll loose information!
512 str = ldb_timestring_utc(out->values, t);
513 W_ERROR_HAVE_NO_MEMORY(str);
514 out->values[i] = data_blob_string_const(str);
517 return WERR_OK;
520 static WERROR dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi(struct ldb_context *ldb,
521 const struct dsdb_schema *schema,
522 const struct dsdb_attribute *attr,
523 const struct ldb_message_element *in,
524 TALLOC_CTX *mem_ctx,
525 struct drsuapi_DsReplicaAttribute *out)
527 uint32_t i;
528 DATA_BLOB *blobs;
530 if (attr->attributeID_id == 0xFFFFFFFF) {
531 return WERR_FOOBAR;
534 out->attid = attr->attributeID_id;
535 out->value_ctr.num_values = in->num_values;
536 out->value_ctr.values = talloc_array(mem_ctx,
537 struct drsuapi_DsAttributeValue,
538 in->num_values);
539 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
541 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
542 W_ERROR_HAVE_NO_MEMORY(blobs);
544 for (i=0; i < in->num_values; i++) {
545 NTTIME v;
546 time_t t;
548 out->value_ctr.values[i].blob = &blobs[i];
550 blobs[i] = data_blob_talloc(blobs, NULL, 8);
551 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
553 t = ldb_string_utc_to_time((const char *)in->values[i].data);
554 unix_to_nt_time(&v, t);
555 v /= 10000000;
557 SBVAL(blobs[i].data, 0, v);
560 return WERR_OK;
563 static WERROR dsdb_syntax_NTTIME_UTC_validate_ldb(struct ldb_context *ldb,
564 const struct dsdb_schema *schema,
565 const struct dsdb_attribute *attr,
566 const struct ldb_message_element *in)
568 uint32_t i;
570 if (attr->attributeID_id == 0xFFFFFFFF) {
571 return WERR_FOOBAR;
574 for (i=0; i < in->num_values; i++) {
575 time_t t;
576 char buf[sizeof("090826075717Z")];
578 ZERO_STRUCT(buf);
579 if (in->values[i].length >= sizeof(buf)) {
580 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
582 memcpy(buf, in->values[i].data, in->values[i].length);
584 errno = 0;
585 t = ldb_string_utc_to_time(buf);
586 if (errno != 0) {
587 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
590 if (attr->rangeLower) {
591 if ((int32_t)t < (int32_t)*attr->rangeLower) {
592 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
596 if (attr->rangeUpper) {
597 if ((int32_t)t > (int32_t)*attr->rangeLower) {
598 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
603 * TODO: verify the comment in the
604 * dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb() function!
608 return WERR_OK;
611 static WERROR dsdb_syntax_NTTIME_drsuapi_to_ldb(struct ldb_context *ldb,
612 const struct dsdb_schema *schema,
613 const struct dsdb_attribute *attr,
614 const struct drsuapi_DsReplicaAttribute *in,
615 TALLOC_CTX *mem_ctx,
616 struct ldb_message_element *out)
618 uint32_t i;
620 out->flags = 0;
621 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
622 W_ERROR_HAVE_NO_MEMORY(out->name);
624 out->num_values = in->value_ctr.num_values;
625 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
626 W_ERROR_HAVE_NO_MEMORY(out->values);
628 for (i=0; i < out->num_values; i++) {
629 NTTIME v;
630 time_t t;
631 char *str;
633 if (in->value_ctr.values[i].blob == NULL) {
634 return WERR_FOOBAR;
637 if (in->value_ctr.values[i].blob->length != 8) {
638 return WERR_FOOBAR;
641 v = BVAL(in->value_ctr.values[i].blob->data, 0);
642 v *= 10000000;
643 t = nt_time_to_unix(v);
645 str = ldb_timestring(out->values, t);
646 W_ERROR_HAVE_NO_MEMORY(str);
648 out->values[i] = data_blob_string_const(str);
651 return WERR_OK;
654 static WERROR dsdb_syntax_NTTIME_ldb_to_drsuapi(struct ldb_context *ldb,
655 const struct dsdb_schema *schema,
656 const struct dsdb_attribute *attr,
657 const struct ldb_message_element *in,
658 TALLOC_CTX *mem_ctx,
659 struct drsuapi_DsReplicaAttribute *out)
661 uint32_t i;
662 DATA_BLOB *blobs;
664 if (attr->attributeID_id == 0xFFFFFFFF) {
665 return WERR_FOOBAR;
668 out->attid = attr->attributeID_id;
669 out->value_ctr.num_values = in->num_values;
670 out->value_ctr.values = talloc_array(mem_ctx,
671 struct drsuapi_DsAttributeValue,
672 in->num_values);
673 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
675 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
676 W_ERROR_HAVE_NO_MEMORY(blobs);
678 for (i=0; i < in->num_values; i++) {
679 NTTIME v;
680 time_t t;
681 int ret;
683 out->value_ctr.values[i].blob = &blobs[i];
685 blobs[i] = data_blob_talloc(blobs, NULL, 8);
686 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
688 ret = ldb_val_to_time(&in->values[i], &t);
689 if (ret != LDB_SUCCESS) {
690 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
692 unix_to_nt_time(&v, t);
693 v /= 10000000;
695 SBVAL(blobs[i].data, 0, v);
698 return WERR_OK;
701 static WERROR dsdb_syntax_NTTIME_validate_ldb(struct ldb_context *ldb,
702 const struct dsdb_schema *schema,
703 const struct dsdb_attribute *attr,
704 const struct ldb_message_element *in)
706 uint32_t i;
708 if (attr->attributeID_id == 0xFFFFFFFF) {
709 return WERR_FOOBAR;
712 for (i=0; i < in->num_values; i++) {
713 time_t t;
714 int ret;
716 ret = ldb_val_to_time(&in->values[i], &t);
717 if (ret != LDB_SUCCESS) {
718 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
721 if (attr->rangeLower) {
722 if ((int32_t)t < (int32_t)*attr->rangeLower) {
723 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
727 if (attr->rangeUpper) {
728 if ((int32_t)t > (int32_t)*attr->rangeLower) {
729 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
734 return WERR_OK;
737 static WERROR dsdb_syntax_DATA_BLOB_drsuapi_to_ldb(struct ldb_context *ldb,
738 const struct dsdb_schema *schema,
739 const struct dsdb_attribute *attr,
740 const struct drsuapi_DsReplicaAttribute *in,
741 TALLOC_CTX *mem_ctx,
742 struct ldb_message_element *out)
744 uint32_t i;
746 out->flags = 0;
747 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
748 W_ERROR_HAVE_NO_MEMORY(out->name);
750 out->num_values = in->value_ctr.num_values;
751 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
752 W_ERROR_HAVE_NO_MEMORY(out->values);
754 for (i=0; i < out->num_values; i++) {
755 if (in->value_ctr.values[i].blob == NULL) {
756 return WERR_FOOBAR;
759 if (in->value_ctr.values[i].blob->length == 0) {
760 return WERR_FOOBAR;
763 out->values[i] = data_blob_dup_talloc(out->values,
764 in->value_ctr.values[i].blob);
765 W_ERROR_HAVE_NO_MEMORY(out->values[i].data);
768 return WERR_OK;
771 static WERROR dsdb_syntax_DATA_BLOB_ldb_to_drsuapi(struct ldb_context *ldb,
772 const struct dsdb_schema *schema,
773 const struct dsdb_attribute *attr,
774 const struct ldb_message_element *in,
775 TALLOC_CTX *mem_ctx,
776 struct drsuapi_DsReplicaAttribute *out)
778 uint32_t i;
779 DATA_BLOB *blobs;
781 if (attr->attributeID_id == 0xFFFFFFFF) {
782 return WERR_FOOBAR;
785 out->attid = attr->attributeID_id;
786 out->value_ctr.num_values = in->num_values;
787 out->value_ctr.values = talloc_array(mem_ctx,
788 struct drsuapi_DsAttributeValue,
789 in->num_values);
790 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
792 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
793 W_ERROR_HAVE_NO_MEMORY(blobs);
795 for (i=0; i < in->num_values; i++) {
796 out->value_ctr.values[i].blob = &blobs[i];
798 blobs[i] = data_blob_dup_talloc(blobs, &in->values[i]);
799 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
802 return WERR_OK;
805 static WERROR dsdb_syntax_DATA_BLOB_validate_one_val(struct ldb_context *ldb,
806 const struct dsdb_schema *schema,
807 const struct dsdb_attribute *attr,
808 const struct ldb_val *val)
810 if (attr->attributeID_id == 0xFFFFFFFF) {
811 return WERR_FOOBAR;
814 if (attr->rangeLower) {
815 if ((uint32_t)val->length < (uint32_t)*attr->rangeLower) {
816 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
820 if (attr->rangeUpper) {
821 if ((uint32_t)val->length > (uint32_t)*attr->rangeUpper) {
822 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
826 return WERR_OK;
829 static WERROR dsdb_syntax_DATA_BLOB_validate_ldb(struct ldb_context *ldb,
830 const struct dsdb_schema *schema,
831 const struct dsdb_attribute *attr,
832 const struct ldb_message_element *in)
834 uint32_t i;
835 WERROR status;
837 if (attr->attributeID_id == 0xFFFFFFFF) {
838 return WERR_FOOBAR;
841 for (i=0; i < in->num_values; i++) {
842 if (in->values[i].length == 0) {
843 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
846 status = dsdb_syntax_DATA_BLOB_validate_one_val(ldb,
847 schema,
848 attr,
849 &in->values[i]);
850 if (!W_ERROR_IS_OK(status)) {
851 return status;
855 return WERR_OK;
858 static WERROR _dsdb_syntax_auto_OID_drsuapi_to_ldb(struct ldb_context *ldb,
859 const struct dsdb_schema *schema,
860 const struct dsdb_attribute *attr,
861 const struct drsuapi_DsReplicaAttribute *in,
862 TALLOC_CTX *mem_ctx,
863 struct ldb_message_element *out)
865 uint32_t i;
867 out->flags = 0;
868 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
869 W_ERROR_HAVE_NO_MEMORY(out->name);
871 out->num_values = in->value_ctr.num_values;
872 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
873 W_ERROR_HAVE_NO_MEMORY(out->values);
875 for (i=0; i < out->num_values; i++) {
876 uint32_t v;
877 const struct dsdb_class *c;
878 const struct dsdb_attribute *a;
879 const char *str = NULL;
881 if (in->value_ctr.values[i].blob == NULL) {
882 return WERR_FOOBAR;
885 if (in->value_ctr.values[i].blob->length != 4) {
886 return WERR_FOOBAR;
889 v = IVAL(in->value_ctr.values[i].blob->data, 0);
891 if ((c = dsdb_class_by_governsID_id(schema, v))) {
892 str = talloc_strdup(out->values, c->lDAPDisplayName);
893 } else if ((a = dsdb_attribute_by_attributeID_id(schema, v))) {
894 str = talloc_strdup(out->values, a->lDAPDisplayName);
895 } else {
896 WERROR werr;
897 werr = dsdb_schema_pfm_oid_from_attid(schema->prefixmap, v, out->values, &str);
898 W_ERROR_NOT_OK_RETURN(werr);
900 W_ERROR_HAVE_NO_MEMORY(str);
902 /* the values need to be reversed */
903 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
906 return WERR_OK;
909 static WERROR _dsdb_syntax_OID_obj_drsuapi_to_ldb(struct ldb_context *ldb,
910 const struct dsdb_schema *schema,
911 const struct dsdb_attribute *attr,
912 const struct drsuapi_DsReplicaAttribute *in,
913 TALLOC_CTX *mem_ctx,
914 struct ldb_message_element *out)
916 uint32_t i;
918 out->flags = 0;
919 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
920 W_ERROR_HAVE_NO_MEMORY(out->name);
922 out->num_values = in->value_ctr.num_values;
923 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
924 W_ERROR_HAVE_NO_MEMORY(out->values);
926 for (i=0; i < out->num_values; i++) {
927 uint32_t v;
928 const struct dsdb_class *c;
929 const char *str;
931 if (in->value_ctr.values[i].blob == NULL) {
932 return WERR_FOOBAR;
935 if (in->value_ctr.values[i].blob->length != 4) {
936 return WERR_FOOBAR;
939 v = IVAL(in->value_ctr.values[i].blob->data, 0);
941 c = dsdb_class_by_governsID_id(schema, v);
942 if (!c) {
943 return WERR_FOOBAR;
946 str = talloc_strdup(out->values, c->lDAPDisplayName);
947 W_ERROR_HAVE_NO_MEMORY(str);
949 /* the values need to be reversed */
950 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
953 return WERR_OK;
956 static WERROR _dsdb_syntax_OID_attr_drsuapi_to_ldb(struct ldb_context *ldb,
957 const struct dsdb_schema *schema,
958 const struct dsdb_attribute *attr,
959 const struct drsuapi_DsReplicaAttribute *in,
960 TALLOC_CTX *mem_ctx,
961 struct ldb_message_element *out)
963 uint32_t i;
965 out->flags = 0;
966 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
967 W_ERROR_HAVE_NO_MEMORY(out->name);
969 out->num_values = in->value_ctr.num_values;
970 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
971 W_ERROR_HAVE_NO_MEMORY(out->values);
973 for (i=0; i < out->num_values; i++) {
974 uint32_t v;
975 const struct dsdb_attribute *a;
976 const char *str;
978 if (in->value_ctr.values[i].blob == NULL) {
979 return WERR_FOOBAR;
982 if (in->value_ctr.values[i].blob->length != 4) {
983 return WERR_FOOBAR;
986 v = IVAL(in->value_ctr.values[i].blob->data, 0);
988 a = dsdb_attribute_by_attributeID_id(schema, v);
989 if (!a) {
990 return WERR_FOOBAR;
993 str = talloc_strdup(out->values, a->lDAPDisplayName);
994 W_ERROR_HAVE_NO_MEMORY(str);
996 /* the values need to be reversed */
997 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
1000 return WERR_OK;
1003 static WERROR _dsdb_syntax_OID_oid_drsuapi_to_ldb(struct ldb_context *ldb,
1004 const struct dsdb_schema *schema,
1005 const struct dsdb_attribute *attr,
1006 const struct drsuapi_DsReplicaAttribute *in,
1007 TALLOC_CTX *mem_ctx,
1008 struct ldb_message_element *out)
1010 uint32_t i;
1012 out->flags = 0;
1013 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1014 W_ERROR_HAVE_NO_MEMORY(out->name);
1016 out->num_values = in->value_ctr.num_values;
1017 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1018 W_ERROR_HAVE_NO_MEMORY(out->values);
1020 for (i=0; i < out->num_values; i++) {
1021 uint32_t attid;
1022 WERROR status;
1023 const char *oid;
1025 if (in->value_ctr.values[i].blob == NULL) {
1026 return WERR_FOOBAR;
1029 if (in->value_ctr.values[i].blob->length != 4) {
1030 return WERR_FOOBAR;
1033 attid = IVAL(in->value_ctr.values[i].blob->data, 0);
1035 status = dsdb_schema_pfm_oid_from_attid(schema->prefixmap, attid, out->values, &oid);
1036 W_ERROR_NOT_OK_RETURN(status);
1038 out->values[i] = data_blob_string_const(oid);
1041 return WERR_OK;
1044 static WERROR _dsdb_syntax_auto_OID_ldb_to_drsuapi(struct ldb_context *ldb,
1045 const struct dsdb_schema *schema,
1046 const struct dsdb_attribute *attr,
1047 const struct ldb_message_element *in,
1048 TALLOC_CTX *mem_ctx,
1049 struct drsuapi_DsReplicaAttribute *out)
1051 uint32_t i;
1052 DATA_BLOB *blobs;
1054 out->attid= attr->attributeID_id;
1055 out->value_ctr.num_values= in->num_values;
1056 out->value_ctr.values= talloc_array(mem_ctx,
1057 struct drsuapi_DsAttributeValue,
1058 in->num_values);
1059 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1061 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1062 W_ERROR_HAVE_NO_MEMORY(blobs);
1064 for (i=0; i < in->num_values; i++) {
1065 const struct dsdb_class *obj_class;
1066 const struct dsdb_attribute *obj_attr;
1067 struct ldb_val *v;
1069 out->value_ctr.values[i].blob= &blobs[i];
1071 blobs[i] = data_blob_talloc(blobs, NULL, 4);
1072 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1074 /* in DRS windows puts the classes in the opposite
1075 order to the order used in ldap */
1076 v = &in->values[(in->num_values-1)-i];
1078 if ((obj_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema, v))) {
1079 SIVAL(blobs[i].data, 0, obj_class->governsID_id);
1080 } else if ((obj_attr = dsdb_attribute_by_lDAPDisplayName_ldb_val(schema, v))) {
1081 SIVAL(blobs[i].data, 0, obj_attr->attributeID_id);
1082 } else {
1083 uint32_t attid;
1084 WERROR werr;
1085 werr = dsdb_schema_pfm_make_attid(schema->prefixmap,
1086 (const char *)v->data,
1087 &attid);
1088 W_ERROR_NOT_OK_RETURN(werr);
1089 SIVAL(blobs[i].data, 0, attid);
1095 return WERR_OK;
1098 static WERROR _dsdb_syntax_OID_obj_ldb_to_drsuapi(struct ldb_context *ldb,
1099 const struct dsdb_schema *schema,
1100 const struct dsdb_attribute *attr,
1101 const struct ldb_message_element *in,
1102 TALLOC_CTX *mem_ctx,
1103 struct drsuapi_DsReplicaAttribute *out)
1105 uint32_t i;
1106 DATA_BLOB *blobs;
1108 out->attid= attr->attributeID_id;
1109 out->value_ctr.num_values= in->num_values;
1110 out->value_ctr.values= talloc_array(mem_ctx,
1111 struct drsuapi_DsAttributeValue,
1112 in->num_values);
1113 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1115 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1116 W_ERROR_HAVE_NO_MEMORY(blobs);
1118 for (i=0; i < in->num_values; i++) {
1119 const struct dsdb_class *obj_class;
1121 out->value_ctr.values[i].blob= &blobs[i];
1123 blobs[i] = data_blob_talloc(blobs, NULL, 4);
1124 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1126 /* in DRS windows puts the classes in the opposite
1127 order to the order used in ldap */
1128 obj_class = dsdb_class_by_lDAPDisplayName(schema,
1129 (const char *)in->values[(in->num_values-1)-i].data);
1130 if (!obj_class) {
1131 return WERR_FOOBAR;
1133 SIVAL(blobs[i].data, 0, obj_class->governsID_id);
1137 return WERR_OK;
1140 static WERROR _dsdb_syntax_OID_attr_ldb_to_drsuapi(struct ldb_context *ldb,
1141 const struct dsdb_schema *schema,
1142 const struct dsdb_attribute *attr,
1143 const struct ldb_message_element *in,
1144 TALLOC_CTX *mem_ctx,
1145 struct drsuapi_DsReplicaAttribute *out)
1147 uint32_t i;
1148 DATA_BLOB *blobs;
1150 out->attid= attr->attributeID_id;
1151 out->value_ctr.num_values= in->num_values;
1152 out->value_ctr.values= talloc_array(mem_ctx,
1153 struct drsuapi_DsAttributeValue,
1154 in->num_values);
1155 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1157 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1158 W_ERROR_HAVE_NO_MEMORY(blobs);
1160 for (i=0; i < in->num_values; i++) {
1161 const struct dsdb_attribute *obj_attr;
1163 out->value_ctr.values[i].blob= &blobs[i];
1165 blobs[i] = data_blob_talloc(blobs, NULL, 4);
1166 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1168 obj_attr = dsdb_attribute_by_lDAPDisplayName(schema, (const char *)in->values[i].data);
1169 if (!obj_attr) {
1170 return WERR_FOOBAR;
1172 SIVAL(blobs[i].data, 0, obj_attr->attributeID_id);
1176 return WERR_OK;
1179 static WERROR _dsdb_syntax_OID_oid_ldb_to_drsuapi(struct ldb_context *ldb,
1180 const struct dsdb_schema *schema,
1181 const struct dsdb_attribute *attr,
1182 const struct ldb_message_element *in,
1183 TALLOC_CTX *mem_ctx,
1184 struct drsuapi_DsReplicaAttribute *out)
1186 uint32_t i;
1187 DATA_BLOB *blobs;
1189 out->attid= attr->attributeID_id;
1190 out->value_ctr.num_values= in->num_values;
1191 out->value_ctr.values= talloc_array(mem_ctx,
1192 struct drsuapi_DsAttributeValue,
1193 in->num_values);
1194 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1196 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1197 W_ERROR_HAVE_NO_MEMORY(blobs);
1199 for (i=0; i < in->num_values; i++) {
1200 uint32_t attid;
1201 WERROR status;
1203 out->value_ctr.values[i].blob= &blobs[i];
1205 blobs[i] = data_blob_talloc(blobs, NULL, 4);
1206 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1208 status = dsdb_schema_pfm_make_attid(schema->prefixmap,
1209 (const char *)in->values[i].data,
1210 &attid);
1211 W_ERROR_NOT_OK_RETURN(status);
1213 SIVAL(blobs[i].data, 0, attid);
1216 return WERR_OK;
1219 static WERROR dsdb_syntax_OID_drsuapi_to_ldb(struct ldb_context *ldb,
1220 const struct dsdb_schema *schema,
1221 const struct dsdb_attribute *attr,
1222 const struct drsuapi_DsReplicaAttribute *in,
1223 TALLOC_CTX *mem_ctx,
1224 struct ldb_message_element *out)
1226 switch (attr->attributeID_id) {
1227 case DRSUAPI_ATTRIBUTE_objectClass:
1228 case DRSUAPI_ATTRIBUTE_subClassOf:
1229 case DRSUAPI_ATTRIBUTE_auxiliaryClass:
1230 case DRSUAPI_ATTRIBUTE_systemAuxiliaryClass:
1231 case DRSUAPI_ATTRIBUTE_systemPossSuperiors:
1232 case DRSUAPI_ATTRIBUTE_possSuperiors:
1233 return _dsdb_syntax_OID_obj_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
1234 case DRSUAPI_ATTRIBUTE_systemMustContain:
1235 case DRSUAPI_ATTRIBUTE_systemMayContain:
1236 case DRSUAPI_ATTRIBUTE_mustContain:
1237 case DRSUAPI_ATTRIBUTE_rDNAttId:
1238 case DRSUAPI_ATTRIBUTE_transportAddressAttribute:
1239 case DRSUAPI_ATTRIBUTE_mayContain:
1240 return _dsdb_syntax_OID_attr_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
1241 case DRSUAPI_ATTRIBUTE_governsID:
1242 case DRSUAPI_ATTRIBUTE_attributeID:
1243 case DRSUAPI_ATTRIBUTE_attributeSyntax:
1244 return _dsdb_syntax_OID_oid_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
1247 DEBUG(0,(__location__ ": Unknown handling for attributeID_id for %s\n",
1248 attr->lDAPDisplayName));
1249 return _dsdb_syntax_auto_OID_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
1252 static WERROR dsdb_syntax_OID_ldb_to_drsuapi(struct ldb_context *ldb,
1253 const struct dsdb_schema *schema,
1254 const struct dsdb_attribute *attr,
1255 const struct ldb_message_element *in,
1256 TALLOC_CTX *mem_ctx,
1257 struct drsuapi_DsReplicaAttribute *out)
1259 if (attr->attributeID_id == 0xFFFFFFFF) {
1260 return WERR_FOOBAR;
1263 switch (attr->attributeID_id) {
1264 case DRSUAPI_ATTRIBUTE_objectClass:
1265 case DRSUAPI_ATTRIBUTE_subClassOf:
1266 case DRSUAPI_ATTRIBUTE_auxiliaryClass:
1267 case DRSUAPI_ATTRIBUTE_systemAuxiliaryClass:
1268 case DRSUAPI_ATTRIBUTE_systemPossSuperiors:
1269 case DRSUAPI_ATTRIBUTE_possSuperiors:
1270 return _dsdb_syntax_OID_obj_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
1271 case DRSUAPI_ATTRIBUTE_systemMustContain:
1272 case DRSUAPI_ATTRIBUTE_systemMayContain:
1273 case DRSUAPI_ATTRIBUTE_mustContain:
1274 case DRSUAPI_ATTRIBUTE_rDNAttId:
1275 case DRSUAPI_ATTRIBUTE_transportAddressAttribute:
1276 case DRSUAPI_ATTRIBUTE_mayContain:
1277 return _dsdb_syntax_OID_attr_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
1278 case DRSUAPI_ATTRIBUTE_governsID:
1279 case DRSUAPI_ATTRIBUTE_attributeID:
1280 case DRSUAPI_ATTRIBUTE_attributeSyntax:
1281 return _dsdb_syntax_OID_oid_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
1284 DEBUG(0,(__location__ ": Unknown handling for attributeID_id for %s\n",
1285 attr->lDAPDisplayName));
1287 return _dsdb_syntax_auto_OID_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
1290 static WERROR dsdb_syntax_UNICODE_drsuapi_to_ldb(struct ldb_context *ldb,
1291 const struct dsdb_schema *schema,
1292 const struct dsdb_attribute *attr,
1293 const struct drsuapi_DsReplicaAttribute *in,
1294 TALLOC_CTX *mem_ctx,
1295 struct ldb_message_element *out)
1297 uint32_t i;
1299 out->flags = 0;
1300 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1301 W_ERROR_HAVE_NO_MEMORY(out->name);
1303 out->num_values = in->value_ctr.num_values;
1304 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1305 W_ERROR_HAVE_NO_MEMORY(out->values);
1307 for (i=0; i < out->num_values; i++) {
1308 char *str;
1310 if (in->value_ctr.values[i].blob == NULL) {
1311 return WERR_FOOBAR;
1314 if (in->value_ctr.values[i].blob->length == 0) {
1315 return WERR_FOOBAR;
1318 if (!convert_string_talloc_convenience(out->values,
1319 schema->iconv_convenience,
1320 CH_UTF16, CH_UNIX,
1321 in->value_ctr.values[i].blob->data,
1322 in->value_ctr.values[i].blob->length,
1323 (void **)&str, NULL, false)) {
1324 return WERR_FOOBAR;
1327 out->values[i] = data_blob_string_const(str);
1330 return WERR_OK;
1333 static WERROR dsdb_syntax_UNICODE_ldb_to_drsuapi(struct ldb_context *ldb,
1334 const struct dsdb_schema *schema,
1335 const struct dsdb_attribute *attr,
1336 const struct ldb_message_element *in,
1337 TALLOC_CTX *mem_ctx,
1338 struct drsuapi_DsReplicaAttribute *out)
1340 uint32_t i;
1341 DATA_BLOB *blobs;
1343 if (attr->attributeID_id == 0xFFFFFFFF) {
1344 return WERR_FOOBAR;
1347 out->attid = attr->attributeID_id;
1348 out->value_ctr.num_values = in->num_values;
1349 out->value_ctr.values = talloc_array(mem_ctx,
1350 struct drsuapi_DsAttributeValue,
1351 in->num_values);
1352 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1354 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1355 W_ERROR_HAVE_NO_MEMORY(blobs);
1357 for (i=0; i < in->num_values; i++) {
1358 out->value_ctr.values[i].blob = &blobs[i];
1360 if (!convert_string_talloc_convenience(blobs,
1361 schema->iconv_convenience, CH_UNIX, CH_UTF16,
1362 in->values[i].data, in->values[i].length,
1363 (void **)&blobs[i].data, &blobs[i].length, false)) {
1364 return WERR_FOOBAR;
1368 return WERR_OK;
1371 static WERROR dsdb_syntax_UNICODE_validate_one_val(struct ldb_context *ldb,
1372 const struct dsdb_schema *schema,
1373 const struct dsdb_attribute *attr,
1374 const struct ldb_val *val)
1376 void *dst = NULL;
1377 size_t size;
1378 bool ok;
1380 if (attr->attributeID_id == 0xFFFFFFFF) {
1381 return WERR_FOOBAR;
1384 ok = convert_string_talloc_convenience(ldb,
1385 schema->iconv_convenience,
1386 CH_UNIX, CH_UTF16,
1387 val->data,
1388 val->length,
1389 (void **)&dst,
1390 &size, false);
1391 TALLOC_FREE(dst);
1392 if (!ok) {
1393 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1396 if (attr->rangeLower) {
1397 if ((size/2) < *attr->rangeLower) {
1398 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1402 if (attr->rangeUpper) {
1403 if ((size/2) > *attr->rangeUpper) {
1404 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1408 return WERR_OK;
1411 static WERROR dsdb_syntax_UNICODE_validate_ldb(struct ldb_context *ldb,
1412 const struct dsdb_schema *schema,
1413 const struct dsdb_attribute *attr,
1414 const struct ldb_message_element *in)
1416 WERROR status;
1417 uint32_t i;
1419 if (attr->attributeID_id == 0xFFFFFFFF) {
1420 return WERR_FOOBAR;
1423 for (i=0; i < in->num_values; i++) {
1424 if (in->values[i].length == 0) {
1425 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1428 status = dsdb_syntax_UNICODE_validate_one_val(ldb,
1429 schema,
1430 attr,
1431 &in->values[i]);
1432 if (!W_ERROR_IS_OK(status)) {
1433 return status;
1437 return WERR_OK;
1440 WERROR dsdb_syntax_one_DN_drsuapi_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
1441 const struct dsdb_syntax *syntax,
1442 struct smb_iconv_convenience *iconv_convenience,
1443 const DATA_BLOB *in, DATA_BLOB *out)
1445 struct drsuapi_DsReplicaObjectIdentifier3 id3;
1446 enum ndr_err_code ndr_err;
1447 DATA_BLOB guid_blob;
1448 struct ldb_dn *dn;
1449 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1450 int ret;
1451 NTSTATUS status;
1453 if (!tmp_ctx) {
1454 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1457 if (in == NULL) {
1458 talloc_free(tmp_ctx);
1459 return WERR_FOOBAR;
1462 if (in->length == 0) {
1463 talloc_free(tmp_ctx);
1464 return WERR_FOOBAR;
1468 /* windows sometimes sends an extra two pad bytes here */
1469 ndr_err = ndr_pull_struct_blob(in,
1470 tmp_ctx, iconv_convenience, &id3,
1471 (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3);
1472 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1473 status = ndr_map_error2ntstatus(ndr_err);
1474 talloc_free(tmp_ctx);
1475 return ntstatus_to_werror(status);
1478 dn = ldb_dn_new(tmp_ctx, ldb, id3.dn);
1479 if (!dn) {
1480 talloc_free(tmp_ctx);
1481 /* If this fails, it must be out of memory, as it does not do much parsing */
1482 W_ERROR_HAVE_NO_MEMORY(dn);
1485 if (!GUID_all_zero(&id3.guid)) {
1486 status = GUID_to_ndr_blob(&id3.guid, tmp_ctx, &guid_blob);
1487 if (!NT_STATUS_IS_OK(status)) {
1488 talloc_free(tmp_ctx);
1489 return ntstatus_to_werror(status);
1492 ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
1493 if (ret != LDB_SUCCESS) {
1494 talloc_free(tmp_ctx);
1495 return WERR_FOOBAR;
1497 talloc_free(guid_blob.data);
1500 if (id3.__ndr_size_sid) {
1501 DATA_BLOB sid_blob;
1502 ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, iconv_convenience, &id3.sid,
1503 (ndr_push_flags_fn_t)ndr_push_dom_sid);
1504 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1505 status = ndr_map_error2ntstatus(ndr_err);
1506 talloc_free(tmp_ctx);
1507 return ntstatus_to_werror(status);
1510 ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
1511 if (ret != LDB_SUCCESS) {
1512 talloc_free(tmp_ctx);
1513 return WERR_FOOBAR;
1517 *out = data_blob_string_const(ldb_dn_get_extended_linearized(mem_ctx, dn, 1));
1518 talloc_free(tmp_ctx);
1519 return WERR_OK;
1522 static WERROR dsdb_syntax_DN_drsuapi_to_ldb(struct ldb_context *ldb,
1523 const struct dsdb_schema *schema,
1524 const struct dsdb_attribute *attr,
1525 const struct drsuapi_DsReplicaAttribute *in,
1526 TALLOC_CTX *mem_ctx,
1527 struct ldb_message_element *out)
1529 uint32_t i;
1531 out->flags = 0;
1532 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1533 W_ERROR_HAVE_NO_MEMORY(out->name);
1535 out->num_values = in->value_ctr.num_values;
1536 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1537 W_ERROR_HAVE_NO_MEMORY(out->values);
1539 for (i=0; i < out->num_values; i++) {
1540 WERROR status = dsdb_syntax_one_DN_drsuapi_to_ldb(out->values, ldb, attr->syntax,
1541 schema->iconv_convenience,
1542 in->value_ctr.values[i].blob,
1543 &out->values[i]);
1544 if (!W_ERROR_IS_OK(status)) {
1545 return status;
1550 return WERR_OK;
1553 static WERROR dsdb_syntax_DN_ldb_to_drsuapi(struct ldb_context *ldb,
1554 const struct dsdb_schema *schema,
1555 const struct dsdb_attribute *attr,
1556 const struct ldb_message_element *in,
1557 TALLOC_CTX *mem_ctx,
1558 struct drsuapi_DsReplicaAttribute *out)
1560 uint32_t i;
1561 DATA_BLOB *blobs;
1563 if (attr->attributeID_id == 0xFFFFFFFF) {
1564 return WERR_FOOBAR;
1567 out->attid = attr->attributeID_id;
1568 out->value_ctr.num_values = in->num_values;
1569 out->value_ctr.values = talloc_array(mem_ctx,
1570 struct drsuapi_DsAttributeValue,
1571 in->num_values);
1572 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1574 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1575 W_ERROR_HAVE_NO_MEMORY(blobs);
1577 for (i=0; i < in->num_values; i++) {
1578 struct drsuapi_DsReplicaObjectIdentifier3 id3;
1579 enum ndr_err_code ndr_err;
1580 const DATA_BLOB *sid_blob;
1581 struct ldb_dn *dn;
1582 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1583 NTSTATUS status;
1585 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1587 out->value_ctr.values[i].blob = &blobs[i];
1589 dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &in->values[i]);
1591 W_ERROR_HAVE_NO_MEMORY(dn);
1593 ZERO_STRUCT(id3);
1595 status = dsdb_get_extended_dn_guid(dn, &id3.guid, "GUID");
1596 if (!NT_STATUS_IS_OK(status) &&
1597 !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1598 talloc_free(tmp_ctx);
1599 return ntstatus_to_werror(status);
1602 sid_blob = ldb_dn_get_extended_component(dn, "SID");
1603 if (sid_blob) {
1605 ndr_err = ndr_pull_struct_blob_all(sid_blob,
1606 tmp_ctx, schema->iconv_convenience, &id3.sid,
1607 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1608 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1609 status = ndr_map_error2ntstatus(ndr_err);
1610 talloc_free(tmp_ctx);
1611 return ntstatus_to_werror(status);
1615 id3.dn = ldb_dn_get_linearized(dn);
1617 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
1618 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1619 status = ndr_map_error2ntstatus(ndr_err);
1620 talloc_free(tmp_ctx);
1621 return ntstatus_to_werror(status);
1623 talloc_free(tmp_ctx);
1626 return WERR_OK;
1629 static WERROR dsdb_syntax_DN_validate_one_val(struct ldb_context *ldb,
1630 const struct dsdb_schema *schema,
1631 const struct dsdb_attribute *attr,
1632 const struct ldb_val *val,
1633 TALLOC_CTX *mem_ctx,
1634 struct dsdb_dn **_dsdb_dn)
1636 static const char * const extended_list[] = { "GUID", "SID", NULL };
1637 enum ndr_err_code ndr_err;
1638 struct GUID guid;
1639 struct dom_sid sid;
1640 const DATA_BLOB *sid_blob;
1641 struct dsdb_dn *dsdb_dn;
1642 struct ldb_dn *dn;
1643 char *dn_str;
1644 struct ldb_dn *dn2;
1645 char *dn2_str;
1646 int num_components;
1647 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1648 NTSTATUS status;
1650 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1652 if (attr->attributeID_id == 0xFFFFFFFF) {
1653 return WERR_FOOBAR;
1656 dsdb_dn = dsdb_dn_parse(tmp_ctx, ldb, val,
1657 attr->syntax->ldap_oid);
1658 if (!dsdb_dn) {
1659 talloc_free(tmp_ctx);
1660 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1662 dn = dsdb_dn->dn;
1664 dn2 = ldb_dn_copy(tmp_ctx, dn);
1665 if (dn == NULL) {
1666 talloc_free(tmp_ctx);
1667 return WERR_NOMEM;
1670 num_components = ldb_dn_get_comp_num(dn);
1672 status = dsdb_get_extended_dn_guid(dn, &guid, "GUID");
1673 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1674 num_components++;
1675 } else if (!NT_STATUS_IS_OK(status)) {
1676 talloc_free(tmp_ctx);
1677 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1680 sid_blob = ldb_dn_get_extended_component(dn, "SID");
1681 if (sid_blob) {
1682 num_components++;
1683 ndr_err = ndr_pull_struct_blob_all(sid_blob,
1684 tmp_ctx,
1685 schema->iconv_convenience,
1686 &sid,
1687 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1688 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1689 talloc_free(tmp_ctx);
1690 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1694 /* Do not allow links to the RootDSE */
1695 if (num_components == 0) {
1696 talloc_free(tmp_ctx);
1697 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1701 * We need to check that only "GUID" and "SID" are
1702 * specified as extended components, we do that
1703 * by comparing the dn's after removing all components
1704 * from one dn and only the allowed subset from the other
1705 * one.
1707 ldb_dn_extended_filter(dn, extended_list);
1708 ldb_dn_remove_extended_components(dn2);
1710 dn_str = ldb_dn_get_extended_linearized(tmp_ctx, dn, 0);
1711 if (dn_str == NULL) {
1712 talloc_free(tmp_ctx);
1713 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1715 dn2_str = ldb_dn_get_extended_linearized(tmp_ctx, dn2, 0);
1716 if (dn2_str == NULL) {
1717 talloc_free(tmp_ctx);
1718 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1721 if (strcmp(dn_str, dn2_str) != 0) {
1722 talloc_free(tmp_ctx);
1723 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1726 *_dsdb_dn = talloc_move(mem_ctx, &dsdb_dn);
1727 talloc_free(tmp_ctx);
1728 return WERR_OK;
1731 static WERROR dsdb_syntax_DN_validate_ldb(struct ldb_context *ldb,
1732 const struct dsdb_schema *schema,
1733 const struct dsdb_attribute *attr,
1734 const struct ldb_message_element *in)
1736 uint32_t i;
1738 if (attr->attributeID_id == 0xFFFFFFFF) {
1739 return WERR_FOOBAR;
1742 for (i=0; i < in->num_values; i++) {
1743 WERROR status;
1744 struct dsdb_dn *dsdb_dn;
1745 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1746 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1748 status = dsdb_syntax_DN_validate_one_val(ldb,
1749 schema,
1750 attr,
1751 &in->values[i],
1752 tmp_ctx, &dsdb_dn);
1753 if (!W_ERROR_IS_OK(status)) {
1754 talloc_free(tmp_ctx);
1755 return status;
1758 if (dsdb_dn->dn_format != DSDB_NORMAL_DN) {
1759 talloc_free(tmp_ctx);
1760 return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
1763 talloc_free(tmp_ctx);
1766 return WERR_OK;
1769 static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(struct ldb_context *ldb,
1770 const struct dsdb_schema *schema,
1771 const struct dsdb_attribute *attr,
1772 const struct drsuapi_DsReplicaAttribute *in,
1773 TALLOC_CTX *mem_ctx,
1774 struct ldb_message_element *out)
1776 uint32_t i;
1777 int ret;
1779 out->flags = 0;
1780 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1781 W_ERROR_HAVE_NO_MEMORY(out->name);
1783 out->num_values = in->value_ctr.num_values;
1784 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1785 W_ERROR_HAVE_NO_MEMORY(out->values);
1787 for (i=0; i < out->num_values; i++) {
1788 struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
1789 enum ndr_err_code ndr_err;
1790 DATA_BLOB guid_blob;
1791 struct ldb_dn *dn;
1792 struct dsdb_dn *dsdb_dn;
1793 NTSTATUS status;
1794 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1795 if (!tmp_ctx) {
1796 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1799 if (in->value_ctr.values[i].blob == NULL) {
1800 talloc_free(tmp_ctx);
1801 return WERR_FOOBAR;
1804 if (in->value_ctr.values[i].blob->length == 0) {
1805 talloc_free(tmp_ctx);
1806 return WERR_FOOBAR;
1810 /* windows sometimes sends an extra two pad bytes here */
1811 ndr_err = ndr_pull_struct_blob(in->value_ctr.values[i].blob,
1812 tmp_ctx, schema->iconv_convenience, &id3,
1813 (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3Binary);
1814 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1815 status = ndr_map_error2ntstatus(ndr_err);
1816 talloc_free(tmp_ctx);
1817 return ntstatus_to_werror(status);
1820 dn = ldb_dn_new(tmp_ctx, ldb, id3.dn);
1821 if (!dn) {
1822 talloc_free(tmp_ctx);
1823 /* If this fails, it must be out of memory, as it does not do much parsing */
1824 W_ERROR_HAVE_NO_MEMORY(dn);
1827 status = GUID_to_ndr_blob(&id3.guid, tmp_ctx, &guid_blob);
1828 if (!NT_STATUS_IS_OK(status)) {
1829 talloc_free(tmp_ctx);
1830 return ntstatus_to_werror(status);
1833 ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
1834 if (ret != LDB_SUCCESS) {
1835 talloc_free(tmp_ctx);
1836 return WERR_FOOBAR;
1839 talloc_free(guid_blob.data);
1841 if (id3.__ndr_size_sid) {
1842 DATA_BLOB sid_blob;
1843 ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, schema->iconv_convenience, &id3.sid,
1844 (ndr_push_flags_fn_t)ndr_push_dom_sid);
1845 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1846 status = ndr_map_error2ntstatus(ndr_err);
1847 talloc_free(tmp_ctx);
1848 return ntstatus_to_werror(status);
1851 ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
1852 if (ret != LDB_SUCCESS) {
1853 talloc_free(tmp_ctx);
1854 return WERR_FOOBAR;
1858 /* set binary stuff */
1859 dsdb_dn = dsdb_dn_construct(tmp_ctx, dn, id3.binary, attr->syntax->ldap_oid);
1860 if (!dsdb_dn) {
1861 /* If this fails, it must be out of memory, we know the ldap_oid is valid */
1862 talloc_free(tmp_ctx);
1863 W_ERROR_HAVE_NO_MEMORY(dsdb_dn);
1865 out->values[i] = data_blob_string_const(dsdb_dn_get_extended_linearized(out->values, dsdb_dn, 1));
1866 talloc_free(tmp_ctx);
1869 return WERR_OK;
1872 static WERROR dsdb_syntax_DN_BINARY_ldb_to_drsuapi(struct ldb_context *ldb,
1873 const struct dsdb_schema *schema,
1874 const struct dsdb_attribute *attr,
1875 const struct ldb_message_element *in,
1876 TALLOC_CTX *mem_ctx,
1877 struct drsuapi_DsReplicaAttribute *out)
1879 uint32_t i;
1880 DATA_BLOB *blobs;
1882 if (attr->attributeID_id == 0xFFFFFFFF) {
1883 return WERR_FOOBAR;
1886 out->attid = attr->attributeID_id;
1887 out->value_ctr.num_values = in->num_values;
1888 out->value_ctr.values = talloc_array(mem_ctx,
1889 struct drsuapi_DsAttributeValue,
1890 in->num_values);
1891 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1893 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1894 W_ERROR_HAVE_NO_MEMORY(blobs);
1896 for (i=0; i < in->num_values; i++) {
1897 struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
1898 enum ndr_err_code ndr_err;
1899 const DATA_BLOB *sid_blob;
1900 struct dsdb_dn *dsdb_dn;
1901 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1902 NTSTATUS status;
1904 W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1906 out->value_ctr.values[i].blob = &blobs[i];
1908 dsdb_dn = dsdb_dn_parse(tmp_ctx, ldb, &in->values[i], attr->syntax->ldap_oid);
1910 if (!dsdb_dn) {
1911 talloc_free(tmp_ctx);
1912 return ntstatus_to_werror(NT_STATUS_INVALID_PARAMETER);
1915 ZERO_STRUCT(id3);
1917 status = dsdb_get_extended_dn_guid(dsdb_dn->dn, &id3.guid, "GUID");
1918 if (!NT_STATUS_IS_OK(status) &&
1919 !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1920 talloc_free(tmp_ctx);
1921 return ntstatus_to_werror(status);
1924 sid_blob = ldb_dn_get_extended_component(dsdb_dn->dn, "SID");
1925 if (sid_blob) {
1927 ndr_err = ndr_pull_struct_blob_all(sid_blob,
1928 tmp_ctx, schema->iconv_convenience, &id3.sid,
1929 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1930 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1931 status = ndr_map_error2ntstatus(ndr_err);
1932 talloc_free(tmp_ctx);
1933 return ntstatus_to_werror(status);
1937 id3.dn = ldb_dn_get_linearized(dsdb_dn->dn);
1939 /* get binary stuff */
1940 id3.binary = dsdb_dn->extra_part;
1942 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3Binary);
1943 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1944 status = ndr_map_error2ntstatus(ndr_err);
1945 talloc_free(tmp_ctx);
1946 return ntstatus_to_werror(status);
1948 talloc_free(tmp_ctx);
1951 return WERR_OK;
1954 static WERROR dsdb_syntax_DN_STRING_drsuapi_to_ldb(struct ldb_context *ldb,
1955 const struct dsdb_schema *schema,
1956 const struct dsdb_attribute *attr,
1957 const struct drsuapi_DsReplicaAttribute *in,
1958 TALLOC_CTX *mem_ctx,
1959 struct ldb_message_element *out)
1961 return dsdb_syntax_DN_BINARY_drsuapi_to_ldb(ldb,
1962 schema,
1963 attr,
1965 mem_ctx,
1966 out);
1969 static WERROR dsdb_syntax_DN_STRING_ldb_to_drsuapi(struct ldb_context *ldb,
1970 const struct dsdb_schema *schema,
1971 const struct dsdb_attribute *attr,
1972 const struct ldb_message_element *in,
1973 TALLOC_CTX *mem_ctx,
1974 struct drsuapi_DsReplicaAttribute *out)
1976 return dsdb_syntax_DN_BINARY_ldb_to_drsuapi(ldb,
1977 schema,
1978 attr,
1980 mem_ctx,
1981 out);
1984 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb(struct ldb_context *ldb,
1985 const struct dsdb_schema *schema,
1986 const struct dsdb_attribute *attr,
1987 const struct drsuapi_DsReplicaAttribute *in,
1988 TALLOC_CTX *mem_ctx,
1989 struct ldb_message_element *out)
1991 uint32_t i;
1993 out->flags = 0;
1994 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1995 W_ERROR_HAVE_NO_MEMORY(out->name);
1997 out->num_values = in->value_ctr.num_values;
1998 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1999 W_ERROR_HAVE_NO_MEMORY(out->values);
2001 for (i=0; i < out->num_values; i++) {
2002 uint32_t len;
2003 char *str;
2005 if (in->value_ctr.values[i].blob == NULL) {
2006 return WERR_FOOBAR;
2009 if (in->value_ctr.values[i].blob->length < 4) {
2010 return WERR_FOOBAR;
2013 len = IVAL(in->value_ctr.values[i].blob->data, 0);
2015 if (len != in->value_ctr.values[i].blob->length) {
2016 return WERR_FOOBAR;
2019 if (!convert_string_talloc_convenience(out->values, schema->iconv_convenience, CH_UTF16, CH_UNIX,
2020 in->value_ctr.values[i].blob->data+4,
2021 in->value_ctr.values[i].blob->length-4,
2022 (void **)&str, NULL, false)) {
2023 return WERR_FOOBAR;
2026 out->values[i] = data_blob_string_const(str);
2029 return WERR_OK;
2032 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi(struct ldb_context *ldb,
2033 const struct dsdb_schema *schema,
2034 const struct dsdb_attribute *attr,
2035 const struct ldb_message_element *in,
2036 TALLOC_CTX *mem_ctx,
2037 struct drsuapi_DsReplicaAttribute *out)
2039 uint32_t i;
2040 DATA_BLOB *blobs;
2042 if (attr->attributeID_id == 0xFFFFFFFF) {
2043 return WERR_FOOBAR;
2046 out->attid = attr->attributeID_id;
2047 out->value_ctr.num_values = in->num_values;
2048 out->value_ctr.values = talloc_array(mem_ctx,
2049 struct drsuapi_DsAttributeValue,
2050 in->num_values);
2051 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
2053 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
2054 W_ERROR_HAVE_NO_MEMORY(blobs);
2056 for (i=0; i < in->num_values; i++) {
2057 uint8_t *data;
2058 size_t ret;
2060 out->value_ctr.values[i].blob = &blobs[i];
2062 if (!convert_string_talloc_convenience(blobs, schema->iconv_convenience, CH_UNIX, CH_UTF16,
2063 in->values[i].data,
2064 in->values[i].length,
2065 (void **)&data, &ret, false)) {
2066 return WERR_FOOBAR;
2069 blobs[i] = data_blob_talloc(blobs, NULL, 4 + ret);
2070 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
2072 SIVAL(blobs[i].data, 0, 4 + ret);
2074 if (ret > 0) {
2075 memcpy(blobs[i].data + 4, data, ret);
2076 talloc_free(data);
2080 return WERR_OK;
2083 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_validate_ldb(struct ldb_context *ldb,
2084 const struct dsdb_schema *schema,
2085 const struct dsdb_attribute *attr,
2086 const struct ldb_message_element *in)
2088 return dsdb_syntax_UNICODE_validate_ldb(ldb,
2089 schema,
2090 attr,
2091 in);
2094 #define OMOBJECTCLASS(val) { .length = sizeof(val) - 1, .data = discard_const_p(uint8_t, val) }
2096 static const struct dsdb_syntax dsdb_syntaxes[] = {
2098 .name = "Boolean",
2099 .ldap_oid = LDB_SYNTAX_BOOLEAN,
2100 .oMSyntax = 1,
2101 .attributeSyntax_oid = "2.5.5.8",
2102 .drsuapi_to_ldb = dsdb_syntax_BOOL_drsuapi_to_ldb,
2103 .ldb_to_drsuapi = dsdb_syntax_BOOL_ldb_to_drsuapi,
2104 .validate_ldb = dsdb_syntax_BOOL_validate_ldb,
2105 .equality = "booleanMatch",
2106 .comment = "Boolean"
2108 .name = "Integer",
2109 .ldap_oid = LDB_SYNTAX_INTEGER,
2110 .oMSyntax = 2,
2111 .attributeSyntax_oid = "2.5.5.9",
2112 .drsuapi_to_ldb = dsdb_syntax_INT32_drsuapi_to_ldb,
2113 .ldb_to_drsuapi = dsdb_syntax_INT32_ldb_to_drsuapi,
2114 .validate_ldb = dsdb_syntax_INT32_validate_ldb,
2115 .equality = "integerMatch",
2116 .comment = "Integer",
2117 .ldb_syntax = LDB_SYNTAX_SAMBA_INT32
2119 .name = "String(Octet)",
2120 .ldap_oid = LDB_SYNTAX_OCTET_STRING,
2121 .oMSyntax = 4,
2122 .attributeSyntax_oid = "2.5.5.10",
2123 .drsuapi_to_ldb = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2124 .ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2125 .validate_ldb = dsdb_syntax_DATA_BLOB_validate_ldb,
2126 .equality = "octetStringMatch",
2127 .comment = "Octet String",
2129 .name = "String(Sid)",
2130 .ldap_oid = LDB_SYNTAX_OCTET_STRING,
2131 .oMSyntax = 4,
2132 .attributeSyntax_oid = "2.5.5.17",
2133 .drsuapi_to_ldb = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2134 .ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2135 .validate_ldb = dsdb_syntax_DATA_BLOB_validate_ldb,
2136 .equality = "octetStringMatch",
2137 .comment = "Octet String - Security Identifier (SID)",
2138 .ldb_syntax = LDB_SYNTAX_SAMBA_SID
2140 .name = "String(Object-Identifier)",
2141 .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.38",
2142 .oMSyntax = 6,
2143 .attributeSyntax_oid = "2.5.5.2",
2144 .drsuapi_to_ldb = dsdb_syntax_OID_drsuapi_to_ldb,
2145 .ldb_to_drsuapi = dsdb_syntax_OID_ldb_to_drsuapi,
2146 .validate_ldb = dsdb_syntax_ALLOW_validate_ldb,
2147 .equality = "caseIgnoreMatch", /* Would use "objectIdentifierMatch" but most are ldap attribute/class names */
2148 .comment = "OID String",
2149 .ldb_syntax = LDB_SYNTAX_DIRECTORY_STRING
2151 .name = "Enumeration",
2152 .ldap_oid = LDB_SYNTAX_INTEGER,
2153 .oMSyntax = 10,
2154 .attributeSyntax_oid = "2.5.5.9",
2155 .drsuapi_to_ldb = dsdb_syntax_INT32_drsuapi_to_ldb,
2156 .ldb_to_drsuapi = dsdb_syntax_INT32_ldb_to_drsuapi,
2157 .validate_ldb = dsdb_syntax_INT32_validate_ldb,
2158 .ldb_syntax = LDB_SYNTAX_SAMBA_INT32
2160 /* not used in w2k3 forest */
2161 .name = "String(Numeric)",
2162 .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.36",
2163 .oMSyntax = 18,
2164 .attributeSyntax_oid = "2.5.5.6",
2165 .drsuapi_to_ldb = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2166 .ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2167 .validate_ldb = dsdb_syntax_DATA_BLOB_validate_ldb,
2168 .equality = "numericStringMatch",
2169 .substring = "numericStringSubstringsMatch",
2170 .comment = "Numeric String",
2171 .ldb_syntax = LDB_SYNTAX_DIRECTORY_STRING,
2173 .name = "String(Printable)",
2174 .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.44",
2175 .oMSyntax = 19,
2176 .attributeSyntax_oid = "2.5.5.5",
2177 .drsuapi_to_ldb = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2178 .ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2179 .validate_ldb = dsdb_syntax_DATA_BLOB_validate_ldb,
2180 .ldb_syntax = LDB_SYNTAX_OCTET_STRING,
2182 .name = "String(Teletex)",
2183 .ldap_oid = "1.2.840.113556.1.4.905",
2184 .oMSyntax = 20,
2185 .attributeSyntax_oid = "2.5.5.4",
2186 .drsuapi_to_ldb = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2187 .ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2188 .validate_ldb = dsdb_syntax_DATA_BLOB_validate_ldb,
2189 .equality = "caseIgnoreMatch",
2190 .substring = "caseIgnoreSubstringsMatch",
2191 .comment = "Case Insensitive String",
2192 .ldb_syntax = LDB_SYNTAX_DIRECTORY_STRING,
2194 .name = "String(IA5)",
2195 .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.26",
2196 .oMSyntax = 22,
2197 .attributeSyntax_oid = "2.5.5.5",
2198 .drsuapi_to_ldb = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2199 .ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2200 .validate_ldb = dsdb_syntax_DATA_BLOB_validate_ldb,
2201 .equality = "caseExactIA5Match",
2202 .comment = "Printable String",
2203 .ldb_syntax = LDB_SYNTAX_OCTET_STRING,
2205 .name = "String(UTC-Time)",
2206 .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.53",
2207 .oMSyntax = 23,
2208 .attributeSyntax_oid = "2.5.5.11",
2209 .drsuapi_to_ldb = dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb,
2210 .ldb_to_drsuapi = dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi,
2211 .validate_ldb = dsdb_syntax_NTTIME_UTC_validate_ldb,
2212 .equality = "generalizedTimeMatch",
2213 .comment = "UTC Time",
2215 .name = "String(Generalized-Time)",
2216 .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.24",
2217 .oMSyntax = 24,
2218 .attributeSyntax_oid = "2.5.5.11",
2219 .drsuapi_to_ldb = dsdb_syntax_NTTIME_drsuapi_to_ldb,
2220 .ldb_to_drsuapi = dsdb_syntax_NTTIME_ldb_to_drsuapi,
2221 .validate_ldb = dsdb_syntax_NTTIME_validate_ldb,
2222 .equality = "generalizedTimeMatch",
2223 .comment = "Generalized Time",
2224 .ldb_syntax = LDB_SYNTAX_UTC_TIME,
2226 /* not used in w2k3 schema */
2227 .name = "String(Case Sensitive)",
2228 .ldap_oid = "1.2.840.113556.1.4.1362",
2229 .oMSyntax = 27,
2230 .attributeSyntax_oid = "2.5.5.3",
2231 .drsuapi_to_ldb = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
2232 .ldb_to_drsuapi = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
2233 .validate_ldb = dsdb_syntax_FOOBAR_validate_ldb,
2235 .name = "String(Unicode)",
2236 .ldap_oid = LDB_SYNTAX_DIRECTORY_STRING,
2237 .oMSyntax = 64,
2238 .attributeSyntax_oid = "2.5.5.12",
2239 .drsuapi_to_ldb = dsdb_syntax_UNICODE_drsuapi_to_ldb,
2240 .ldb_to_drsuapi = dsdb_syntax_UNICODE_ldb_to_drsuapi,
2241 .validate_ldb = dsdb_syntax_UNICODE_validate_ldb,
2242 .equality = "caseIgnoreMatch",
2243 .substring = "caseIgnoreSubstringsMatch",
2244 .comment = "Directory String",
2246 .name = "Interval/LargeInteger",
2247 .ldap_oid = "1.2.840.113556.1.4.906",
2248 .oMSyntax = 65,
2249 .attributeSyntax_oid = "2.5.5.16",
2250 .drsuapi_to_ldb = dsdb_syntax_INT64_drsuapi_to_ldb,
2251 .ldb_to_drsuapi = dsdb_syntax_INT64_ldb_to_drsuapi,
2252 .validate_ldb = dsdb_syntax_INT64_validate_ldb,
2253 .equality = "integerMatch",
2254 .comment = "Large Integer",
2255 .ldb_syntax = LDB_SYNTAX_INTEGER,
2257 .name = "String(NT-Sec-Desc)",
2258 .ldap_oid = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
2259 .oMSyntax = 66,
2260 .attributeSyntax_oid = "2.5.5.15",
2261 .drsuapi_to_ldb = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2262 .ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2263 .validate_ldb = dsdb_syntax_DATA_BLOB_validate_ldb,
2265 .name = "Object(DS-DN)",
2266 .ldap_oid = LDB_SYNTAX_DN,
2267 .oMSyntax = 127,
2268 .oMObjectClass = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x4a"),
2269 .attributeSyntax_oid = "2.5.5.1",
2270 .drsuapi_to_ldb = dsdb_syntax_DN_drsuapi_to_ldb,
2271 .ldb_to_drsuapi = dsdb_syntax_DN_ldb_to_drsuapi,
2272 .validate_ldb = dsdb_syntax_DN_validate_ldb,
2273 .equality = "distinguishedNameMatch",
2274 .comment = "Object(DS-DN) == a DN",
2276 .name = "Object(DN-Binary)",
2277 .ldap_oid = DSDB_SYNTAX_BINARY_DN,
2278 .oMSyntax = 127,
2279 .oMObjectClass = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0b"),
2280 .attributeSyntax_oid = "2.5.5.7",
2281 .drsuapi_to_ldb = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
2282 .ldb_to_drsuapi = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
2283 .validate_ldb = dsdb_syntax_ALLOW_validate_ldb,
2284 .equality = "octetStringMatch",
2285 .comment = "OctetString: Binary+DN",
2287 /* not used in w2k3 schema, but used in Exchange schema*/
2288 .name = "Object(OR-Name)",
2289 .ldap_oid = DSDB_SYNTAX_OR_NAME,
2290 .oMSyntax = 127,
2291 .oMObjectClass = OMOBJECTCLASS("\x56\x06\x01\x02\x05\x0b\x1D"),
2292 .attributeSyntax_oid = "2.5.5.7",
2293 .drsuapi_to_ldb = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
2294 .ldb_to_drsuapi = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
2295 .validate_ldb = dsdb_syntax_ALLOW_validate_ldb,
2296 .equality = "caseIgnoreMatch",
2297 .ldb_syntax = LDB_SYNTAX_DN,
2300 * TODO: verify if DATA_BLOB is correct here...!
2302 * repsFrom and repsTo are the only attributes using
2303 * this attribute syntax, but they're not replicated...
2305 .name = "Object(Replica-Link)",
2306 .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.40",
2307 .oMSyntax = 127,
2308 .oMObjectClass = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x06"),
2309 .attributeSyntax_oid = "2.5.5.10",
2310 .drsuapi_to_ldb = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
2311 .ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
2312 .validate_ldb = dsdb_syntax_DATA_BLOB_validate_ldb,
2314 .name = "Object(Presentation-Address)",
2315 .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.43",
2316 .oMSyntax = 127,
2317 .oMObjectClass = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x5c"),
2318 .attributeSyntax_oid = "2.5.5.13",
2319 .drsuapi_to_ldb = dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb,
2320 .ldb_to_drsuapi = dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi,
2321 .validate_ldb = dsdb_syntax_PRESENTATION_ADDRESS_validate_ldb,
2322 .comment = "Presentation Address",
2323 .ldb_syntax = LDB_SYNTAX_DIRECTORY_STRING,
2325 /* not used in w2k3 schema */
2326 .name = "Object(Access-Point)",
2327 .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.2",
2328 .oMSyntax = 127,
2329 .oMObjectClass = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x3e"),
2330 .attributeSyntax_oid = "2.5.5.14",
2331 .drsuapi_to_ldb = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
2332 .ldb_to_drsuapi = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
2333 .validate_ldb = dsdb_syntax_FOOBAR_validate_ldb,
2334 .ldb_syntax = LDB_SYNTAX_DIRECTORY_STRING,
2336 /* not used in w2k3 schema */
2337 .name = "Object(DN-String)",
2338 .ldap_oid = DSDB_SYNTAX_STRING_DN,
2339 .oMSyntax = 127,
2340 .oMObjectClass = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0c"),
2341 .attributeSyntax_oid = "2.5.5.14",
2342 .drsuapi_to_ldb = dsdb_syntax_DN_STRING_drsuapi_to_ldb,
2343 .ldb_to_drsuapi = dsdb_syntax_DN_STRING_ldb_to_drsuapi,
2344 .validate_ldb = dsdb_syntax_ALLOW_validate_ldb,
2345 .equality = "octetStringMatch",
2346 .comment = "OctetString: String+DN",
2350 const struct dsdb_syntax *find_syntax_map_by_ad_oid(const char *ad_oid)
2352 int i;
2353 for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
2354 if (strcasecmp(ad_oid, dsdb_syntaxes[i].attributeSyntax_oid) == 0) {
2355 return &dsdb_syntaxes[i];
2358 return NULL;
2361 const struct dsdb_syntax *find_syntax_map_by_ad_syntax(int oMSyntax)
2363 int i;
2364 for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
2365 if (oMSyntax == dsdb_syntaxes[i].oMSyntax) {
2366 return &dsdb_syntaxes[i];
2369 return NULL;
2372 const struct dsdb_syntax *find_syntax_map_by_standard_oid(const char *standard_oid)
2374 int i;
2375 for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
2376 if (strcasecmp(standard_oid, dsdb_syntaxes[i].ldap_oid) == 0) {
2377 return &dsdb_syntaxes[i];
2380 return NULL;
2382 const struct dsdb_syntax *dsdb_syntax_for_attribute(const struct dsdb_attribute *attr)
2384 uint32_t i;
2386 for (i=0; i < ARRAY_SIZE(dsdb_syntaxes); i++) {
2387 if (attr->oMSyntax != dsdb_syntaxes[i].oMSyntax) continue;
2389 if (attr->oMObjectClass.length != dsdb_syntaxes[i].oMObjectClass.length) continue;
2391 if (attr->oMObjectClass.length) {
2392 int ret;
2393 ret = memcmp(attr->oMObjectClass.data,
2394 dsdb_syntaxes[i].oMObjectClass.data,
2395 attr->oMObjectClass.length);
2396 if (ret != 0) continue;
2399 if (strcmp(attr->attributeSyntax_oid, dsdb_syntaxes[i].attributeSyntax_oid) != 0) continue;
2401 return &dsdb_syntaxes[i];
2404 return NULL;
2407 WERROR dsdb_attribute_drsuapi_to_ldb(struct ldb_context *ldb,
2408 const struct dsdb_schema *schema,
2409 const struct drsuapi_DsReplicaAttribute *in,
2410 TALLOC_CTX *mem_ctx,
2411 struct ldb_message_element *out)
2413 const struct dsdb_attribute *sa;
2415 sa = dsdb_attribute_by_attributeID_id(schema, in->attid);
2416 if (!sa) {
2417 return WERR_FOOBAR;
2420 return sa->syntax->drsuapi_to_ldb(ldb, schema, sa, in, mem_ctx, out);
2423 WERROR dsdb_attribute_ldb_to_drsuapi(struct ldb_context *ldb,
2424 const struct dsdb_schema *schema,
2425 const struct ldb_message_element *in,
2426 TALLOC_CTX *mem_ctx,
2427 struct drsuapi_DsReplicaAttribute *out)
2429 const struct dsdb_attribute *sa;
2431 sa = dsdb_attribute_by_lDAPDisplayName(schema, in->name);
2432 if (!sa) {
2433 return WERR_FOOBAR;
2436 return sa->syntax->ldb_to_drsuapi(ldb, schema, sa, in, mem_ctx, out);
2439 WERROR dsdb_attribute_validate_ldb(struct ldb_context *ldb,
2440 const struct dsdb_schema *schema,
2441 const struct ldb_message_element *in)
2443 const struct dsdb_attribute *sa;
2445 sa = dsdb_attribute_by_lDAPDisplayName(schema, in->name);
2446 if (!sa) {
2447 return WERR_DS_ATTRIBUTE_TYPE_UNDEFINED;
2450 return sa->syntax->validate_ldb(ldb, schema, sa, in);