s4-dsdb: add auto-normalisation of attributes
[amitay/samba.git] / source4 / dsdb / samdb / ldb_modules / objectclass_attrs.c
index 4525cf3dddbdeffce71f8a795e2d1b53a08eb4c4..9893adae93752c353ac976c163acd428d0586dad 100644 (file)
@@ -88,6 +88,45 @@ static int oc_validate_dsheuristics(struct ldb_message_element *el)
        return LDB_SUCCESS;
 }
 
+/*
+  auto normalise values on input
+ */
+static int oc_auto_normalise(struct ldb_context *ldb, const struct dsdb_attribute *attr,
+                            struct ldb_message *msg, struct ldb_message_element *el)
+{
+       int i;
+       bool values_copied = false;
+
+       for (i=0; i<el->num_values; i++) {
+               struct ldb_val v;
+               int ret;
+               ret = attr->ldb_schema_attribute->syntax->canonicalise_fn(ldb, el->values, &el->values[i], &v);
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
+               if (data_blob_cmp(&v, &el->values[i]) == 0) {
+                       /* no need to replace it */
+                       talloc_free(v.data);
+                       continue;
+               }
+
+               /* we need to copy the values array on the first change */
+               if (!values_copied) {
+                       struct ldb_val *v2;
+                       v2 = talloc_array(msg->elements, struct ldb_val, el->num_values);
+                       if (v2 == NULL) {
+                               return ldb_oom(ldb);
+                       }
+                       memcpy(v2, el->values, sizeof(struct ldb_val) * el->num_values);
+                       el->values = v2;
+                       values_copied = true;
+               }
+
+               el->values[i] = v;
+       }
+       return LDB_SUCCESS;
+}
+
 static int attr_handler(struct oc_context *ac)
 {
        struct ldb_context *ldb;
@@ -174,6 +213,14 @@ static int attr_handler(struct oc_context *ac)
                        }
                }
 
+               /* auto normalise some attribute values */
+               if (attr->syntax->auto_normalise) {
+                       ret = oc_auto_normalise(ldb, attr, msg, &msg->elements[i]);
+                       if (ret != LDB_SUCCESS) {
+                               return ret;
+                       }
+               }
+
                /* Substitute the attribute name to match in case */
                msg->elements[i].name = attr->lDAPDisplayName;
        }