2 Unix SMB/CIFS mplementation.
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/>.
24 #include "dsdb/samdb/samdb.h"
25 #include "librpc/gen_ndr/ndr_drsuapi.h"
26 #include "lib/ldb/include/ldb.h"
27 #include "system/time.h"
28 #include "lib/charset/charset.h"
29 #include "librpc/ndr/libndr.h"
30 #include "param/param.h"
32 static WERROR dsdb_syntax_FOOBAR_drsuapi_to_ldb(const struct dsdb_schema *schema,
33 const struct dsdb_attribute *attr,
34 const struct drsuapi_DsReplicaAttribute *in,
36 struct ldb_message_element *out)
41 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
42 W_ERROR_HAVE_NO_MEMORY(out->name);
44 out->num_values = in->value_ctr.num_values;
45 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
46 W_ERROR_HAVE_NO_MEMORY(out->values);
48 for (i=0; i < out->num_values; i++) {
51 if (in->value_ctr.values[i].blob == NULL) {
55 str = talloc_asprintf(out->values, "%s: not implemented",
57 W_ERROR_HAVE_NO_MEMORY(str);
59 out->values[i] = data_blob_string_const(str);
65 static WERROR dsdb_syntax_FOOBAR_ldb_to_drsuapi(const struct dsdb_schema *schema,
66 const struct dsdb_attribute *attr,
67 const struct ldb_message_element *in,
69 struct drsuapi_DsReplicaAttribute *out)
74 static WERROR dsdb_syntax_BOOL_drsuapi_to_ldb(const struct dsdb_schema *schema,
75 const struct dsdb_attribute *attr,
76 const struct drsuapi_DsReplicaAttribute *in,
78 struct ldb_message_element *out)
83 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
84 W_ERROR_HAVE_NO_MEMORY(out->name);
86 out->num_values = in->value_ctr.num_values;
87 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
88 W_ERROR_HAVE_NO_MEMORY(out->values);
90 for (i=0; i < out->num_values; i++) {
94 if (in->value_ctr.values[i].blob == NULL) {
98 if (in->value_ctr.values[i].blob->length != 4) {
102 v = IVAL(in->value_ctr.values[i].blob->data, 0);
105 str = talloc_strdup(out->values, "TRUE");
106 W_ERROR_HAVE_NO_MEMORY(str);
108 str = talloc_strdup(out->values, "FALSE");
109 W_ERROR_HAVE_NO_MEMORY(str);
112 out->values[i] = data_blob_string_const(str);
118 static WERROR dsdb_syntax_BOOL_ldb_to_drsuapi(const struct dsdb_schema *schema,
119 const struct dsdb_attribute *attr,
120 const struct ldb_message_element *in,
122 struct drsuapi_DsReplicaAttribute *out)
127 if (attr->attributeID_id == 0xFFFFFFFF) {
131 out->attid = attr->attributeID_id;
132 out->value_ctr.num_values = in->num_values;
133 out->value_ctr.values = talloc_array(mem_ctx,
134 struct drsuapi_DsAttributeValue,
136 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
138 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
139 W_ERROR_HAVE_NO_MEMORY(blobs);
141 for (i=0; i < in->num_values; i++) {
142 out->value_ctr.values[i].blob = &blobs[i];
144 blobs[i] = data_blob_talloc(blobs, NULL, 4);
145 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
147 if (strcmp("TRUE", (const char *)in->values[i].data) == 0) {
148 SIVAL(blobs[i].data, 0, 0x00000001);
149 } else if (strcmp("FALSE", (const char *)in->values[i].data) == 0) {
150 SIVAL(blobs[i].data, 0, 0x00000000);
159 static WERROR dsdb_syntax_INT32_drsuapi_to_ldb(const struct dsdb_schema *schema,
160 const struct dsdb_attribute *attr,
161 const struct drsuapi_DsReplicaAttribute *in,
163 struct ldb_message_element *out)
168 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
169 W_ERROR_HAVE_NO_MEMORY(out->name);
171 out->num_values = in->value_ctr.num_values;
172 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
173 W_ERROR_HAVE_NO_MEMORY(out->values);
175 for (i=0; i < out->num_values; i++) {
179 if (in->value_ctr.values[i].blob == NULL) {
183 if (in->value_ctr.values[i].blob->length != 4) {
187 v = IVALS(in->value_ctr.values[i].blob->data, 0);
189 str = talloc_asprintf(out->values, "%d", v);
190 W_ERROR_HAVE_NO_MEMORY(str);
192 out->values[i] = data_blob_string_const(str);
198 static WERROR dsdb_syntax_INT32_ldb_to_drsuapi(const struct dsdb_schema *schema,
199 const struct dsdb_attribute *attr,
200 const struct ldb_message_element *in,
202 struct drsuapi_DsReplicaAttribute *out)
207 if (attr->attributeID_id == 0xFFFFFFFF) {
211 out->attid = attr->attributeID_id;
212 out->value_ctr.num_values = in->num_values;
213 out->value_ctr.values = talloc_array(mem_ctx,
214 struct drsuapi_DsAttributeValue,
216 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
218 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
219 W_ERROR_HAVE_NO_MEMORY(blobs);
221 for (i=0; i < in->num_values; i++) {
224 out->value_ctr.values[i].blob = &blobs[i];
226 blobs[i] = data_blob_talloc(blobs, NULL, 4);
227 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
229 v = strtol((const char *)in->values[i].data, NULL, 10);
231 SIVALS(blobs[i].data, 0, v);
237 static WERROR dsdb_syntax_INT64_drsuapi_to_ldb(const struct dsdb_schema *schema,
238 const struct dsdb_attribute *attr,
239 const struct drsuapi_DsReplicaAttribute *in,
241 struct ldb_message_element *out)
246 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
247 W_ERROR_HAVE_NO_MEMORY(out->name);
249 out->num_values = in->value_ctr.num_values;
250 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
251 W_ERROR_HAVE_NO_MEMORY(out->values);
253 for (i=0; i < out->num_values; i++) {
257 if (in->value_ctr.values[i].blob == NULL) {
261 if (in->value_ctr.values[i].blob->length != 8) {
265 v = BVALS(in->value_ctr.values[i].blob->data, 0);
267 str = talloc_asprintf(out->values, "%lld", (long long int)v);
268 W_ERROR_HAVE_NO_MEMORY(str);
270 out->values[i] = data_blob_string_const(str);
276 static WERROR dsdb_syntax_INT64_ldb_to_drsuapi(const struct dsdb_schema *schema,
277 const struct dsdb_attribute *attr,
278 const struct ldb_message_element *in,
280 struct drsuapi_DsReplicaAttribute *out)
285 if (attr->attributeID_id == 0xFFFFFFFF) {
289 out->attid = attr->attributeID_id;
290 out->value_ctr.num_values = in->num_values;
291 out->value_ctr.values = talloc_array(mem_ctx,
292 struct drsuapi_DsAttributeValue,
294 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
296 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
297 W_ERROR_HAVE_NO_MEMORY(blobs);
299 for (i=0; i < in->num_values; i++) {
302 out->value_ctr.values[i].blob = &blobs[i];
304 blobs[i] = data_blob_talloc(blobs, NULL, 8);
305 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
307 v = strtoll((const char *)in->values[i].data, NULL, 10);
309 SBVALS(blobs[i].data, 0, v);
315 static WERROR dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb(const struct dsdb_schema *schema,
316 const struct dsdb_attribute *attr,
317 const struct drsuapi_DsReplicaAttribute *in,
319 struct ldb_message_element *out)
324 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
325 W_ERROR_HAVE_NO_MEMORY(out->name);
327 out->num_values = in->value_ctr.num_values;
328 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
329 W_ERROR_HAVE_NO_MEMORY(out->values);
331 for (i=0; i < out->num_values; i++) {
336 if (in->value_ctr.values[i].blob == NULL) {
340 if (in->value_ctr.values[i].blob->length != 8) {
344 v = BVAL(in->value_ctr.values[i].blob->data, 0);
346 t = nt_time_to_unix(v);
349 * NOTE: On a w2k3 server you can set a GeneralizedTime string
350 * via LDAP, but you get back an UTCTime string,
351 * but via DRSUAPI you get back the NTTIME_1sec value
352 * that represents the GeneralizedTime value!
354 * So if we store the UTCTime string in our ldb
355 * we'll loose information!
357 str = ldb_timestring_utc(out->values, t);
358 W_ERROR_HAVE_NO_MEMORY(str);
359 out->values[i] = data_blob_string_const(str);
365 static WERROR dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi(const struct dsdb_schema *schema,
366 const struct dsdb_attribute *attr,
367 const struct ldb_message_element *in,
369 struct drsuapi_DsReplicaAttribute *out)
374 if (attr->attributeID_id == 0xFFFFFFFF) {
378 out->attid = attr->attributeID_id;
379 out->value_ctr.num_values = in->num_values;
380 out->value_ctr.values = talloc_array(mem_ctx,
381 struct drsuapi_DsAttributeValue,
383 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
385 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
386 W_ERROR_HAVE_NO_MEMORY(blobs);
388 for (i=0; i < in->num_values; i++) {
392 out->value_ctr.values[i].blob = &blobs[i];
394 blobs[i] = data_blob_talloc(blobs, NULL, 8);
395 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
397 t = ldb_string_utc_to_time((const char *)in->values[i].data);
398 unix_to_nt_time(&v, t);
401 SBVAL(blobs[i].data, 0, v);
407 static WERROR dsdb_syntax_NTTIME_drsuapi_to_ldb(const struct dsdb_schema *schema,
408 const struct dsdb_attribute *attr,
409 const struct drsuapi_DsReplicaAttribute *in,
411 struct ldb_message_element *out)
416 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
417 W_ERROR_HAVE_NO_MEMORY(out->name);
419 out->num_values = in->value_ctr.num_values;
420 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
421 W_ERROR_HAVE_NO_MEMORY(out->values);
423 for (i=0; i < out->num_values; i++) {
428 if (in->value_ctr.values[i].blob == NULL) {
432 if (in->value_ctr.values[i].blob->length != 8) {
436 v = BVAL(in->value_ctr.values[i].blob->data, 0);
438 t = nt_time_to_unix(v);
440 str = ldb_timestring(out->values, t);
441 W_ERROR_HAVE_NO_MEMORY(str);
443 out->values[i] = data_blob_string_const(str);
449 static WERROR dsdb_syntax_NTTIME_ldb_to_drsuapi(const struct dsdb_schema *schema,
450 const struct dsdb_attribute *attr,
451 const struct ldb_message_element *in,
453 struct drsuapi_DsReplicaAttribute *out)
458 if (attr->attributeID_id == 0xFFFFFFFF) {
462 out->attid = attr->attributeID_id;
463 out->value_ctr.num_values = in->num_values;
464 out->value_ctr.values = talloc_array(mem_ctx,
465 struct drsuapi_DsAttributeValue,
467 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
469 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
470 W_ERROR_HAVE_NO_MEMORY(blobs);
472 for (i=0; i < in->num_values; i++) {
476 out->value_ctr.values[i].blob = &blobs[i];
478 blobs[i] = data_blob_talloc(blobs, NULL, 8);
479 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
481 t = ldb_string_to_time((const char *)in->values[i].data);
482 unix_to_nt_time(&v, t);
485 SBVAL(blobs[i].data, 0, v);
491 static WERROR dsdb_syntax_DATA_BLOB_drsuapi_to_ldb(const struct dsdb_schema *schema,
492 const struct dsdb_attribute *attr,
493 const struct drsuapi_DsReplicaAttribute *in,
495 struct ldb_message_element *out)
500 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
501 W_ERROR_HAVE_NO_MEMORY(out->name);
503 out->num_values = in->value_ctr.num_values;
504 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
505 W_ERROR_HAVE_NO_MEMORY(out->values);
507 for (i=0; i < out->num_values; i++) {
508 if (in->value_ctr.values[i].blob == NULL) {
512 if (in->value_ctr.values[i].blob->length == 0) {
516 out->values[i] = data_blob_dup_talloc(out->values,
517 in->value_ctr.values[i].blob);
518 W_ERROR_HAVE_NO_MEMORY(out->values[i].data);
524 static WERROR dsdb_syntax_DATA_BLOB_ldb_to_drsuapi(const struct dsdb_schema *schema,
525 const struct dsdb_attribute *attr,
526 const struct ldb_message_element *in,
528 struct drsuapi_DsReplicaAttribute *out)
533 if (attr->attributeID_id == 0xFFFFFFFF) {
537 out->attid = attr->attributeID_id;
538 out->value_ctr.num_values = in->num_values;
539 out->value_ctr.values = talloc_array(mem_ctx,
540 struct drsuapi_DsAttributeValue,
542 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
544 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
545 W_ERROR_HAVE_NO_MEMORY(blobs);
547 for (i=0; i < in->num_values; i++) {
548 out->value_ctr.values[i].blob = &blobs[i];
550 blobs[i] = data_blob_dup_talloc(blobs, &in->values[i]);
551 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
557 static WERROR _dsdb_syntax_OID_obj_drsuapi_to_ldb(const struct dsdb_schema *schema,
558 const struct dsdb_attribute *attr,
559 const struct drsuapi_DsReplicaAttribute *in,
561 struct ldb_message_element *out)
566 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
567 W_ERROR_HAVE_NO_MEMORY(out->name);
569 out->num_values = in->value_ctr.num_values;
570 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
571 W_ERROR_HAVE_NO_MEMORY(out->values);
573 for (i=0; i < out->num_values; i++) {
575 const struct dsdb_class *c;
578 if (in->value_ctr.values[i].blob == NULL) {
582 if (in->value_ctr.values[i].blob->length != 4) {
586 v = IVAL(in->value_ctr.values[i].blob->data, 0);
588 c = dsdb_class_by_governsID_id(schema, v);
593 str = talloc_strdup(out->values, c->lDAPDisplayName);
594 W_ERROR_HAVE_NO_MEMORY(str);
596 /* the values need to be reversed */
597 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
603 static WERROR _dsdb_syntax_OID_oid_drsuapi_to_ldb(const struct dsdb_schema *schema,
604 const struct dsdb_attribute *attr,
605 const struct drsuapi_DsReplicaAttribute *in,
607 struct ldb_message_element *out)
612 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
613 W_ERROR_HAVE_NO_MEMORY(out->name);
615 out->num_values = in->value_ctr.num_values;
616 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
617 W_ERROR_HAVE_NO_MEMORY(out->values);
619 for (i=0; i < out->num_values; i++) {
624 if (in->value_ctr.values[i].blob == NULL) {
628 if (in->value_ctr.values[i].blob->length != 4) {
632 v = IVAL(in->value_ctr.values[i].blob->data, 0);
634 status = dsdb_map_int2oid(schema, v, out->values, &str);
635 W_ERROR_NOT_OK_RETURN(status);
637 out->values[i] = data_blob_string_const(str);
643 static WERROR dsdb_syntax_OID_drsuapi_to_ldb(const struct dsdb_schema *schema,
644 const struct dsdb_attribute *attr,
645 const struct drsuapi_DsReplicaAttribute *in,
647 struct ldb_message_element *out)
651 switch (attr->attributeID_id) {
652 case DRSUAPI_ATTRIBUTE_objectClass:
653 return _dsdb_syntax_OID_obj_drsuapi_to_ldb(schema, attr, in, mem_ctx, out);
654 case DRSUAPI_ATTRIBUTE_governsID:
655 case DRSUAPI_ATTRIBUTE_attributeID:
656 case DRSUAPI_ATTRIBUTE_attributeSyntax:
657 return _dsdb_syntax_OID_oid_drsuapi_to_ldb(schema, attr, in, mem_ctx, out);
661 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
662 W_ERROR_HAVE_NO_MEMORY(out->name);
664 out->num_values = in->value_ctr.num_values;
665 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
666 W_ERROR_HAVE_NO_MEMORY(out->values);
668 for (i=0; i < out->num_values; i++) {
673 if (in->value_ctr.values[i].blob == NULL) {
677 if (in->value_ctr.values[i].blob->length != 4) {
681 v = IVAL(in->value_ctr.values[i].blob->data, 0);
683 name = dsdb_lDAPDisplayName_by_id(schema, v);
688 str = talloc_strdup(out->values, name);
689 W_ERROR_HAVE_NO_MEMORY(str);
691 out->values[i] = data_blob_string_const(str);
697 static WERROR dsdb_syntax_OID_ldb_to_drsuapi(const struct dsdb_schema *schema,
698 const struct dsdb_attribute *attr,
699 const struct ldb_message_element *in,
701 struct drsuapi_DsReplicaAttribute *out)
706 if (attr->attributeID_id == 0xFFFFFFFF) {
710 switch (attr->attributeID_id) {
711 case DRSUAPI_ATTRIBUTE_objectClass:
712 case DRSUAPI_ATTRIBUTE_governsID:
713 case DRSUAPI_ATTRIBUTE_attributeID:
714 case DRSUAPI_ATTRIBUTE_attributeSyntax:
715 return dsdb_syntax_FOOBAR_ldb_to_drsuapi(schema, attr, in, mem_ctx, out);
718 out->attid = attr->attributeID_id;
719 out->value_ctr.num_values = in->num_values;
720 out->value_ctr.values = talloc_array(mem_ctx,
721 struct drsuapi_DsAttributeValue,
723 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
725 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
726 W_ERROR_HAVE_NO_MEMORY(blobs);
728 for (i=0; i < in->num_values; i++) {
731 out->value_ctr.values[i].blob = &blobs[i];
733 blobs[i] = data_blob_talloc(blobs, NULL, 4);
734 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
736 v = strtol((const char *)in->values[i].data, NULL, 10);
738 SIVAL(blobs[i].data, 0, v);
744 static WERROR dsdb_syntax_UNICODE_drsuapi_to_ldb(const struct dsdb_schema *schema,
745 const struct dsdb_attribute *attr,
746 const struct drsuapi_DsReplicaAttribute *in,
748 struct ldb_message_element *out)
753 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
754 W_ERROR_HAVE_NO_MEMORY(out->name);
756 out->num_values = in->value_ctr.num_values;
757 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
758 W_ERROR_HAVE_NO_MEMORY(out->values);
760 for (i=0; i < out->num_values; i++) {
764 if (in->value_ctr.values[i].blob == NULL) {
768 if (in->value_ctr.values[i].blob->length == 0) {
772 ret = convert_string_talloc(out->values, schema->iconv_convenience,
774 in->value_ctr.values[i].blob->data,
775 in->value_ctr.values[i].blob->length,
781 out->values[i] = data_blob_string_const(str);
787 static WERROR dsdb_syntax_UNICODE_ldb_to_drsuapi(const struct dsdb_schema *schema,
788 const struct dsdb_attribute *attr,
789 const struct ldb_message_element *in,
791 struct drsuapi_DsReplicaAttribute *out)
796 if (attr->attributeID_id == 0xFFFFFFFF) {
800 out->attid = attr->attributeID_id;
801 out->value_ctr.num_values = in->num_values;
802 out->value_ctr.values = talloc_array(mem_ctx,
803 struct drsuapi_DsAttributeValue,
805 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
807 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
808 W_ERROR_HAVE_NO_MEMORY(blobs);
810 for (i=0; i < in->num_values; i++) {
813 out->value_ctr.values[i].blob = &blobs[i];
815 ret = convert_string_talloc(blobs, schema->iconv_convenience, CH_UNIX, CH_UTF16,
817 in->values[i].length,
818 (void **)&blobs[i].data);
822 blobs[i].length = ret;
828 static WERROR dsdb_syntax_DN_drsuapi_to_ldb(const struct dsdb_schema *schema,
829 const struct dsdb_attribute *attr,
830 const struct drsuapi_DsReplicaAttribute *in,
832 struct ldb_message_element *out)
837 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
838 W_ERROR_HAVE_NO_MEMORY(out->name);
840 out->num_values = in->value_ctr.num_values;
841 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
842 W_ERROR_HAVE_NO_MEMORY(out->values);
844 for (i=0; i < out->num_values; i++) {
845 struct drsuapi_DsReplicaObjectIdentifier3 id3;
846 enum ndr_err_code ndr_err;
848 if (in->value_ctr.values[i].blob == NULL) {
852 if (in->value_ctr.values[i].blob->length == 0) {
856 ndr_err = ndr_pull_struct_blob_all(in->value_ctr.values[i].blob,
857 out->values, schema->iconv_convenience, &id3,
858 (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3);
859 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
860 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
861 return ntstatus_to_werror(status);
864 /* TODO: handle id3.guid and id3.sid */
865 out->values[i] = data_blob_string_const(id3.dn);
871 static WERROR dsdb_syntax_DN_ldb_to_drsuapi(const struct dsdb_schema *schema,
872 const struct dsdb_attribute *attr,
873 const struct ldb_message_element *in,
875 struct drsuapi_DsReplicaAttribute *out)
880 if (attr->attributeID_id == 0xFFFFFFFF) {
884 out->attid = attr->attributeID_id;
885 out->value_ctr.num_values = in->num_values;
886 out->value_ctr.values = talloc_array(mem_ctx,
887 struct drsuapi_DsAttributeValue,
889 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
891 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
892 W_ERROR_HAVE_NO_MEMORY(blobs);
894 for (i=0; i < in->num_values; i++) {
895 struct drsuapi_DsReplicaObjectIdentifier3 id3;
896 enum ndr_err_code ndr_err;
898 out->value_ctr.values[i].blob = &blobs[i];
900 /* TODO: handle id3.guid and id3.sid */
902 id3.dn = (const char *)in->values[i].data;
904 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
905 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
906 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
907 return ntstatus_to_werror(status);
914 static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(const struct dsdb_schema *schema,
915 const struct dsdb_attribute *attr,
916 const struct drsuapi_DsReplicaAttribute *in,
918 struct ldb_message_element *out)
923 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
924 W_ERROR_HAVE_NO_MEMORY(out->name);
926 out->num_values = in->value_ctr.num_values;
927 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
928 W_ERROR_HAVE_NO_MEMORY(out->values);
930 for (i=0; i < out->num_values; i++) {
931 struct drsuapi_DsReplicaObjectIdentifier3Binary id3b;
934 enum ndr_err_code ndr_err;
936 if (in->value_ctr.values[i].blob == NULL) {
940 if (in->value_ctr.values[i].blob->length == 0) {
944 ndr_err = ndr_pull_struct_blob_all(in->value_ctr.values[i].blob,
945 out->values, schema->iconv_convenience, &id3b,
946 (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3Binary);
947 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
948 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
949 return ntstatus_to_werror(status);
952 /* TODO: handle id3.guid and id3.sid */
953 binary = data_blob_hex_string(out->values, &id3b.binary);
954 W_ERROR_HAVE_NO_MEMORY(binary);
956 str = talloc_asprintf(out->values, "B:%u:%s:%s",
957 (unsigned int)(id3b.binary.length * 2), /* because of 2 hex chars per byte */
960 W_ERROR_HAVE_NO_MEMORY(str);
962 /* TODO: handle id3.guid and id3.sid */
963 out->values[i] = data_blob_string_const(str);
969 static WERROR dsdb_syntax_DN_BINARY_ldb_to_drsuapi(const struct dsdb_schema *schema,
970 const struct dsdb_attribute *attr,
971 const struct ldb_message_element *in,
973 struct drsuapi_DsReplicaAttribute *out)
978 if (attr->attributeID_id == 0xFFFFFFFF) {
982 out->attid = attr->attributeID_id;
983 out->value_ctr.num_values = in->num_values;
984 out->value_ctr.values = talloc_array(mem_ctx,
985 struct drsuapi_DsAttributeValue,
987 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
989 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
990 W_ERROR_HAVE_NO_MEMORY(blobs);
992 for (i=0; i < in->num_values; i++) {
993 struct drsuapi_DsReplicaObjectIdentifier3Binary id3b;
994 enum ndr_err_code ndr_err;
996 out->value_ctr.values[i].blob = &blobs[i];
998 /* TODO: handle id3b.guid and id3b.sid, id3.binary */
1000 id3b.dn = (const char *)in->values[i].data;
1001 id3b.binary = data_blob(NULL, 0);
1003 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3b,
1004 (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3Binary);
1005 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1006 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1007 return ntstatus_to_werror(status);
1014 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb(const struct dsdb_schema *schema,
1015 const struct dsdb_attribute *attr,
1016 const struct drsuapi_DsReplicaAttribute *in,
1017 TALLOC_CTX *mem_ctx,
1018 struct ldb_message_element *out)
1023 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1024 W_ERROR_HAVE_NO_MEMORY(out->name);
1026 out->num_values = in->value_ctr.num_values;
1027 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
1028 W_ERROR_HAVE_NO_MEMORY(out->values);
1030 for (i=0; i < out->num_values; i++) {
1035 if (in->value_ctr.values[i].blob == NULL) {
1039 if (in->value_ctr.values[i].blob->length < 4) {
1043 len = IVAL(in->value_ctr.values[i].blob->data, 0);
1045 if (len != in->value_ctr.values[i].blob->length) {
1049 ret = convert_string_talloc(out->values, schema->iconv_convenience, CH_UTF16, CH_UNIX,
1050 in->value_ctr.values[i].blob->data+4,
1051 in->value_ctr.values[i].blob->length-4,
1057 out->values[i] = data_blob_string_const(str);
1063 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi(const struct dsdb_schema *schema,
1064 const struct dsdb_attribute *attr,
1065 const struct ldb_message_element *in,
1066 TALLOC_CTX *mem_ctx,
1067 struct drsuapi_DsReplicaAttribute *out)
1072 if (attr->attributeID_id == 0xFFFFFFFF) {
1076 out->attid = attr->attributeID_id;
1077 out->value_ctr.num_values = in->num_values;
1078 out->value_ctr.values = talloc_array(mem_ctx,
1079 struct drsuapi_DsAttributeValue,
1081 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1083 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1084 W_ERROR_HAVE_NO_MEMORY(blobs);
1086 for (i=0; i < in->num_values; i++) {
1090 out->value_ctr.values[i].blob = &blobs[i];
1092 ret = convert_string_talloc(blobs, schema->iconv_convenience, CH_UNIX, CH_UTF16,
1094 in->values[i].length,
1100 blobs[i] = data_blob_talloc(blobs, NULL, 4 + ret);
1101 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1103 SIVAL(blobs[i].data, 0, 4 + ret);
1106 memcpy(blobs[i].data + 4, data, ret);
1114 #define OMOBJECTCLASS(val) { .length = sizeof(val) - 1, .data = discard_const_p(uint8_t, val) }
1116 static const struct dsdb_syntax dsdb_syntaxes[] = {
1119 .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.7",
1121 .attributeSyntax_oid = "2.5.5.8",
1122 .drsuapi_to_ldb = dsdb_syntax_BOOL_drsuapi_to_ldb,
1123 .ldb_to_drsuapi = dsdb_syntax_BOOL_ldb_to_drsuapi,
1124 .equality = "booleanMatch",
1125 .comment = "Boolean"
1128 .ldap_oid = LDB_SYNTAX_INTEGER,
1130 .attributeSyntax_oid = "2.5.5.9",
1131 .drsuapi_to_ldb = dsdb_syntax_INT32_drsuapi_to_ldb,
1132 .ldb_to_drsuapi = dsdb_syntax_INT32_ldb_to_drsuapi,
1133 .equality = "integerMatch",
1134 .comment = "Integer",
1136 .name = "String(Octet)",
1137 .ldap_oid = LDB_SYNTAX_OCTET_STRING,
1139 .attributeSyntax_oid = "2.5.5.10",
1140 .drsuapi_to_ldb = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1141 .ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1142 .equality = "octetStringMatch",
1143 .comment = "Octet String",
1145 .name = "String(Sid)",
1146 .ldap_oid = LDB_SYNTAX_OCTET_STRING,
1148 .attributeSyntax_oid = "2.5.5.17",
1149 .drsuapi_to_ldb = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1150 .ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1151 .equality = "octetStringMatch",
1152 .comment = "Octet String - Security Identifier (SID)",
1153 .ldb_syntax = LDB_SYNTAX_SAMBA_SID
1155 .name = "String(Object-Identifier)",
1156 .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.38",
1158 .attributeSyntax_oid = "2.5.5.2",
1159 .drsuapi_to_ldb = dsdb_syntax_OID_drsuapi_to_ldb,
1160 .ldb_to_drsuapi = dsdb_syntax_OID_ldb_to_drsuapi,
1161 .equality = "caseIgnoreMatch", /* Would use "objectIdentifierMatch" but most are ldap attribute/class names */
1162 .comment = "OID String",
1163 .ldb_syntax = LDB_SYNTAX_DIRECTORY_STRING
1165 .name = "Enumeration",
1166 .ldap_oid = LDB_SYNTAX_INTEGER,
1168 .attributeSyntax_oid = "2.5.5.9",
1169 .drsuapi_to_ldb = dsdb_syntax_INT32_drsuapi_to_ldb,
1170 .ldb_to_drsuapi = dsdb_syntax_INT32_ldb_to_drsuapi,
1172 /* not used in w2k3 forest */
1173 .name = "String(Numeric)",
1174 .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.36",
1176 .attributeSyntax_oid = "2.5.5.6",
1177 .drsuapi_to_ldb = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1178 .ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1179 .equality = "numericStringMatch",
1180 .substring = "numericStringSubstringsMatch",
1181 .comment = "Numeric String"
1183 .name = "String(Printable)",
1184 .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.44",
1186 .attributeSyntax_oid = "2.5.5.5",
1187 .drsuapi_to_ldb = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1188 .ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1190 .name = "String(Teletex)",
1191 .ldap_oid = "1.2.840.113556.1.4.905",
1193 .attributeSyntax_oid = "2.5.5.4",
1194 .drsuapi_to_ldb = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1195 .ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1196 .equality = "caseIgnoreMatch",
1197 .substring = "caseIgnoreSubstringsMatch",
1198 .comment = "Case Insensitive String",
1199 .ldb_syntax = LDB_SYNTAX_DIRECTORY_STRING,
1201 .name = "String(IA5)",
1202 .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.26",
1204 .attributeSyntax_oid = "2.5.5.5",
1205 .drsuapi_to_ldb = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1206 .ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1207 .equality = "caseExactIA5Match",
1208 .comment = "Printable String"
1210 .name = "String(UTC-Time)",
1211 .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.53",
1213 .attributeSyntax_oid = "2.5.5.11",
1214 .drsuapi_to_ldb = dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb,
1215 .ldb_to_drsuapi = dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi,
1216 .equality = "generalizedTimeMatch",
1217 .comment = "UTC Time",
1219 .name = "String(Generalized-Time)",
1220 .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.24",
1222 .attributeSyntax_oid = "2.5.5.11",
1223 .drsuapi_to_ldb = dsdb_syntax_NTTIME_drsuapi_to_ldb,
1224 .ldb_to_drsuapi = dsdb_syntax_NTTIME_ldb_to_drsuapi,
1225 .equality = "generalizedTimeMatch",
1226 .comment = "Generalized Time",
1227 .ldb_syntax = LDB_SYNTAX_UTC_TIME,
1229 /* not used in w2k3 schema */
1230 .name = "String(Case Sensitive)",
1231 .ldap_oid = "1.2.840.113556.1.4.1362",
1233 .attributeSyntax_oid = "2.5.5.3",
1234 .drsuapi_to_ldb = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1235 .ldb_to_drsuapi = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1237 .name = "String(Unicode)",
1238 .ldap_oid = LDB_SYNTAX_DIRECTORY_STRING,
1240 .attributeSyntax_oid = "2.5.5.12",
1241 .drsuapi_to_ldb = dsdb_syntax_UNICODE_drsuapi_to_ldb,
1242 .ldb_to_drsuapi = dsdb_syntax_UNICODE_ldb_to_drsuapi,
1243 .equality = "caseIgnoreMatch",
1244 .substring = "caseIgnoreSubstringsMatch",
1245 .comment = "Directory String",
1247 .name = "Interval/LargeInteger",
1248 .ldap_oid = "1.2.840.113556.1.4.906",
1250 .attributeSyntax_oid = "2.5.5.16",
1251 .drsuapi_to_ldb = dsdb_syntax_INT64_drsuapi_to_ldb,
1252 .ldb_to_drsuapi = dsdb_syntax_INT64_ldb_to_drsuapi,
1253 .equality = "integerMatch",
1254 .comment = "Large Integer",
1255 .ldb_syntax = LDB_SYNTAX_INTEGER,
1257 .name = "String(NT-Sec-Desc)",
1258 .ldap_oid = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1260 .attributeSyntax_oid = "2.5.5.15",
1261 .drsuapi_to_ldb = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1262 .ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1264 .name = "Object(DS-DN)",
1265 .ldap_oid = LDB_SYNTAX_DN,
1267 .oMObjectClass = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x4a"),
1268 .attributeSyntax_oid = "2.5.5.1",
1269 .drsuapi_to_ldb = dsdb_syntax_DN_drsuapi_to_ldb,
1270 .ldb_to_drsuapi = dsdb_syntax_DN_ldb_to_drsuapi,
1271 .equality = "distinguishedNameMatch",
1272 .comment = "Object(DS-DN) == a DN",
1274 .name = "Object(DN-Binary)",
1275 .ldap_oid = "1.2.840.113556.1.4.903",
1277 .oMObjectClass = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0b"),
1278 .attributeSyntax_oid = "2.5.5.7",
1279 .drsuapi_to_ldb = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
1280 .ldb_to_drsuapi = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
1281 .equality = "distinguishedNameMatch",
1282 .comment = "OctetString: Binary+DN",
1283 .ldb_syntax = LDB_SYNTAX_DN,
1285 /* not used in w2k3 schema */
1286 .name = "Object(OR-Name)",
1287 .ldap_oid = "1.2.840.113556.1.4.1221",
1289 .oMObjectClass = OMOBJECTCLASS("\x56\x06\x01\x02\x05\x0b\x1D"),
1290 .attributeSyntax_oid = "2.5.5.7",
1291 .drsuapi_to_ldb = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1292 .ldb_to_drsuapi = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1295 * TODO: verify if DATA_BLOB is correct here...!
1297 * repsFrom and repsTo are the only attributes using
1298 * this attribute syntax, but they're not replicated...
1300 .name = "Object(Replica-Link)",
1301 .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.40",
1303 .oMObjectClass = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x06"),
1304 .attributeSyntax_oid = "2.5.5.10",
1305 .drsuapi_to_ldb = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1306 .ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1308 .name = "Object(Presentation-Address)",
1309 .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.43",
1311 .oMObjectClass = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x5c"),
1312 .attributeSyntax_oid = "2.5.5.13",
1313 .drsuapi_to_ldb = dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb,
1314 .ldb_to_drsuapi = dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi,
1315 .comment = "Presentation Address"
1317 /* not used in w2k3 schema */
1318 .name = "Object(Access-Point)",
1319 .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.2",
1321 .oMObjectClass = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x3e"),
1322 .attributeSyntax_oid = "2.5.5.14",
1323 .drsuapi_to_ldb = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1324 .ldb_to_drsuapi = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1325 .equality = "distinguishedNameMatch",
1326 .comment = "OctetString: String+DN",
1327 .ldb_syntax = LDB_SYNTAX_DN,
1329 /* not used in w2k3 schema */
1330 .name = "Object(DN-String)",
1331 .ldap_oid = "1.2.840.113556.1.4.904",
1333 .oMObjectClass = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0c"),
1334 .attributeSyntax_oid = "2.5.5.14",
1335 .drsuapi_to_ldb = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1336 .ldb_to_drsuapi = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1337 .ldb_syntax = LDB_SYNTAX_DN,
1341 const struct dsdb_syntax *find_syntax_map_by_ad_oid(const char *ad_oid)
1344 for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1345 if (strcasecmp(ad_oid, dsdb_syntaxes[i].attributeSyntax_oid) == 0) {
1346 return &dsdb_syntaxes[i];
1352 const struct dsdb_syntax *find_syntax_map_by_ad_syntax(int oMSyntax)
1355 for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1356 if (oMSyntax == dsdb_syntaxes[i].oMSyntax) {
1357 return &dsdb_syntaxes[i];
1363 const struct dsdb_syntax *find_syntax_map_by_standard_oid(const char *standard_oid)
1366 for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1367 if (strcasecmp(standard_oid, dsdb_syntaxes[i].ldap_oid) == 0) {
1368 return &dsdb_syntaxes[i];
1373 const struct dsdb_syntax *dsdb_syntax_for_attribute(const struct dsdb_attribute *attr)
1377 for (i=0; i < ARRAY_SIZE(dsdb_syntaxes); i++) {
1378 if (attr->oMSyntax != dsdb_syntaxes[i].oMSyntax) continue;
1380 if (attr->oMObjectClass.length != dsdb_syntaxes[i].oMObjectClass.length) continue;
1382 if (attr->oMObjectClass.length) {
1384 ret = memcmp(attr->oMObjectClass.data,
1385 dsdb_syntaxes[i].oMObjectClass.data,
1386 attr->oMObjectClass.length);
1387 if (ret != 0) continue;
1390 if (strcmp(attr->attributeSyntax_oid, dsdb_syntaxes[i].attributeSyntax_oid) != 0) continue;
1392 return &dsdb_syntaxes[i];
1398 WERROR dsdb_attribute_drsuapi_to_ldb(const struct dsdb_schema *schema,
1399 const struct drsuapi_DsReplicaAttribute *in,
1400 TALLOC_CTX *mem_ctx,
1401 struct ldb_message_element *out)
1403 const struct dsdb_attribute *sa;
1405 sa = dsdb_attribute_by_attributeID_id(schema, in->attid);
1410 return sa->syntax->drsuapi_to_ldb(schema, sa, in, mem_ctx, out);
1413 WERROR dsdb_attribute_ldb_to_drsuapi(const struct dsdb_schema *schema,
1414 const struct ldb_message_element *in,
1415 TALLOC_CTX *mem_ctx,
1416 struct drsuapi_DsReplicaAttribute *out)
1418 const struct dsdb_attribute *sa;
1420 sa = dsdb_attribute_by_lDAPDisplayName(schema, in->name);
1425 return sa->syntax->ldb_to_drsuapi(schema, sa, in, mem_ctx, out);