r10916: - finished the 'operational' ldb module
authorAndrew Tridgell <tridge@samba.org>
Wed, 12 Oct 2005 07:57:39 +0000 (07:57 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:39:42 +0000 (13:39 -0500)
- removed the timestamps module, replacing it with the operational module

- added a ldb_msg_copy_shallow() function which should be used when a module
  wants to add new elements to a message on add/modify. This is needed
  because the caller might be using a constant structure, or may want to
  re-use the structure again

- enabled the UTC time attribute syntaxes in the operational module
(This used to be commit 61e8b010223ac6a0573185008f3719ba29574688)

source4/lib/ldb/common/ldb_modules.c
source4/lib/ldb/common/ldb_msg.c
source4/lib/ldb/include/ldb_private.h
source4/lib/ldb/modules/operational.c
source4/lib/ldb/modules/rdn_name.c
source4/setup/provision_init.ldif
source4/setup/rootdse.ldif
source4/setup/secrets.ldif

index 5ca666c194e27a2f8220170d40abe78b3ec8d18e..f3ca4df9b4c619a462bdb8bf4b2bde3665f987d4 100644 (file)
@@ -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 },
index 2aef7acc42fc93ec4e951918d062bf7a313f6293..1c7ae3920a964de1a5f2e6328e4e5e52fa79826b 100644 (file)
@@ -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;
index 2367d6c3f800585b8308a3b5343edb0244aec6a6..e444b7235a0df60dd60c5dd8961fc26a6983fea4 100644 (file)
@@ -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);
index 911bc087ca0d16beae2b5138630810609da7058a..d1e83c02e0690bce62361626ac880ad535fb499c 100644 (file)
@@ -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;
 }
index c8f2ebaabdddc446bb835a9514b4b6bb7da5b278..c51aa74244a4367644eb3e1af5f1e30e46a0e89d 100644 (file)
@@ -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;
                }
index 976645e0e73a04a86ae0070abd21b09cc7c9a579..a0cbb6ad7adb205552c6b8660216a295dc2cba34 100644 (file)
@@ -48,5 +48,5 @@ template: groupTemplate
 #Add modules to the list to activate them by default
 #beware often order is important
 dn: @MODULES
-@LIST: samldb,timestamps,objectguid,rdn_name
+@LIST: samldb,operational,objectguid,rdn_name
 
index 534249859a840fc36c3b9fcec6eebf00cdceb919..6c74b5d63104c48893b777920c0a47848b409ffb 100644 (file)
@@ -7,7 +7,7 @@ modifyTimestamp: HIDDEN
 dn: @SUBCLASSES
 
 dn: @MODULES
-@MODULE: timestamps
+@MODULE: operational
 
 dn: cn=rootDSE
 currentTime: _DYNAMIC_
index 9ba095290e43bba793f9f02b8e2b12cde1eecc21..3dcb82dbddeb4d642cbe1b38a4380bce163a2b98 100644 (file)
@@ -11,7 +11,7 @@ sAMAccountName: CASE_INSENSITIVE
 #Add modules to the list to activate them by default
 #beware often order is important
 dn: @MODULES
-@LIST: timestamps
+@LIST: operational
 
 dn: CN=LSA Secrets
 objectClass: top