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/util/charset/charset.h"
29 #include "librpc/ndr/libndr.h"
31 static WERROR dsdb_syntax_FOOBAR_drsuapi_to_ldb(const struct dsdb_schema *schema,
32 const struct dsdb_attribute *attr,
33 const struct drsuapi_DsReplicaAttribute *in,
35 struct ldb_message_element *out)
40 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
41 W_ERROR_HAVE_NO_MEMORY(out->name);
43 out->num_values = in->value_ctr.num_values;
44 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
45 W_ERROR_HAVE_NO_MEMORY(out->values);
47 for (i=0; i < out->num_values; i++) {
50 if (in->value_ctr.values[i].blob == NULL) {
54 str = talloc_asprintf(out->values, "%s: not implemented",
56 W_ERROR_HAVE_NO_MEMORY(str);
58 out->values[i] = data_blob_string_const(str);
64 static WERROR dsdb_syntax_FOOBAR_ldb_to_drsuapi(const struct dsdb_schema *schema,
65 const struct dsdb_attribute *attr,
66 const struct ldb_message_element *in,
68 struct drsuapi_DsReplicaAttribute *out)
73 static WERROR dsdb_syntax_BOOL_drsuapi_to_ldb(const struct dsdb_schema *schema,
74 const struct dsdb_attribute *attr,
75 const struct drsuapi_DsReplicaAttribute *in,
77 struct ldb_message_element *out)
82 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
83 W_ERROR_HAVE_NO_MEMORY(out->name);
85 out->num_values = in->value_ctr.num_values;
86 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
87 W_ERROR_HAVE_NO_MEMORY(out->values);
89 for (i=0; i < out->num_values; i++) {
93 if (in->value_ctr.values[i].blob == NULL) {
97 if (in->value_ctr.values[i].blob->length != 4) {
101 v = IVAL(in->value_ctr.values[i].blob->data, 0);
104 str = talloc_strdup(out->values, "TRUE");
105 W_ERROR_HAVE_NO_MEMORY(str);
107 str = talloc_strdup(out->values, "FALSE");
108 W_ERROR_HAVE_NO_MEMORY(str);
111 out->values[i] = data_blob_string_const(str);
117 static WERROR dsdb_syntax_BOOL_ldb_to_drsuapi(const struct dsdb_schema *schema,
118 const struct dsdb_attribute *attr,
119 const struct ldb_message_element *in,
121 struct drsuapi_DsReplicaAttribute *out)
126 if (attr->attributeID_id == 0xFFFFFFFF) {
130 out->attid = attr->attributeID_id;
131 out->value_ctr.num_values = in->num_values;
132 out->value_ctr.values = talloc_array(mem_ctx,
133 struct drsuapi_DsAttributeValue,
135 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
137 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
138 W_ERROR_HAVE_NO_MEMORY(blobs);
140 for (i=0; i < in->num_values; i++) {
141 out->value_ctr.values[i].blob = &blobs[i];
143 blobs[i] = data_blob_talloc(blobs, NULL, 4);
144 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
146 if (strcmp("TRUE", (const char *)in->values[i].data) == 0) {
147 SIVAL(blobs[i].data, 0, 0x00000001);
148 } else if (strcmp("FALSE", (const char *)in->values[i].data) == 0) {
149 SIVAL(blobs[i].data, 0, 0x00000000);
158 static WERROR dsdb_syntax_INT32_drsuapi_to_ldb(const struct dsdb_schema *schema,
159 const struct dsdb_attribute *attr,
160 const struct drsuapi_DsReplicaAttribute *in,
162 struct ldb_message_element *out)
167 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
168 W_ERROR_HAVE_NO_MEMORY(out->name);
170 out->num_values = in->value_ctr.num_values;
171 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
172 W_ERROR_HAVE_NO_MEMORY(out->values);
174 for (i=0; i < out->num_values; i++) {
178 if (in->value_ctr.values[i].blob == NULL) {
182 if (in->value_ctr.values[i].blob->length != 4) {
186 v = IVALS(in->value_ctr.values[i].blob->data, 0);
188 str = talloc_asprintf(out->values, "%d", v);
189 W_ERROR_HAVE_NO_MEMORY(str);
191 out->values[i] = data_blob_string_const(str);
197 static WERROR dsdb_syntax_INT32_ldb_to_drsuapi(const struct dsdb_schema *schema,
198 const struct dsdb_attribute *attr,
199 const struct ldb_message_element *in,
201 struct drsuapi_DsReplicaAttribute *out)
206 if (attr->attributeID_id == 0xFFFFFFFF) {
210 out->attid = attr->attributeID_id;
211 out->value_ctr.num_values = in->num_values;
212 out->value_ctr.values = talloc_array(mem_ctx,
213 struct drsuapi_DsAttributeValue,
215 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
217 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
218 W_ERROR_HAVE_NO_MEMORY(blobs);
220 for (i=0; i < in->num_values; i++) {
223 out->value_ctr.values[i].blob = &blobs[i];
225 blobs[i] = data_blob_talloc(blobs, NULL, 4);
226 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
228 v = strtol((const char *)in->values[i].data, NULL, 10);
230 SIVALS(blobs[i].data, 0, v);
236 static WERROR dsdb_syntax_INT64_drsuapi_to_ldb(const struct dsdb_schema *schema,
237 const struct dsdb_attribute *attr,
238 const struct drsuapi_DsReplicaAttribute *in,
240 struct ldb_message_element *out)
245 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
246 W_ERROR_HAVE_NO_MEMORY(out->name);
248 out->num_values = in->value_ctr.num_values;
249 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
250 W_ERROR_HAVE_NO_MEMORY(out->values);
252 for (i=0; i < out->num_values; i++) {
256 if (in->value_ctr.values[i].blob == NULL) {
260 if (in->value_ctr.values[i].blob->length != 8) {
264 v = BVALS(in->value_ctr.values[i].blob->data, 0);
266 str = talloc_asprintf(out->values, "%lld", (long long int)v);
267 W_ERROR_HAVE_NO_MEMORY(str);
269 out->values[i] = data_blob_string_const(str);
275 static WERROR dsdb_syntax_INT64_ldb_to_drsuapi(const struct dsdb_schema *schema,
276 const struct dsdb_attribute *attr,
277 const struct ldb_message_element *in,
279 struct drsuapi_DsReplicaAttribute *out)
284 if (attr->attributeID_id == 0xFFFFFFFF) {
288 out->attid = attr->attributeID_id;
289 out->value_ctr.num_values = in->num_values;
290 out->value_ctr.values = talloc_array(mem_ctx,
291 struct drsuapi_DsAttributeValue,
293 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
295 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
296 W_ERROR_HAVE_NO_MEMORY(blobs);
298 for (i=0; i < in->num_values; i++) {
301 out->value_ctr.values[i].blob = &blobs[i];
303 blobs[i] = data_blob_talloc(blobs, NULL, 8);
304 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
306 v = strtoll((const char *)in->values[i].data, NULL, 10);
308 SBVALS(blobs[i].data, 0, v);
314 static WERROR dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb(const struct dsdb_schema *schema,
315 const struct dsdb_attribute *attr,
316 const struct drsuapi_DsReplicaAttribute *in,
318 struct ldb_message_element *out)
323 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
324 W_ERROR_HAVE_NO_MEMORY(out->name);
326 out->num_values = in->value_ctr.num_values;
327 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
328 W_ERROR_HAVE_NO_MEMORY(out->values);
330 for (i=0; i < out->num_values; i++) {
335 if (in->value_ctr.values[i].blob == NULL) {
339 if (in->value_ctr.values[i].blob->length != 8) {
343 v = BVAL(in->value_ctr.values[i].blob->data, 0);
345 t = nt_time_to_unix(v);
348 * NOTE: On a w2k3 server you can set a GeneralizedTime string
349 * via LDAP, but you get back an UTCTime string,
350 * but via DRSUAPI you get back the NTTIME_1sec value
351 * that represents the GeneralizedTime value!
353 * So if we store the UTCTime string in our ldb
354 * we'll loose information!
356 str = ldb_timestring_utc(out->values, t);
357 W_ERROR_HAVE_NO_MEMORY(str);
358 out->values[i] = data_blob_string_const(str);
364 static WERROR dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi(const struct dsdb_schema *schema,
365 const struct dsdb_attribute *attr,
366 const struct ldb_message_element *in,
368 struct drsuapi_DsReplicaAttribute *out)
373 if (attr->attributeID_id == 0xFFFFFFFF) {
377 out->attid = attr->attributeID_id;
378 out->value_ctr.num_values = in->num_values;
379 out->value_ctr.values = talloc_array(mem_ctx,
380 struct drsuapi_DsAttributeValue,
382 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
384 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
385 W_ERROR_HAVE_NO_MEMORY(blobs);
387 for (i=0; i < in->num_values; i++) {
391 out->value_ctr.values[i].blob = &blobs[i];
393 blobs[i] = data_blob_talloc(blobs, NULL, 8);
394 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
396 t = ldb_string_utc_to_time((const char *)in->values[i].data);
397 unix_to_nt_time(&v, t);
400 SBVAL(blobs[i].data, 0, v);
406 static WERROR dsdb_syntax_NTTIME_drsuapi_to_ldb(const struct dsdb_schema *schema,
407 const struct dsdb_attribute *attr,
408 const struct drsuapi_DsReplicaAttribute *in,
410 struct ldb_message_element *out)
415 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
416 W_ERROR_HAVE_NO_MEMORY(out->name);
418 out->num_values = in->value_ctr.num_values;
419 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
420 W_ERROR_HAVE_NO_MEMORY(out->values);
422 for (i=0; i < out->num_values; i++) {
427 if (in->value_ctr.values[i].blob == NULL) {
431 if (in->value_ctr.values[i].blob->length != 8) {
435 v = BVAL(in->value_ctr.values[i].blob->data, 0);
437 t = nt_time_to_unix(v);
439 str = ldb_timestring(out->values, t);
440 W_ERROR_HAVE_NO_MEMORY(str);
442 out->values[i] = data_blob_string_const(str);
448 static WERROR dsdb_syntax_NTTIME_ldb_to_drsuapi(const struct dsdb_schema *schema,
449 const struct dsdb_attribute *attr,
450 const struct ldb_message_element *in,
452 struct drsuapi_DsReplicaAttribute *out)
457 if (attr->attributeID_id == 0xFFFFFFFF) {
461 out->attid = attr->attributeID_id;
462 out->value_ctr.num_values = in->num_values;
463 out->value_ctr.values = talloc_array(mem_ctx,
464 struct drsuapi_DsAttributeValue,
466 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
468 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
469 W_ERROR_HAVE_NO_MEMORY(blobs);
471 for (i=0; i < in->num_values; i++) {
475 out->value_ctr.values[i].blob = &blobs[i];
477 blobs[i] = data_blob_talloc(blobs, NULL, 8);
478 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
480 t = ldb_string_to_time((const char *)in->values[i].data);
481 unix_to_nt_time(&v, t);
484 SBVAL(blobs[i].data, 0, v);
490 static WERROR dsdb_syntax_DATA_BLOB_drsuapi_to_ldb(const struct dsdb_schema *schema,
491 const struct dsdb_attribute *attr,
492 const struct drsuapi_DsReplicaAttribute *in,
494 struct ldb_message_element *out)
499 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
500 W_ERROR_HAVE_NO_MEMORY(out->name);
502 out->num_values = in->value_ctr.num_values;
503 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
504 W_ERROR_HAVE_NO_MEMORY(out->values);
506 for (i=0; i < out->num_values; i++) {
507 if (in->value_ctr.values[i].blob == NULL) {
511 if (in->value_ctr.values[i].blob->length == 0) {
515 out->values[i] = data_blob_dup_talloc(out->values,
516 in->value_ctr.values[i].blob);
517 W_ERROR_HAVE_NO_MEMORY(out->values[i].data);
523 static WERROR dsdb_syntax_DATA_BLOB_ldb_to_drsuapi(const struct dsdb_schema *schema,
524 const struct dsdb_attribute *attr,
525 const struct ldb_message_element *in,
527 struct drsuapi_DsReplicaAttribute *out)
532 if (attr->attributeID_id == 0xFFFFFFFF) {
536 out->attid = attr->attributeID_id;
537 out->value_ctr.num_values = in->num_values;
538 out->value_ctr.values = talloc_array(mem_ctx,
539 struct drsuapi_DsAttributeValue,
541 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
543 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
544 W_ERROR_HAVE_NO_MEMORY(blobs);
546 for (i=0; i < in->num_values; i++) {
547 out->value_ctr.values[i].blob = &blobs[i];
549 blobs[i] = data_blob_dup_talloc(blobs, &in->values[i]);
550 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
556 static WERROR _dsdb_syntax_OID_obj_drsuapi_to_ldb(const struct dsdb_schema *schema,
557 const struct dsdb_attribute *attr,
558 const struct drsuapi_DsReplicaAttribute *in,
560 struct ldb_message_element *out)
565 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
566 W_ERROR_HAVE_NO_MEMORY(out->name);
568 out->num_values = in->value_ctr.num_values;
569 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
570 W_ERROR_HAVE_NO_MEMORY(out->values);
572 for (i=0; i < out->num_values; i++) {
574 const struct dsdb_class *c;
577 if (in->value_ctr.values[i].blob == NULL) {
581 if (in->value_ctr.values[i].blob->length != 4) {
585 v = IVAL(in->value_ctr.values[i].blob->data, 0);
587 c = dsdb_class_by_governsID_id(schema, v);
592 str = talloc_strdup(out->values, c->lDAPDisplayName);
593 W_ERROR_HAVE_NO_MEMORY(str);
595 /* the values need to be reversed */
596 out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
602 static WERROR _dsdb_syntax_OID_oid_drsuapi_to_ldb(const struct dsdb_schema *schema,
603 const struct dsdb_attribute *attr,
604 const struct drsuapi_DsReplicaAttribute *in,
606 struct ldb_message_element *out)
611 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
612 W_ERROR_HAVE_NO_MEMORY(out->name);
614 out->num_values = in->value_ctr.num_values;
615 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
616 W_ERROR_HAVE_NO_MEMORY(out->values);
618 for (i=0; i < out->num_values; i++) {
623 if (in->value_ctr.values[i].blob == NULL) {
627 if (in->value_ctr.values[i].blob->length != 4) {
631 v = IVAL(in->value_ctr.values[i].blob->data, 0);
633 status = dsdb_map_int2oid(schema, v, out->values, &str);
634 W_ERROR_NOT_OK_RETURN(status);
636 out->values[i] = data_blob_string_const(str);
642 static WERROR dsdb_syntax_OID_drsuapi_to_ldb(const struct dsdb_schema *schema,
643 const struct dsdb_attribute *attr,
644 const struct drsuapi_DsReplicaAttribute *in,
646 struct ldb_message_element *out)
650 switch (attr->attributeID_id) {
651 case DRSUAPI_ATTRIBUTE_objectClass:
652 return _dsdb_syntax_OID_obj_drsuapi_to_ldb(schema, attr, in, mem_ctx, out);
653 case DRSUAPI_ATTRIBUTE_governsID:
654 case DRSUAPI_ATTRIBUTE_attributeID:
655 case DRSUAPI_ATTRIBUTE_attributeSyntax:
656 return _dsdb_syntax_OID_oid_drsuapi_to_ldb(schema, attr, in, mem_ctx, out);
660 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
661 W_ERROR_HAVE_NO_MEMORY(out->name);
663 out->num_values = in->value_ctr.num_values;
664 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
665 W_ERROR_HAVE_NO_MEMORY(out->values);
667 for (i=0; i < out->num_values; i++) {
672 if (in->value_ctr.values[i].blob == NULL) {
676 if (in->value_ctr.values[i].blob->length != 4) {
680 v = IVAL(in->value_ctr.values[i].blob->data, 0);
682 name = dsdb_lDAPDisplayName_by_id(schema, v);
687 str = talloc_strdup(out->values, name);
688 W_ERROR_HAVE_NO_MEMORY(str);
690 out->values[i] = data_blob_string_const(str);
696 static WERROR dsdb_syntax_OID_ldb_to_drsuapi(const struct dsdb_schema *schema,
697 const struct dsdb_attribute *attr,
698 const struct ldb_message_element *in,
700 struct drsuapi_DsReplicaAttribute *out)
705 if (attr->attributeID_id == 0xFFFFFFFF) {
709 switch (attr->attributeID_id) {
710 case DRSUAPI_ATTRIBUTE_objectClass:
711 case DRSUAPI_ATTRIBUTE_governsID:
712 case DRSUAPI_ATTRIBUTE_attributeID:
713 case DRSUAPI_ATTRIBUTE_attributeSyntax:
714 return dsdb_syntax_FOOBAR_ldb_to_drsuapi(schema, attr, in, mem_ctx, out);
717 out->attid = attr->attributeID_id;
718 out->value_ctr.num_values = in->num_values;
719 out->value_ctr.values = talloc_array(mem_ctx,
720 struct drsuapi_DsAttributeValue,
722 W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
724 blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
725 W_ERROR_HAVE_NO_MEMORY(blobs);
727 for (i=0; i < in->num_values; i++) {
730 out->value_ctr.values[i].blob = &blobs[i];
732 blobs[i] = data_blob_talloc(blobs, NULL, 4);
733 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
735 v = strtol((const char *)in->values[i].data, NULL, 10);
737 SIVAL(blobs[i].data, 0, v);
743 static WERROR dsdb_syntax_UNICODE_drsuapi_to_ldb(const struct dsdb_schema *schema,
744 const struct dsdb_attribute *attr,
745 const struct drsuapi_DsReplicaAttribute *in,
747 struct ldb_message_element *out)
752 out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
753 W_ERROR_HAVE_NO_MEMORY(out->name);
755 out->num_values = in->value_ctr.num_values;
756 out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
757 W_ERROR_HAVE_NO_MEMORY(out->values);
759 for (i=0; i < out->num_values; i++) {
763 if (in->value_ctr.values[i].blob == NULL) {
767 if (in->value_ctr.values[i].blob->length == 0) {
771 ret = convert_string_talloc_convenience(out->values,
772 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_convenience(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_convenience(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_convenience(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,
1326 /* not used in w2k3 schema */
1327 .name = "Object(DN-String)",
1328 .ldap_oid = "1.2.840.113556.1.4.904",
1330 .oMObjectClass = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0c"),
1331 .attributeSyntax_oid = "2.5.5.14",
1332 .drsuapi_to_ldb = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1333 .ldb_to_drsuapi = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1334 .equality = "distinguishedNameMatch",
1335 .comment = "OctetString: String+DN",
1336 .ldb_syntax = LDB_SYNTAX_DN,
1340 const struct dsdb_syntax *find_syntax_map_by_ad_oid(const char *ad_oid)
1343 for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1344 if (strcasecmp(ad_oid, dsdb_syntaxes[i].attributeSyntax_oid) == 0) {
1345 return &dsdb_syntaxes[i];
1351 const struct dsdb_syntax *find_syntax_map_by_ad_syntax(int oMSyntax)
1354 for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1355 if (oMSyntax == dsdb_syntaxes[i].oMSyntax) {
1356 return &dsdb_syntaxes[i];
1362 const struct dsdb_syntax *find_syntax_map_by_standard_oid(const char *standard_oid)
1365 for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1366 if (strcasecmp(standard_oid, dsdb_syntaxes[i].ldap_oid) == 0) {
1367 return &dsdb_syntaxes[i];
1372 const struct dsdb_syntax *dsdb_syntax_for_attribute(const struct dsdb_attribute *attr)
1376 for (i=0; i < ARRAY_SIZE(dsdb_syntaxes); i++) {
1377 if (attr->oMSyntax != dsdb_syntaxes[i].oMSyntax) continue;
1379 if (attr->oMObjectClass.length != dsdb_syntaxes[i].oMObjectClass.length) continue;
1381 if (attr->oMObjectClass.length) {
1383 ret = memcmp(attr->oMObjectClass.data,
1384 dsdb_syntaxes[i].oMObjectClass.data,
1385 attr->oMObjectClass.length);
1386 if (ret != 0) continue;
1389 if (strcmp(attr->attributeSyntax_oid, dsdb_syntaxes[i].attributeSyntax_oid) != 0) continue;
1391 return &dsdb_syntaxes[i];
1397 WERROR dsdb_attribute_drsuapi_to_ldb(const struct dsdb_schema *schema,
1398 const struct drsuapi_DsReplicaAttribute *in,
1399 TALLOC_CTX *mem_ctx,
1400 struct ldb_message_element *out)
1402 const struct dsdb_attribute *sa;
1404 sa = dsdb_attribute_by_attributeID_id(schema, in->attid);
1409 return sa->syntax->drsuapi_to_ldb(schema, sa, in, mem_ctx, out);
1412 WERROR dsdb_attribute_ldb_to_drsuapi(const struct dsdb_schema *schema,
1413 const struct ldb_message_element *in,
1414 TALLOC_CTX *mem_ctx,
1415 struct drsuapi_DsReplicaAttribute *out)
1417 const struct dsdb_attribute *sa;
1419 sa = dsdb_attribute_by_lDAPDisplayName(schema, in->name);
1424 return sa->syntax->ldb_to_drsuapi(schema, sa, in, mem_ctx, out);