if (!s.array) {
return s;
}
- s.length = s.size = val->length/2;
+ s.length = s.size = val->length;
memcpy(s.array, val->data, val->length);
return s;
int samdb_msg_add_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
const char *attr_name, uint_t v)
{
- const char *s = talloc_asprintf(mem_ctx, "%u", v);
- return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
+ return samdb_msg_add_int(sam_ldb, mem_ctx, msg, attr_name, (int)v);
}
/*
int samdb_msg_add_uint64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
const char *attr_name, uint64_t v)
{
- const char *s = talloc_asprintf(mem_ctx, "%llu", (unsigned long long)v);
- return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
+ return samdb_msg_add_int64(sam_ldb, mem_ctx, msg, attr_name, (int64_t)v);
}
/*
const char *attr_name, struct lsa_BinaryString *parameters)
{
struct ldb_val val;
- val.length = parameters->length * 2;
+ val.length = parameters->length;
val.data = (uint8_t *)parameters->array;
return ldb_msg_add_value(msg, attr_name, &val, NULL);
}
return domain_sid;
failed:
- DEBUG(1,("Failed to find domain_sid for open ldb\n"));
talloc_free(tmp_ctx);
return NULL;
}
+/*
+ get domain sid from cache
+*/
+const struct dom_sid *samdb_domain_sid_cache_only(struct ldb_context *ldb)
+{
+ return (struct dom_sid *)ldb_get_opaque(ldb, "cache.domain_sid");
+}
+
bool samdb_set_domain_sid(struct ldb_context *ldb, const struct dom_sid *dom_sid_in)
{
TALLOC_CTX *tmp_ctx;
/*
- load the uSNHighest attribute from the @REPLCHANGED object for a
- partition
+ load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
+ object for a partition
*/
-int dsdb_load_partition_usn(struct ldb_context *ldb, struct ldb_dn *dn, uint64_t *uSN)
+int dsdb_load_partition_usn(struct ldb_context *ldb, struct ldb_dn *dn,
+ uint64_t *uSN, uint64_t *urgent_uSN)
{
struct ldb_request *req;
int ret;
if (res->count < 1) {
*uSN = 0;
+ if (urgent_uSN) {
+ *urgent_uSN = 0;
+ }
} else {
*uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
+ if (urgent_uSN) {
+ *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
+ }
}
talloc_free(tmp_ctx);
}
/*
- save the uSNHighest attribute in the @REPLCHANGED object for a
+ save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
partition
*/
-int dsdb_save_partition_usn(struct ldb_context *ldb, struct ldb_dn *dn, uint64_t uSN)
+int dsdb_save_partition_usn(struct ldb_context *ldb, struct ldb_dn *dn,
+ uint64_t uSN, uint64_t urgent_uSN)
{
struct ldb_request *req;
struct ldb_message *msg;
}
msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
+ /* urgent_uSN is optional so may not be stored */
+ if (urgent_uSN) {
+ ret = ldb_msg_add_fmt(msg, "uSNUrgent", "%llu", (unsigned long long)urgent_uSN);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(msg);
+ return ret;
+ }
+ msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
+ }
+
p_ctrl = talloc(msg, struct dsdb_control_current_partition);
if (p_ctrl == NULL) {
return GUID_compare(&c1->source_dsa_invocation_id, &c2->source_dsa_invocation_id);
}
+int drsuapi_DsReplicaCursor_compare(const struct drsuapi_DsReplicaCursor *c1,
+ const struct drsuapi_DsReplicaCursor *c2)
+{
+ return GUID_compare(&c1->source_dsa_invocation_id, &c2->source_dsa_invocation_id);
+}
+
/*
see if we are a RODC
talloc_free(dn);
return LDB_SUCCESS;
}
+
+/*
+ compare a ldb_val to a string case insensitively
+ */
+int samdb_ldb_val_case_cmp(const char *s, struct ldb_val *v)
+{
+ size_t len = strlen(s);
+ int ret;
+ if (len > v->length) return 1;
+ ret = strncasecmp(s, (const char *)v->data, v->length);
+ if (ret != 0) return ret;
+ if (v->length > len && v->data[len] != 0) {
+ return -1;
+ }
+ return 0;
+}
+
+
+/*
+ load the UDV for a partition in v2 format
+ The list is returned sorted, and with our local cursor added
+ */
+int dsdb_load_udv_v2(struct ldb_context *samdb, struct ldb_dn *dn, TALLOC_CTX *mem_ctx,
+ struct drsuapi_DsReplicaCursor2 **cursors, uint32_t *count)
+{
+ static const char *attrs[] = { "replUpToDateVector", NULL };
+ struct ldb_result *r;
+ const struct ldb_val *ouv_value;
+ int ret, i;
+ uint64_t highest_usn;
+ const struct GUID *our_invocation_id;
+ struct timeval now = timeval_current();
+
+ ret = ldb_search(samdb, mem_ctx, &r, dn, LDB_SCOPE_BASE, attrs, NULL);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ ouv_value = ldb_msg_find_ldb_val(r->msgs[0], "replUpToDateVector");
+ if (ouv_value) {
+ enum ndr_err_code ndr_err;
+ struct replUpToDateVectorBlob ouv;
+
+ ndr_err = ndr_pull_struct_blob(ouv_value, r,
+ lp_iconv_convenience(ldb_get_opaque(samdb, "loadparm")), &ouv,
+ (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ talloc_free(r);
+ return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
+ }
+ if (ouv.version != 2) {
+ /* we always store as version 2, and
+ * replUpToDateVector is not replicated
+ */
+ return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
+ }
+
+ *count = ouv.ctr.ctr2.count;
+ *cursors = talloc_steal(mem_ctx, ouv.ctr.ctr2.cursors);
+ } else {
+ *count = 0;
+ *cursors = NULL;
+ }
+
+ talloc_free(r);
+
+ our_invocation_id = samdb_ntds_invocation_id(samdb);
+ if (!our_invocation_id) {
+ DEBUG(0,(__location__ ": No invocationID on samdb - %s\n", ldb_errstring(samdb)));
+ talloc_free(*cursors);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = dsdb_load_partition_usn(samdb, dn, &highest_usn, NULL);
+ if (ret != LDB_SUCCESS) {
+ /* nothing to add - this can happen after a vampire */
+ qsort(*cursors, *count,
+ sizeof(struct drsuapi_DsReplicaCursor2),
+ (comparison_fn_t)drsuapi_DsReplicaCursor2_compare);
+ return LDB_SUCCESS;
+ }
+
+ for (i=0; i<*count; i++) {
+ if (GUID_equal(our_invocation_id, &(*cursors)[i].source_dsa_invocation_id)) {
+ (*cursors)[i].highest_usn = highest_usn;
+ (*cursors)[i].last_sync_success = timeval_to_nttime(&now);
+ qsort(*cursors, *count,
+ sizeof(struct drsuapi_DsReplicaCursor2),
+ (comparison_fn_t)drsuapi_DsReplicaCursor2_compare);
+ return LDB_SUCCESS;
+ }
+ }
+
+ (*cursors) = talloc_realloc(mem_ctx, *cursors, struct drsuapi_DsReplicaCursor2, (*count)+1);
+ if (! *cursors) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ (*cursors)[*count].source_dsa_invocation_id = *our_invocation_id;
+ (*cursors)[*count].highest_usn = highest_usn;
+ (*cursors)[*count].last_sync_success = timeval_to_nttime(&now);
+ (*count)++;
+
+ qsort(*cursors, *count,
+ sizeof(struct drsuapi_DsReplicaCursor2),
+ (comparison_fn_t)drsuapi_DsReplicaCursor2_compare);
+
+ return LDB_SUCCESS;
+}
+
+/*
+ load the UDV for a partition in version 1 format
+ The list is returned sorted, and with our local cursor added
+ */
+int dsdb_load_udv_v1(struct ldb_context *samdb, struct ldb_dn *dn, TALLOC_CTX *mem_ctx,
+ struct drsuapi_DsReplicaCursor **cursors, uint32_t *count)
+{
+ struct drsuapi_DsReplicaCursor2 *v2;
+ int ret, i;
+
+ ret = dsdb_load_udv_v2(samdb, dn, mem_ctx, &v2, count);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ if (*count == 0) {
+ talloc_free(v2);
+ *cursors = NULL;
+ return LDB_SUCCESS;
+ }
+
+ *cursors = talloc_array(mem_ctx, struct drsuapi_DsReplicaCursor, *count);
+ if (*cursors == NULL) {
+ talloc_free(v2);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ for (i=0; i<*count; i++) {
+ (*cursors)[i].source_dsa_invocation_id = v2[i].source_dsa_invocation_id;
+ (*cursors)[i].highest_usn = v2[i].highest_usn;
+ }
+ talloc_free(v2);
+ return LDB_SUCCESS;
+}