summaryrefslogtreecommitdiff
path: root/source4/lib/ldb
diff options
context:
space:
mode:
Diffstat (limited to 'source4/lib/ldb')
-rw-r--r--source4/lib/ldb/common/ldb_modules.c2
-rw-r--r--source4/lib/ldb/common/ldb_msg.c71
-rw-r--r--source4/lib/ldb/include/ldb_private.h2
-rw-r--r--source4/lib/ldb/modules/operational.c101
-rw-r--r--source4/lib/ldb/modules/rdn_name.c8
5 files changed, 145 insertions, 39 deletions
diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c
index 5ca666c194..f3ca4df9b4 100644
--- a/source4/lib/ldb/common/ldb_modules.c
+++ b/source4/lib/ldb/common/ldb_modules.c
@@ -127,7 +127,7 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[])
ldb_module_init_t init;
} well_known_modules[] = {
{ "schema", schema_module_init },
- { "timestamps", timestamps_module_init },
+ { "operational", operational_module_init },
{ "rdn_name", rdn_name_module_init },
#ifdef _SAMBA_BUILD_
{ "objectguid", objectguid_module_init },
diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c
index 2aef7acc42..1c7ae3920a 100644
--- a/source4/lib/ldb/common/ldb_msg.c
+++ b/source4/lib/ldb/common/ldb_msg.c
@@ -353,47 +353,64 @@ void ldb_msg_sort_elements(struct ldb_message *msg)
}
/*
- copy a message, allocating new memory for all parts
+ shallow copy a message - copying only the elements array so that the caller
+ can safely add new elements without changing the message
*/
-struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
- const struct ldb_message *msg)
+struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx,
+ const struct ldb_message *msg)
{
struct ldb_message *msg2;
- int i, j;
+ int i;
msg2 = talloc(mem_ctx, struct ldb_message);
if (msg2 == NULL) return NULL;
- msg2->elements = NULL;
- msg2->num_elements = 0;
+ *msg2 = *msg;
msg2->private_data = NULL;
- msg2->dn = ldb_dn_copy(msg2, msg->dn);
- if (msg2->dn == NULL) goto failed;
-
- msg2->elements = talloc_array(msg2, struct ldb_message_element, msg->num_elements);
+ msg2->elements = talloc_array(msg2, struct ldb_message_element,
+ msg2->num_elements);
if (msg2->elements == NULL) goto failed;
- for (i=0;i<msg->num_elements;i++) {
- struct ldb_message_element *el1 = &msg->elements[i];
- struct ldb_message_element *el2 = &msg2->elements[i];
+ for (i=0;i<msg2->num_elements;i++) {
+ msg2->elements[i] = msg->elements[i];
+ }
+
+ return msg2;
- el2->flags = el1->flags;
- el2->num_values = 0;
- el2->values = NULL;
- el2->name = talloc_strdup(msg2->elements, el1->name);
- if (el2->name == NULL) goto failed;
- el2->values = talloc_array(msg2->elements, struct ldb_val, el1->num_values);
- for (j=0;j<el1->num_values;j++) {
- el2->values[j] = ldb_val_dup(el2->values, &el1->values[j]);
- if (el2->values[j].data == NULL &&
- el1->values[j].length != 0) {
+failed:
+ talloc_free(msg2);
+ return NULL;
+}
+
+
+/*
+ copy a message, allocating new memory for all parts
+*/
+struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
+ const struct ldb_message *msg)
+{
+ struct ldb_message *msg2;
+ int i, j;
+
+ msg2 = ldb_msg_copy_shallow(mem_ctx, msg);
+ if (msg2 == NULL) return NULL;
+
+ msg2->dn = ldb_dn_copy(msg2, msg2->dn);
+ if (msg2->dn == NULL) goto failed;
+
+ for (i=0;i<msg2->num_elements;i++) {
+ struct ldb_message_element *el = &msg2->elements[i];
+ struct ldb_val *values = el->values;
+ el->name = talloc_strdup(msg2->elements, el->name);
+ if (el->name == NULL) goto failed;
+ el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
+ for (j=0;j<el->num_values;j++) {
+ el->values[j] = ldb_val_dup(el->values, &values[j]);
+ if (el->values[j].data == NULL && values[j].length != 0) {
goto failed;
}
- el2->num_values++;
}
-
- msg2->num_elements++;
}
return msg2;
@@ -626,7 +643,7 @@ time_t ldb_string_to_time(const char *s)
if (s == NULL) return 0;
ZERO_STRUCT(tm);
- if (sscanf(s, "%04u%02u%02u%02u%02u%02u.0Z",
+ if (sscanf(s, "%04u%02u%02u%02u%02u%02u",
&tm.tm_year, &tm.tm_mon, &tm.tm_mday,
&tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
return 0;
diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h
index 2367d6c3f8..e444b7235a 100644
--- a/source4/lib/ldb/include/ldb_private.h
+++ b/source4/lib/ldb/include/ldb_private.h
@@ -183,6 +183,8 @@ int ldb_set_attrib_handlers(struct ldb_context *ldb,
const struct ldb_attrib_handler *handlers,
unsigned num_handlers);
int ldb_setup_wellknown_attributes(struct ldb_context *ldb);
+int ldb_set_attrib_handler_syntax(struct ldb_context *ldb,
+ const char *attr, const char *syntax);
/* The following definitions come from lib/ldb/common/ldb_attributes.c */
const char **ldb_subclass_list(struct ldb_context *ldb, const char *class);
diff --git a/source4/lib/ldb/modules/operational.c b/source4/lib/ldb/modules/operational.c
index 911bc087ca..d1e83c02e0 100644
--- a/source4/lib/ldb/modules/operational.c
+++ b/source4/lib/ldb/modules/operational.c
@@ -126,7 +126,7 @@ static int operational_search_bytree(struct ldb_module *module,
attributes to the alias for any hidden attributes that can
be fetched directly using non-hidden names */
for (i=0;i<ARRAY_SIZE(search_sub);i++) {
- for (a=0;attrs[a];a++) {
+ for (a=0;attrs && attrs[a];a++) {
if (ldb_attr_cmp(attrs[a], search_sub[i].attr) == 0) {
if (!search_attrs) {
search_attrs = ldb_attr_list_copy(module, attrs);
@@ -153,7 +153,7 @@ static int operational_search_bytree(struct ldb_module *module,
them (if the aliased entry was not asked for) */
for (r=0;r<ret;r++) {
for (i=0;i<ARRAY_SIZE(search_sub);i++) {
- for (a=0;attrs[a];a++) {
+ for (a=0;attrs && attrs[a];a++) {
if (ldb_attr_cmp(attrs[a], search_sub[i].attr) != 0) {
continue;
}
@@ -183,15 +183,98 @@ oom:
return -1;
}
+/*
+ add a time element to a record
+*/
+static int add_time_element(struct ldb_message *msg, const char *attr, time_t t)
+{
+ struct ldb_message_element *el;
+ char *s;
+
+ if (ldb_msg_find_element(msg, attr) != NULL) {
+ return 0;
+ }
+
+ s = ldb_timestring(msg, t);
+ if (s == NULL) {
+ return -1;
+ }
+
+ if (ldb_msg_add_string(msg, attr, s) != 0) {
+ return -1;
+ }
+
+ el = ldb_msg_find_element(msg, attr);
+ /* always set as replace. This works because on add ops, the flag
+ is ignored */
+ el->flags = LDB_FLAG_MOD_REPLACE;
+
+ return 0;
+}
+
+
+/*
+ hook add record ops
+*/
+static int operational_add_record(struct ldb_module *module,
+ const struct ldb_message *msg)
+{
+ time_t t = time(NULL);
+ struct ldb_message *msg2;
+ int ret;
+
+ if (ldb_dn_is_special(msg->dn)) {
+ return ldb_next_add_record(module, msg);
+ }
+
+ /* we have to copy the message as the caller might have it as a const */
+ msg2 = ldb_msg_copy_shallow(module, msg);
+ if (msg2 == NULL) {
+ return -1;
+ }
+ if (add_time_element(msg2, "whenCreated", t) != 0 ||
+ add_time_element(msg2, "whenChanged", t) != 0) {
+ talloc_free(msg2);
+ return -1;
+ }
+ ret = ldb_next_add_record(module, msg2);
+ talloc_free(msg2);
+ return ret;
+}
+
+/*
+ hook modify record ops
+*/
+static int operational_modify_record(struct ldb_module *module,
+ const struct ldb_message *msg)
+{
+ time_t t = time(NULL);
+ struct ldb_message *msg2;
+ int ret;
+
+ if (ldb_dn_is_special(msg->dn)) {
+ return ldb_next_modify_record(module, msg);
+ }
+
+ /* we have to copy the message as the caller might have it as a const */
+ msg2 = ldb_msg_copy_shallow(module, msg);
+ if (msg2 == NULL) {
+ return -1;
+ }
+ if (add_time_element(msg2, "whenChanged", t) != 0) {
+ talloc_free(msg2);
+ return -1;
+ }
+ ret = ldb_next_modify_record(module, msg2);
+ talloc_free(msg2);
+ return ret;
+}
static const struct ldb_module_ops operational_ops = {
.name = "operational",
.search_bytree = operational_search_bytree,
-#if 0
.add_record = operational_add_record,
- .modify_record = operational_modify_record,
- .rename_record = operational_rename_record
-#endif
+ .modify_record = operational_modify_record
};
@@ -213,5 +296,11 @@ struct ldb_module *operational_module_init(struct ldb_context *ldb, const char *
ctx->prev = ctx->next = NULL;
ctx->ops = &operational_ops;
+ /* setup some standard attribute handlers */
+ ldb_set_attrib_handler_syntax(ldb, "whenCreated", LDB_SYNTAX_UTC_TIME);
+ ldb_set_attrib_handler_syntax(ldb, "whenChanged", LDB_SYNTAX_UTC_TIME);
+ ldb_set_attrib_handler_syntax(ldb, "subschemaSubentry", LDB_SYNTAX_DN);
+ ldb_set_attrib_handler_syntax(ldb, "structuralObjectClass", LDB_SYNTAX_OBJECTCLASS);
+
return ctx;
}
diff --git a/source4/lib/ldb/modules/rdn_name.c b/source4/lib/ldb/modules/rdn_name.c
index c8f2ebaabd..c51aa74244 100644
--- a/source4/lib/ldb/modules/rdn_name.c
+++ b/source4/lib/ldb/modules/rdn_name.c
@@ -120,11 +120,9 @@ static int rdn_name_add_record(struct ldb_module *module, const struct ldb_messa
}
}
if (i == attribute->num_values) {
- char *error_string = talloc_asprintf(module, "RDN mismatch on %s: %s", ldb_dn_linearize(msg2, msg2->dn), rdn->name);
- if (error_string) {
- ldb_set_errstring(module, error_string);
- ldb_debug(module->ldb, LDB_DEBUG_FATAL, "%s\n", error_string);
- }
+ ldb_debug_set(module->ldb, LDB_DEBUG_FATAL,
+ "RDN mismatch on %s: %s",
+ ldb_dn_linearize(msg2, msg2->dn), rdn->name);
talloc_free(msg2);
return -1;
}