state->value = v;
}
-static int ldif_write_HEXDUMP(struct ldb_context *ldb, void *mem_ctx,
- const struct ldb_val *in, struct ldb_val *out)
+static int ldif_write_HEXDUMP_prefix(struct ldb_context *ldb, const char *prefix,
+ void *mem_ctx,
+ const struct ldb_val *in, struct ldb_val *out)
{
struct ldif_write_HEXDUMP_state state = {
.error = false,
return ldb_handler_copy(ldb, mem_ctx, in, out);
}
- state.value = talloc_asprintf(mem_ctx, "HEXDUMP length[%zu]\n", in->length);
+ state.value = talloc_asprintf(mem_ctx, "%sHEXDUMP length[%zu]\n",
+ prefix, in->length);
if (state.value == NULL) {
ldb_oom(ldb);
return -1;
return 0;
}
+static int ldif_write_HEXDUMP(struct ldb_context *ldb, void *mem_ctx,
+ const struct ldb_val *in, struct ldb_val *out)
+{
+ return ldif_write_HEXDUMP_prefix(ldb, "", mem_ctx, in, out);
+}
+
/*
use ndr_print_* to convert a NDR formatted blob to a ldif formatted blob
\return 0 on success; -1 on error
*/
-static int ldif_write_NDR(struct ldb_context *ldb, void *mem_ctx,
- const struct ldb_val *in, struct ldb_val *out,
- size_t struct_size,
- ndr_pull_flags_fn_t pull_fn,
- ndr_print_fn_t print_fn,
- bool mask_errors)
+static int ldif_write_NDR_v(struct ldb_context *ldb, void *mem_ctx,
+ const struct ldb_val *in, struct ldb_val *out,
+ size_t struct_size,
+ ndr_pull_flags_fn_t pull_fn,
+ ndr_push_flags_fn_t push_fn,
+ ndr_print_fn_t print_fn,
+ bool mask_errors)
{
- uint8_t *p;
+ struct ndr_pull *ndr = NULL;
+ uint32_t highest_ofs;
+ uint8_t *p = NULL;
enum ndr_err_code err;
+ char *str = NULL;
+
if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
return ldb_handler_copy(ldb, mem_ctx, in, out);
}
- p = talloc_size(mem_ctx, struct_size);
- err = ndr_pull_struct_blob(in, mem_ctx,
- p, pull_fn);
+
+ ndr = ndr_pull_init_blob(in, mem_ctx);
+ if (ndr == NULL) {
+ return ldb_oom(ldb);
+ }
+ p = talloc_zero_size(ndr, struct_size);
+ if (p == NULL) {
+ TALLOC_FREE(ndr);
+ return ldb_oom(ldb);
+ }
+
+ err = pull_fn(ndr, NDR_SCALARS|NDR_BUFFERS, p);
if (err != NDR_ERR_SUCCESS) {
/* fail in not in mask_error mode */
if (!mask_errors) {
return -1;
}
- talloc_free(p);
- out->data = (uint8_t *)talloc_strdup(mem_ctx, "<Unable to decode binary data>");
- out->length = strlen((const char *)out->data);
- return 0;
+ TALLOC_FREE(ndr);
+ return ldif_write_HEXDUMP_prefix(ldb, "<Unable to decode binary data>",
+ mem_ctx, in, out);
}
- out->data = (uint8_t *)ndr_print_struct_string(mem_ctx, print_fn, "NDR", p);
- talloc_free(p);
- if (out->data == NULL) {
- return ldb_handler_copy(ldb, mem_ctx, in, out);
+ str = ndr_print_struct_string(mem_ctx, print_fn, "NDR", p);
+ if (str == NULL) {
+ TALLOC_FREE(ndr);
+ return ldif_write_HEXDUMP_prefix(ldb, "<ndr_print_struct_string failed>",
+ mem_ctx, in, out);
}
- out->length = strlen((char *)out->data);
+
+ if (ndr->offset > ndr->relative_highest_offset) {
+ highest_ofs = ndr->offset;
+ } else {
+ highest_ofs = ndr->relative_highest_offset;
+ }
+ if (highest_ofs < ndr->data_size) {
+ int ret;
+ const char *prefix = NULL;
+
+ prefix = talloc_asprintf(ndr, "%s\n<not all bytes consumed ofs[%u] size[%u]>",
+ str, highest_ofs, ndr->data_size);
+ if (prefix == NULL) {
+ TALLOC_FREE(ndr);
+ return ldb_oom(ldb);
+ }
+ TALLOC_FREE(str);
+ ret = ldif_write_HEXDUMP_prefix(ldb, prefix, mem_ctx, in, out);
+ TALLOC_FREE(ndr);
+ return ret;
+ }
+
+ if (push_fn != NULL) {
+ const char *prefix = NULL;
+ DATA_BLOB v = data_blob_null;
+ int ret;
+ int cmp;
+
+ err = ndr_push_struct_blob(&v, ndr, p, push_fn);
+ if (err != NDR_ERR_SUCCESS) {
+ prefix = talloc_asprintf(ndr, "%s\n<all bytes consumed ofs[%u] size[%u]>\n<ndr validate push failed>",
+ str, highest_ofs, ndr->data_size);
+ TALLOC_FREE(str);
+ if (prefix == NULL) {
+ TALLOC_FREE(ndr);
+ return ldb_oom(ldb);
+ }
+ ret = ldif_write_HEXDUMP_prefix(ldb, prefix, mem_ctx, in, out);
+ TALLOC_FREE(ndr);
+ return ret;
+ }
+
+ cmp = data_blob_cmp(in, &v);
+ if (cmp == 0) {
+ prefix = talloc_asprintf(ndr, "%s\n<all bytes consumed ofs[%u] size[%u]>\n<ndr validate ok>",
+ str, highest_ofs, ndr->data_size);
+ TALLOC_FREE(str);
+ if (prefix == NULL) {
+ TALLOC_FREE(ndr);
+ return ldb_oom(ldb);
+ }
+ ret = ldif_write_HEXDUMP_prefix(ldb, prefix, mem_ctx, in, out);
+ TALLOC_FREE(ndr);
+ return ret;
+ }
+
+ prefix = talloc_asprintf(ndr, "%s\n<all bytes consumed ofs[%u] size[%u]>",
+ str, highest_ofs, ndr->data_size);
+ TALLOC_FREE(str);
+ if (prefix == NULL) {
+ TALLOC_FREE(ndr);
+ return ldb_oom(ldb);
+ }
+ ret = ldif_write_HEXDUMP_prefix(ldb, prefix, mem_ctx, in, out);
+ if (ret != LDB_SUCCESS) {
+ TALLOC_FREE(ndr);
+ return ret;
+ }
+ str = (char *)out->data;
+ *out = data_blob_null;
+ prefix = talloc_asprintf(ndr, "%s\n<ndr validate failed>",
+ str);
+ TALLOC_FREE(str);
+ if (prefix == NULL) {
+ TALLOC_FREE(ndr);
+ return ldb_oom(ldb);
+ }
+ ret = ldif_write_HEXDUMP_prefix(ldb, prefix, mem_ctx, &v, out);
+ TALLOC_FREE(ndr);
+ return ret;
+ }
+
+ if (1) {
+ int ret;
+ const char *prefix = NULL;
+
+ prefix = talloc_asprintf(ndr, "%s\n<all bytes consumed ofs[%u] size[%u]>",
+ str, highest_ofs, ndr->data_size);
+ TALLOC_FREE(str);
+ if (prefix == NULL) {
+ TALLOC_FREE(ndr);
+ return ldb_oom(ldb);
+ }
+ ret = ldif_write_HEXDUMP_prefix(ldb, prefix, mem_ctx, in, out);
+ TALLOC_FREE(ndr);
+ return ret;
+ }
+
+ TALLOC_FREE(ndr);
+ *out = data_blob_string_const(str);
return 0;
}
+static int ldif_write_NDR(struct ldb_context *ldb, void *mem_ctx,
+ const struct ldb_val *in, struct ldb_val *out,
+ size_t struct_size,
+ ndr_pull_flags_fn_t pull_fn,
+ ndr_print_fn_t print_fn,
+ bool mask_errors)
+{
+ return ldif_write_NDR_v(ldb, mem_ctx, in, out, struct_size, pull_fn, NULL, print_fn, mask_errors);
+}
+
/*
convert a ldif formatted objectSid to a NDR formatted blob
*/
true);
}
+static bool is_xml_value(const struct ldb_val *in)
+{
+ if (in->length < 4) {
+ return false;
+ }
+
+ if (in->data[0] != '<') {
+ return false;
+ }
+
+ if (in->data[in->length - 3] != '>') {
+ return false;
+ }
+
+ if (in->data[in->length - 2] != '\n') {
+ return false;
+ }
+
+ if (in->data[in->length - 1] != '\0') {
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ convert a NDR formatted blob to a ldif formatted
+ "msDs-replAttributeMetaData" => XML
+ "msDs-replAttributeMetaData;binary" => msDS_ReplAttributeMetaDataBlob
+*/
+static int ldif_write_msDS_ReplAttributeMetaData(struct ldb_context *ldb,
+ void *mem_ctx,
+ const struct ldb_val *in,
+ struct ldb_val *out)
+{
+ if (is_xml_value(in)) {
+ return ldb_handler_copy(ldb, mem_ctx, in, out);
+ }
+
+ return ldif_write_NDR_v(ldb, mem_ctx, in, out,
+ sizeof(struct msDS_ReplAttributeMetaDataBlob),
+ (ndr_pull_flags_fn_t)ndr_pull_msDS_ReplAttributeMetaDataBlob,
+ (ndr_push_flags_fn_t)ndr_push_msDS_ReplAttributeMetaDataBlob,
+ (ndr_print_fn_t)ndr_print_msDS_ReplAttributeMetaDataBlob,
+ true);
+}
+
+/*
+ convert a NDR formatted blob to a ldif formatted
+ "msDs-replValueMetaData" or
+ "msDs-replValueMetaData;binary"
+*/
+static int ldif_write_msDS_ReplValueMetaData(struct ldb_context *ldb,
+ void *mem_ctx,
+ const struct ldb_val *in,
+ struct ldb_val *out)
+{
+ if (is_xml_value(in)) {
+ return ldb_handler_copy(ldb, mem_ctx, in, out);
+ }
+
+ return ldif_write_NDR_v(ldb, mem_ctx, in, out,
+ sizeof(struct msDS_ReplValueMetaDataBlob),
+ (ndr_pull_flags_fn_t)ndr_pull_msDS_ReplValueMetaDataBlob,
+ (ndr_push_flags_fn_t)ndr_push_msDS_ReplValueMetaDataBlob,
+ (ndr_print_fn_t)ndr_print_msDS_ReplValueMetaDataBlob,
+ true);
+}
+
/*
convert a NDR formatted blob to a ldif formatted replUpToDateVector
*/
.canonicalise_fn = ldb_handler_copy,
.comparison_fn = samba_ldb_comparison_binary,
.operator_fn = samba_syntax_binary_operator_fn
+ },{
+ .name = LDB_SYNTAX_SAMBA_REPLATTRIBUTEMETADATA,
+ .ldif_read_fn = ldb_handler_copy,
+ .ldif_write_fn = ldif_write_msDS_ReplAttributeMetaData,
+ .canonicalise_fn = ldb_handler_copy,
+ .comparison_fn = samba_ldb_comparison_binary,
+ .operator_fn = samba_syntax_binary_operator_fn
+ },{
+ .name = LDB_SYNTAX_SAMBA_REPLVALUEMETADATA,
+ .ldif_read_fn = ldb_handler_copy,
+ .ldif_write_fn = ldif_write_msDS_ReplValueMetaData,
+ .canonicalise_fn = ldb_handler_copy,
+ .comparison_fn = samba_ldb_comparison_binary,
+ .operator_fn = samba_syntax_binary_operator_fn
},{
.name = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
.ldif_read_fn = ldb_handler_copy,
{ "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO },
{ "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO },
{ "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
+ { "msDS-replAttributeMetaData", LDB_SYNTAX_SAMBA_REPLATTRIBUTEMETADATA },
+ { "msDS-replAttributeMetaData;binary", LDB_SYNTAX_SAMBA_REPLATTRIBUTEMETADATA },
+ { "msDS-replValueMetaData", LDB_SYNTAX_SAMBA_REPLVALUEMETADATA },
+ { "msDS-replValueMetaData;binary", LDB_SYNTAX_SAMBA_REPLVALUEMETADATA },
{ "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
{ "msDS-RevealedUsers", LDB_SYNTAX_SAMBA_REVEALEDUSERS },
{ "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
#define LDB_SYNTAX_SAMBA_INT32 "LDB_SYNTAX_SAMBA_INT32"
#define LDB_SYNTAX_SAMBA_REPSFROMTO "LDB_SYNTAX_SAMBA_REPSFROMTO"
#define LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA "LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA"
+#define LDB_SYNTAX_SAMBA_REPLATTRIBUTEMETADATA "LDB_SYNTAX_SAMBA_REPLATTRIBUTEMETADATA"
+#define LDB_SYNTAX_SAMBA_REPLVALUEMETADATA "LDB_SYNTAX_SAMBA_REPLVALUEMETADATA"
#define LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR "LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR"
#define LDB_SYNTAX_SAMBA_REVEALEDUSERS "LDB_SYNTAX_SAMBA_REVEALEDUSERS"
#define LDB_SYNTAX_SAMBA_RANGE64 "LDB_SYNTAX_SAMBA_RANGE64"
Return the date and time as a string
****************************************************************************/
-char *timeval_str_buf(const struct timeval *tp, bool rfc5424, bool hires,
- struct timeval_buf *dst)
+static char *timeval_str_buf_internal(const struct timeval *tp,
+ bool utc, bool rfc5424, bool hires,
+ struct timeval_buf *dst)
{
time_t t;
struct tm *tm;
size_t len;
t = (time_t)tp->tv_sec;
- tm = localtime(&t);
+ if (utc) {
+ tm = gmtime(&t);
+ } else {
+ tm = localtime(&t);
+ }
if (tm == NULL) {
if (hires) {
1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
- if ((rfc5424 || hires) && (len < sizeof(dst->buf))) {
+ if (hires && (len < sizeof(dst->buf))) {
len += snprintf(dst->buf + len, sizeof(dst->buf) - len,
".%06ld", (long)tp->tv_usec);
}
- if (rfc5424 && (len < sizeof(dst->buf))) {
+ if (utc && rfc5424 && (len < sizeof(dst->buf))) {
+ snprintf(dst->buf + len, sizeof(dst->buf) - len, "Z");
+ } else if (rfc5424 && (len < sizeof(dst->buf))) {
struct tm tm_utc, tm_local;
int offset;
return dst->buf;
}
+
+char *timeval_str_buf(const struct timeval *tp, bool rfc5424, bool hires,
+ struct timeval_buf *dst)
+{
+ const bool utc = false;
+ return timeval_str_buf_internal(tp, utc, rfc5424, hires, dst);
+}
+
+char *timeval_str_utc_buf(const struct timeval *tp, bool hires,
+ struct timeval_buf *dst)
+{
+ const bool utc = true;
+ const bool rfc5424 = true;
+ return timeval_str_buf_internal(tp, utc, rfc5424, hires, dst);
+}
is a stricter instance of RFC3339 and is used for syslog). For
example: 2003-08-24T05:14:15.000003-07:00. Otherwise,
format is %Y/%m/%d %H:%M:%S
+
+ This is based on the local time.
**/
char *timeval_str_buf(const struct timeval *tp, bool rfc5424, bool hires,
struct timeval_buf *dst);
+/**
+ Put a date and time into dst->buf, return it dst->buf
+ (optionally with microseconds)
+
+ If rfc5424 is true then produce the RFC5424 timestamp format (which
+ is a stricter instance of RFC3339 and is used for syslog). For
+ example: 2003-08-24T05:14:15.000003Z.
+ or: 2003-08-24T05:14:15Z (with hires = false).
+
+ The value is based on UTC.
+**/
+
+char *timeval_str_utc_buf(const struct timeval *tp, bool hires,
+ struct timeval_buf *dst);
+
#endif /* _SAMBA_TIME_BASIC_H_ */
[switch_is(version)] replPropertyMetaDataCtr ctr;
} replPropertyMetaDataBlob;
+ typedef [public,gensize] struct {
+ [relative] nstring *attribute_name;
+ uint32 version;
+ NTTIME originating_change_time;
+ GUID originating_invocation_id;
+ hyper originating_usn;
+ hyper local_usn;
+ [relative] nstring *originating_dsa_dn;
+ [flag(NDR_ALIGN8)] DATA_BLOB __padding;
+ } msDS_ReplAttributeMetaData;
+
+ typedef [public] struct {
+ [subcontext(0)]
+ [subcontext_size(_ndr_size_msDS_ReplAttributeMetaData(ndr, &stamp))]
+ msDS_ReplAttributeMetaData stamp;
+ } msDS_ReplAttributeMetaDataBlob;
+
+ typedef [public,gensize] struct {
+ [relative] nstring *attribute_name;
+ [relative] nstring *object_dn;
+ [value(ndr_size_DATA_BLOB(0,binary,0))] uint32 __ndr_size_binary;
+ [relative,subcontext(0),subcontext_size(__ndr_size_binary),flag(NDR_REMAINING)] DATA_BLOB *binary;
+ NTTIME deleted;
+ NTTIME created;
+ uint32 version;
+ NTTIME originating_change_time;
+ GUID originating_invocation_id;
+ hyper originating_usn;
+ hyper local_usn;
+ [relative] nstring *originating_dsa_dn;
+ [flag(NDR_ALIGN8)] DATA_BLOB __padding;
+ } msDS_ReplValueMetaData;
+
+ typedef [public] struct {
+ [subcontext(0)]
+ [subcontext_size(_ndr_size_msDS_ReplValueMetaData(ndr, &stamp))]
+ msDS_ReplValueMetaData stamp;
+ } msDS_ReplValueMetaDataBlob;
+
/*
* replUpToDateVector
* w2k uses version 1
#include "librpc/gen_ndr/ndr_drsblobs.h"
#include "../lib/util/asn1.h"
+_PUBLIC_ size_t _ndr_size_msDS_ReplAttributeMetaData(const void *ndr, const struct msDS_ReplAttributeMetaData *r)
+{
+ struct ndr_push *push = talloc_get_type(ndr, struct ndr_push);
+ struct ndr_pull *pull = talloc_get_type(ndr, struct ndr_pull);
+ size_t s = 0;
+
+ if (push != NULL) {
+ s = ndr_size_msDS_ReplAttributeMetaData(r, 0);
+ }
+
+ if (pull != NULL) {
+ s = pull->data_size;
+ }
+
+ return NDR_ROUND(s, 4);
+}
+
+_PUBLIC_ size_t _ndr_size_msDS_ReplValueMetaData(const void *ndr, const struct msDS_ReplValueMetaData *r)
+{
+ struct ndr_push *push = talloc_get_type(ndr, struct ndr_push);
+ struct ndr_pull *pull = talloc_get_type(ndr, struct ndr_pull);
+ size_t s = 0;
+
+ if (push != NULL) {
+ s = ndr_size_msDS_ReplValueMetaData(r, 0);
+ }
+
+ if (pull != NULL) {
+ s = pull->data_size;
+ }
+
+ return NDR_ROUND(s, 4);
+}
+
_PUBLIC_ enum ndr_err_code ndr_push_AuthenticationInformationArray(struct ndr_push *ndr, int ndr_flags, const struct AuthenticationInformationArray *r)
{
uint32_t cntr_array_0;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+_PUBLIC_ size_t _ndr_size_msDS_ReplAttributeMetaData(const void *ndr, const struct msDS_ReplAttributeMetaData *r);
+_PUBLIC_ size_t _ndr_size_msDS_ReplValueMetaData(const void *ndr, const struct msDS_ReplValueMetaData *r);
_PUBLIC_ enum ndr_err_code ndr_pull_trustDomainPasswords(struct ndr_pull *ndr, int ndr_flags, struct trustDomainPasswords *r);
_PUBLIC_ void ndr_print_drsuapi_MSPrefixMap_Entry(struct ndr_print *ndr, const char *name, const struct drsuapi_MSPrefixMap_Entry *r);
#include <ldb.h>
#include <ldb_module.h>
+#include <tdb.h>
+#include "lib/dbwrap/dbwrap.h"
+#include "lib/dbwrap/dbwrap_rbt.h"
+
#include "librpc/gen_ndr/ndr_misc.h"
#include "librpc/gen_ndr/ndr_drsblobs.h"
#include "param/param.h"
#include "dsdb/samdb/samdb.h"
#include "dsdb/samdb/ldb_modules/util.h"
+#include "lib/util/time_basic.h"
+#include "libcli/ldap/ldap_ndr.h"
+
#include "libcli/security/security.h"
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
#endif
+struct operational_context {
+ struct ldb_module *module;
+ struct ldb_request *req;
+ enum ldb_scope scope;
+ const char * const *attrs;
+ struct op_controls_flags* controls_flags;
+ struct op_attributes_operations *list_operations;
+ unsigned int list_operations_size;
+ struct op_attributes_replace *attrs_to_replace;
+ unsigned int attrs_to_replace_size;
+ const struct dsdb_schema *schema;
+ struct db_context *dsa_cache;
+ struct ldb_dn *sites_dn;
+};
+
struct operational_data {
struct ldb_dn *aggregate_dn;
};
return LDB_SUCCESS;
}
+struct operational_dsa_by_invocation_id_state {
+ struct ldb_dn *dn;
+};
+
+static void operational_dsa_by_invocation_id_parser(TDB_DATA key, TDB_DATA data, void *private_data)
+{
+ struct operational_dsa_by_invocation_id_state *state =
+ (struct operational_dsa_by_invocation_id_state *)private_data;
+ void *ptr = NULL;
+
+ state->dn = NULL;
+
+ if (data.dsize == 0) {
+ return;
+ }
+
+ if (data.dsize != sizeof(ptr)) {
+ smb_panic(__location__);
+ }
+
+ memcpy(&ptr, data.dptr, sizeof(ptr));
+ state->dn = talloc_get_type_abort(ptr, struct ldb_dn);
+}
+
+static const char *operational_dsa_by_invocation_id(struct operational_context *ac,
+ const struct GUID *invocation_id)
+{
+ struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
+ struct operational_dsa_by_invocation_id_state state = {
+ .dn = NULL,
+ };
+ TDB_DATA key = {
+ .dptr = discard_const_p(uint8_t, invocation_id),
+ .dsize = sizeof(*invocation_id),
+ };
+ void *ptr = NULL;
+ TDB_DATA value = {
+ .dptr = (uint8_t *)&ptr,
+ .dsize = sizeof(ptr),
+ };
+ char *encoded_id = NULL;
+ struct ldb_message *msg = NULL;
+ NTSTATUS status;
+ int ret;
+
+ if (ac->dsa_cache == NULL) {
+ ac->dsa_cache = db_open_rbt(ac);
+ if (ac->dsa_cache == NULL) {
+ return NULL;
+ }
+ }
+
+ if (ac->sites_dn == NULL) {
+ ac->sites_dn = samdb_sites_dn(ldb, ac);
+ if (ac->sites_dn == NULL) {
+ return NULL;
+ }
+ }
+
+ status = dbwrap_parse_record(ac->dsa_cache, key,
+ operational_dsa_by_invocation_id_parser,
+ &state);
+ if (NT_STATUS_IS_OK(status) && state.dn != NULL) {
+ return ldb_dn_get_linearized(state.dn);
+ }
+
+ encoded_id = ldap_encode_ndr_GUID(ac->dsa_cache, invocation_id);
+ if (encoded_id == NULL) {
+ return NULL;
+ }
+
+ // TODO DSDB_SEARCH_SHOW_RECYCLED ok???
+ ret = dsdb_search_one(ldb, ac->dsa_cache, &msg, ac->sites_dn,
+ LDB_SCOPE_SUBTREE, NULL,
+ DSDB_FLAG_AS_SYSTEM |
+ DSDB_SEARCH_SHOW_RECYCLED,
+ "(invocationId=%s)",
+ encoded_id);
+ TALLOC_FREE(encoded_id);
+ if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+ return "<unknown-todo>";
+ }
+ if (ret != LDB_SUCCESS) {
+ return NULL;
+ }
+
+ state.dn = talloc_move(ac->dsa_cache, &msg->dn);
+ TALLOC_FREE(msg);
+ ptr = state.dn;
+
+ status = dbwrap_store(ac->dsa_cache, key, value, TDB_INSERT);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(state.dn);
+ return NULL;
+ }
+
+ return ldb_dn_get_linearized(state.dn);
+}
+
+static int construct_msDS_ReplAttributeMetaData(struct ldb_module *module,
+ struct ldb_message *msg,
+ enum ldb_scope scope,
+ struct ldb_request *parent,
+ bool xml)
+{
+ struct operational_context *ac =
+ talloc_get_type_abort(parent->context,
+ struct operational_context);
+ struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
+ uint32_t i;
+ enum ndr_err_code ndr_err;
+ const struct ldb_val *omd_value = NULL;
+ struct replPropertyMetaDataBlob *omd = NULL;
+ int ret;
+
+ if (ac->schema == NULL) {
+ ac->schema = dsdb_get_schema(ldb, ac);
+ if (ac->schema == NULL) {
+ /* We can't make up anything without a schema */
+ return LDB_SUCCESS;
+ }
+ }
+
+ omd_value = ldb_msg_find_ldb_val(msg, "replPropertyMetaData");
+ if (!omd_value) {
+ /* We can't make up anything without meta data */
+ return LDB_SUCCESS;
+ }
+
+ omd = talloc_zero(msg, struct replPropertyMetaDataBlob);
+ if (omd == NULL) {
+ return ldb_module_oom(module);
+ }
+
+ ndr_err = ndr_pull_struct_blob(omd_value, omd, omd,
+ (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DEBUG(0,(__location__ ": Failed to parse replPropertyMetaData for %s when trying to add msDS-KeyVersionNumber\n",
+ ldb_dn_get_linearized(msg->dn)));
+ return ldb_operr(ldb_module_get_ctx(module));
+ }
+
+ if (omd->version != 1) {
+ DEBUG(0,(__location__ ": bad version %u in replPropertyMetaData for %s when trying to add msDS-KeyVersionNumber\n",
+ omd->version, ldb_dn_get_linearized(msg->dn)));
+ talloc_free(omd);
+ return LDB_SUCCESS;
+ }
+
+ for (i=0; i<omd->ctr.ctr1.count; i++) {
+ struct msDS_ReplAttributeMetaDataBlob _r;
+ struct msDS_ReplAttributeMetaData *r = &_r.stamp;
+ const struct replPropertyMetaData1 *m = &omd->ctr.ctr1.array[i];
+ const struct dsdb_attribute *a = NULL;
+ const char *dsa_dn = NULL;
+ const char *attr_name = NULL;
+ struct ldb_val val = data_blob_null;
+
+ a = dsdb_attribute_by_attributeID_id(ac->schema, m->attid);
+ if (a == NULL) {
+ return ldb_module_operr(module);
+ }
+
+ dsa_dn = operational_dsa_by_invocation_id(ac,
+ &m->originating_invocation_id);
+ if (dsa_dn == NULL) {
+ return ldb_module_operr(module);
+ }
+
+ r->attribute_name = a->lDAPDisplayName;
+ r->version = m->version;
+ r->originating_change_time = m->originating_change_time;
+ r->originating_invocation_id = m->originating_invocation_id;
+ r->originating_usn = m->originating_usn;
+ r->local_usn = m->local_usn;
+ r->originating_dsa_dn = dsa_dn;
+
+ if (xml) {
+ struct timeval_buf tv_buf;
+ struct timeval change_tv;
+ struct GUID_txt_buf iv_buf;
+ char *str = NULL;
+
+ nttime_to_timeval(&change_tv,
+ r->originating_change_time);
+
+ str = talloc_asprintf(msg,
+ "<DS_REPL_ATTR_META_DATA>\n"
+ "\t<pszAttributeName>%s"
+ "</pszAttributeName>\n"
+ "\t<dwVersion>%u</dwVersion>\n"
+ "\t<ftimeLastOriginatingChange>%s"
+ "</ftimeLastOriginatingChange>\n"
+ "\t<uuidLastOriginatingDsaInvocationID>%s"
+ "</uuidLastOriginatingDsaInvocationID>\n"
+ "\t<usnOriginatingChange>%llu"
+ "</usnOriginatingChange>\n"
+ "\t<usnLocalChange>%llu</usnLocalChange>\n"
+ "\t<pszLastOriginatingDsaDN>%s"
+ "</pszLastOriginatingDsaDN>\n"
+ "</DS_REPL_ATTR_META_DATA>\n",
+ r->attribute_name,
+ (unsigned)r->version,
+ timeval_str_utc_buf(&change_tv, false, &tv_buf),
+ GUID_buf_string(&r->originating_invocation_id,
+ &iv_buf),
+ (unsigned long long)r->originating_usn,
+ (unsigned long long)r->local_usn,
+ dsa_dn);
+ if (str == NULL) {
+ return ldb_module_oom(module);
+ }
+
+ attr_name = "msDS-ReplAttributeMetaData";
+ val.data = (uint8_t *)str;
+ val.length = strlen(str) + 1;
+ } else {
+
+ attr_name = "msDS-ReplAttributeMetaData;binary";
+ ndr_err = ndr_push_struct_blob(&val, msg, &_r,
+ (ndr_push_flags_fn_t)ndr_push_msDS_ReplAttributeMetaDataBlob);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DEBUG(0,(__location__ ": Failed to marshall msDS_ReplAttributeMetaDataBlob for %s\n",
+ ldb_dn_get_linearized(msg->dn)));
+ return ldb_module_operr(module);
+ }
+ }
+
+ ret = ldb_msg_add_steal_value(msg, attr_name, &val);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ }
+
+ talloc_free(omd);
+ return LDB_SUCCESS;
+}
+
+static int construct_msDS_ReplAttributeMetaData_xml(struct ldb_module *module,
+ struct ldb_message *msg,
+ enum ldb_scope scope,
+ struct ldb_request *parent)
+{
+ return construct_msDS_ReplAttributeMetaData(module, msg, scope,
+ parent, true);
+}
+
+static int construct_msDS_ReplAttributeMetaData_blob(struct ldb_module *module,
+ struct ldb_message *msg,
+ enum ldb_scope scope,
+ struct ldb_request *parent)
+{
+ return construct_msDS_ReplAttributeMetaData(module, msg, scope,
+ parent, false);
+}
+
struct op_controls_flags {
bool sd;
bool bypassoperational;
{ "msDS-UserPasswordExpiryTimeComputed", "userAccountControl", user_password_expiry_time_computed_attrs,
construct_msds_user_password_expiry_time_computed },
{ "msDS-ResultantPSO", "objectClass", resultant_pso_computed_attrs,
- construct_resultant_pso }
+ construct_resultant_pso },
+ { "msDS-ReplAttributeMetaData", "replPropertyMetaData", NULL,
+ construct_msDS_ReplAttributeMetaData_xml },
+ { "msDS-ReplAttributeMetaData;binary", "replPropertyMetaData", NULL,
+ construct_msDS_ReplAttributeMetaData_blob },
};
hook search operations
*/
-struct operational_context {
- struct ldb_module *module;
- struct ldb_request *req;
- enum ldb_scope scope;
- const char * const *attrs;
- struct op_controls_flags* controls_flags;
- struct op_attributes_operations *list_operations;
- unsigned int list_operations_size;
- struct op_attributes_replace *attrs_to_replace;
- unsigned int attrs_to_replace_size;
-};
-
static int operational_callback(struct ldb_request *req, struct ldb_reply *ares)
{
struct operational_context *ac;
ldb = ldb_module_get_ctx(module);
- ac = talloc(req, struct operational_context);
+ ac = talloc_zero(req, struct operational_context);
if (ac == NULL) {
return ldb_oom(ldb);
}
ac->attrs_to_replace = NULL;
ac->attrs_to_replace_size = 0;
+
/* in the list of attributes we are looking for, rename any
attributes to the alias for any hidden attributes that can
be fetched directly using non-hidden names.