+/*
+ convert a ldif formatted prefixMap to a NDR formatted blob
+*/
+static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
+ const struct ldb_val *in, struct ldb_val *out)
+{
+ struct prefixMapBlob *blob;
+ enum ndr_err_code ndr_err;
+ char *string, *line, *p, *oid;
+
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+
+ if (tmp_ctx == NULL) {
+ return -1;
+ }
+
+ blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
+ if (blob == NULL) {
+ talloc_free(blob);
+ return -1;
+ }
+
+ blob->version = PREFIX_MAP_VERSION_DSDB;
+
+ string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
+ if (string == NULL) {
+ talloc_free(blob);
+ return -1;
+ }
+
+ line = string;
+ while (line && line[0]) {
+ p=strchr(line, ';');
+ if (p) {
+ p[0] = '\0';
+ } else {
+ p=strchr(line, '\n');
+ if (p) {
+ p[0] = '\0';
+ }
+ }
+ /* allow a traling seperator */
+ if (line == p) {
+ break;
+ }
+
+ blob->ctr.dsdb.mappings = talloc_realloc(blob,
+ blob->ctr.dsdb.mappings,
+ struct drsuapi_DsReplicaOIDMapping,
+ blob->ctr.dsdb.num_mappings+1);
+ if (!blob->ctr.dsdb.mappings) {
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+
+ blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix = strtoul(line, &oid, 10);
+
+ if (oid[0] != ':') {
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+
+ /* we know there must be at least ":" */
+ oid++;
+
+ blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.oid
+ = talloc_strdup(blob->ctr.dsdb.mappings, oid);
+
+ blob->ctr.dsdb.num_mappings++;
+
+ /* Now look past the terminator we added above */
+ if (p) {
+ line = p + 1;
+ } else {
+ line = NULL;
+ }
+ }
+
+ ndr_err = ndr_push_struct_blob(out, mem_ctx,
+ lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
+ blob,
+ (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
+ talloc_free(tmp_ctx);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ convert a NDR formatted blob to a ldif formatted prefixMap
+*/
+static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
+ const struct ldb_val *in, struct ldb_val *out)
+{
+ struct prefixMapBlob *blob;
+ enum ndr_err_code ndr_err;
+ char *string;
+ uint32_t i;
+
+ if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
+ return ldif_write_NDR(ldb, mem_ctx, in, out,
+ sizeof(struct prefixMapBlob),
+ (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
+ (ndr_print_fn_t)ndr_print_prefixMapBlob);
+
+ }
+
+ blob = talloc(mem_ctx, struct prefixMapBlob);
+ if (blob == NULL) {
+ return -1;
+ }
+ ndr_err = ndr_pull_struct_blob_all(in, blob,
+ lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
+ blob,
+ (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ talloc_free(blob);
+ return -1;
+ }
+ if (blob->version != PREFIX_MAP_VERSION_DSDB) {
+ return -1;
+ }
+ string = talloc_strdup(mem_ctx, "");
+ if (string == NULL) {
+ return -1;
+ }
+
+ for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
+ if (i > 0) {
+ string = talloc_asprintf_append(string, ";");
+ }
+ string = talloc_asprintf_append(string, "%u:%s",
+ blob->ctr.dsdb.mappings[i].id_prefix,
+ blob->ctr.dsdb.mappings[i].oid.oid);
+ if (string == NULL) {
+ return -1;
+ }
+ }
+
+ talloc_free(blob);
+ *out = data_blob_string_const(string);
+ return 0;
+}
+
+static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
+{
+ if (v->length < 4) {
+ return true;
+ }
+
+ if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ canonicalise a prefixMap
+*/
+static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
+ const struct ldb_val *in, struct ldb_val *out)
+{
+ if (ldif_comparision_prefixMap_isString(in)) {
+ return ldif_read_prefixMap(ldb, mem_ctx, in, out);
+ }
+ return ldb_handler_copy(ldb, mem_ctx, in, out);
+}
+
+static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
+ const struct ldb_val *v1,
+ const struct ldb_val *v2)
+{
+
+ int ret, ret1, ret2;
+ struct ldb_val v1_canon, v2_canon;
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+
+ /* I could try and bail if tmp_ctx was NULL, but what return
+ * value would I use?
+ *
+ * It seems easier to continue on the NULL context
+ */
+ ret1 = ldif_canonicalise_prefixMap(ldb, tmp_ctx, v1, &v1_canon);
+ ret2 = ldif_canonicalise_prefixMap(ldb, tmp_ctx, v2, &v2_canon);
+
+ if (ret1 == LDB_SUCCESS && ret2 == LDB_SUCCESS) {
+ ret = data_blob_cmp(&v1_canon, &v2_canon);
+ } else {
+ ret = data_blob_cmp(v1, v2);
+ }
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+/* Canonicalisation of two 32-bit integers */
+static int ldif_canonicalise_int32(struct ldb_context *ldb, void *mem_ctx,
+ const struct ldb_val *in, struct ldb_val *out)
+{
+ char *end;
+ /* We've to use "strtoll" here to have the intended overflows.
+ * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
+ int32_t i = (int32_t) strtoll((char *)in->data, &end, 0);
+ if (*end != 0) {
+ return -1;
+ }
+ out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%d", i);
+ if (out->data == NULL) {
+ return -1;
+ }
+ out->length = strlen((char *)out->data);
+ return 0;
+}
+
+/* Comparison of two 32-bit integers */
+static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
+ const struct ldb_val *v1, const struct ldb_val *v2)
+{
+ /* We've to use "strtoll" here to have the intended overflows.
+ * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
+ return (int32_t) strtoll((char *)v1->data, NULL, 0)
+ - (int32_t) strtoll((char *)v2->data, NULL, 0);
+}
+
+/*
+ convert a NDR formatted blob to a ldif formatted repsFromTo
+*/
+static int ldif_write_repsFromTo(struct ldb_context *ldb, void *mem_ctx,
+ const struct ldb_val *in, struct ldb_val *out)
+{
+ return ldif_write_NDR(ldb, mem_ctx, in, out,
+ sizeof(struct repsFromToBlob),
+ (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob,
+ (ndr_print_fn_t)ndr_print_repsFromToBlob);
+}
+
+/*
+ convert a NDR formatted blob to a ldif formatted replPropertyMetaData
+*/
+static int ldif_write_replPropertyMetaData(struct ldb_context *ldb, void *mem_ctx,
+ const struct ldb_val *in, struct ldb_val *out)
+{
+ return ldif_write_NDR(ldb, mem_ctx, in, out,
+ sizeof(struct replPropertyMetaDataBlob),
+ (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob,
+ (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob);
+}
+
+/*
+ convert a NDR formatted blob to a ldif formatted replUpToDateVector
+*/
+static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
+ const struct ldb_val *in, struct ldb_val *out)
+{
+ return ldif_write_NDR(ldb, mem_ctx, in, out,
+ sizeof(struct replUpToDateVectorBlob),
+ (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob,
+ (ndr_print_fn_t)ndr_print_replUpToDateVectorBlob);
+}
+
+
+static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
+ const struct ldb_val *in, struct ldb_val *out)
+{
+ *out = data_blob_string_const(data_blob_hex_string(mem_ctx, in));
+ if (!out->data) {
+ return -1;
+ }
+ return 0;
+}