Merge commit 'release-4-0-0alpha1' into v4-0-test
[ira/wip.git] / source4 / lib / ldb / common / ldb_dn.c
index 3f66943ad22e7b4095718eb5af684b0475f38a75..f0bd72e0098dfa3eb8a261b45d5bb4ea9a679b5e 100644 (file)
@@ -10,7 +10,7 @@
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
-   version 2 of the License, or (at your option) any later version.
+   version 3 of the License, or (at your option) any later version.
 
    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,8 +18,7 @@
    Lesser General Public License for more details.
 
    You should have received a copy of the GNU Lesser General Public
-   License along with this library; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */
 
 /*
@@ -34,9 +33,8 @@
  *  Author: Simo Sorce
  */
 
-#include "includes.h"
+#include "ldb_includes.h"
 #include <ctype.h>
-#include "ldb/include/includes.h"
 
 #define LDB_DN_NULL_FAILED(x) if (!(x)) goto failed
 
@@ -93,6 +91,16 @@ struct ldb_dn *ldb_dn_new(void *mem_ctx, struct ldb_context *ldb, const char *st
                         * exploded_dn control is used */
                        dn->special = true;
                        /* FIXME: add a GUID string to ldb_dn structure */
+               } else if (strncasecmp(strdn, "<SID=", 8) == 0) {
+                       /* this is special DN returned when the
+                        * exploded_dn control is used */
+                       dn->special = true;
+                       /* FIXME: add a SID string to ldb_dn structure */
+               } else if (strncasecmp(strdn, "<WKGUID=", 8) == 0) {
+                       /* this is special DN returned when the
+                        * exploded_dn control is used */
+                       dn->special = true;
+                       /* FIXME: add a WKGUID string to ldb_dn structure */
                }
                dn->linearized = talloc_strdup(dn, strdn);
        } else {
@@ -133,6 +141,16 @@ struct ldb_dn *ldb_dn_new_fmt(void *mem_ctx, struct ldb_context *ldb, const char
                 * exploded_dn control is used */
                dn->special = true;
                /* FIXME: add a GUID string to ldb_dn structure */
+       } else if (strncasecmp(strdn, "<SID=", 8) == 0) {
+               /* this is special DN returned when the
+                * exploded_dn control is used */
+               dn->special = true;
+               /* FIXME: add a SID string to ldb_dn structure */
+       } else if (strncasecmp(strdn, "<WKGUID=", 8) == 0) {
+               /* this is special DN returned when the
+                * exploded_dn control is used */
+               dn->special = true;
+               /* FIXME: add a WKGUID string to ldb_dn structure */
        }
        dn->linearized = strdn;
 
@@ -251,6 +269,9 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
 
        /* Components data space is allocated here once */
        data = talloc_array(dn->components, char, strlen(dn->linearized) + 1);
+       if (!data) {
+               return false;
+       }
 
        p = dn->linearized;
        in_attr = true;
@@ -270,6 +291,12 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
                                /* first char */
                                trim = false;
 
+                               if (!isascii(*p)) {
+                                       /* attr names must be ascii only */
+                                       dn->invalid = true;
+                                       goto failed;
+                               }
+
                                if (isdigit(*p)) {
                                        is_oid = true;
                                } else
@@ -316,6 +343,12 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
                                continue;
                        }
 
+                       if (!isascii(*p)) {
+                               /* attr names must be ascii only */
+                               dn->invalid = true;
+                               goto failed;
+                       }
+
                        if (is_oid && ( ! (isdigit(*p) || (*p == '.')))) {
                                /* not a digit nor a dot, invalid attribute oid */
                                dn->invalid = true;
@@ -595,17 +628,17 @@ static bool ldb_dn_casefold_internal(struct ldb_dn *dn)
        }
 
        for (i = 0; i < dn->comp_num; i++) {
-               const struct ldb_attrib_handler *h;
+               const struct ldb_schema_attribute *a;
 
                dn->components[i].cf_name = ldb_attr_casefold(dn->components, dn->components[i].name);
                if (!dn->components[i].cf_name) {
                        goto failed;
                }
 
-               h = ldb_attrib_handler(dn->ldb, dn->components[i].cf_name);
-               ret = h->canonicalise_fn(dn->ldb, dn->components,
-                                        &(dn->components[i].value),
-                                        &(dn->components[i].cf_value));
+               a = ldb_schema_attribute_by_name(dn->ldb, dn->components[i].cf_name);
+               ret = a->syntax->canonicalise_fn(dn->ldb, dn->components,
+                                                &(dn->components[i].value),
+                                                &(dn->components[i].cf_value));
                if (ret != 0) {
                        goto failed;
                }
@@ -630,7 +663,7 @@ const char *ldb_dn_get_casefold(struct ldb_dn *dn)
 
        if (dn->casefold) return dn->casefold;
 
-       if (dn->special) {
+       if (dn->special) { 
                dn->casefold = talloc_strdup(dn, dn->linearized);
                if (!dn->casefold) return NULL;
                dn->valid_case = true;
@@ -642,10 +675,14 @@ const char *ldb_dn_get_casefold(struct ldb_dn *dn)
        }
 
        if (dn->comp_num == 0) {
-               dn->casefold = talloc_strdup(dn, "");
-               if (!dn->casefold) return NULL;
-               dn->valid_case = true;
-               return dn->casefold;
+               if (dn->linearized && dn->linearized[0] == '\0') {
+                       /* hmm a NULL dn, should we faild casefolding ? */
+                       dn->casefold = talloc_strdup(dn, "");
+                       return dn->casefold;
+               }
+               /* A DN must be NULL, special, or have components */
+               dn->invalid = true;
+               return NULL;
        }
 
        /* calculate maximum possible length of DN */
@@ -961,7 +998,11 @@ bool ldb_dn_add_base(struct ldb_dn *dn, struct ldb_dn *base)
                }
 
                if (dn->casefold && s) {
-                       t = talloc_asprintf(dn, "%s,%s", dn->casefold, s);
+                       if (*dn->casefold) {
+                               t = talloc_asprintf(dn, "%s,%s", dn->casefold, s);
+                       } else {
+                               t = talloc_strdup(dn, s);
+                       }
                        LDB_FREE(dn->casefold);
                        dn->casefold = t;
                }
@@ -974,7 +1015,11 @@ bool ldb_dn_add_base(struct ldb_dn *dn, struct ldb_dn *base)
                        return false;
                }
                
-               t = talloc_asprintf(dn, "%s,%s", dn->linearized, s);
+               if (*dn->linearized) {
+                       t = talloc_asprintf(dn, "%s,%s", dn->linearized, s);
+               } else {
+                       t = talloc_strdup(dn, s);
+               }
                if ( ! t) {
                        dn->invalid = true;
                        return false;
@@ -1234,6 +1279,7 @@ static char *ldb_dn_canonical(void *mem_ctx, struct ldb_dn *dn, int ex_format) {
        int i;
        TALLOC_CTX *tmpctx;
        char *cracked = NULL;
+       const char *format = (ex_format ? "\n" : "/" );
  
        if ( ! ldb_dn_validate(dn)) {
                return NULL;
@@ -1260,32 +1306,23 @@ static char *ldb_dn_canonical(void *mem_ctx, struct ldb_dn *dn, int ex_format) {
 
        /* Only domain components?  Finish here */
        if (i < 0) {
-               if (ex_format) {
-                       cracked = talloc_asprintf(tmpctx, "%s\n", cracked);
-               } else {
-                       cracked = talloc_asprintf(tmpctx, "%s/", cracked);
-               }
+               cracked = talloc_strdup_append_buffer(cracked, format);
                talloc_steal(mem_ctx, cracked);
                goto done;
        }
 
        /* Now walk backwards appending remaining components */
        for (; i > 0; i--) {
-               cracked = talloc_asprintf(tmpctx, "%s/%s", cracked
-                                         ldb_dn_escape_value(tmpctx, dn->components[i].value));
+               cracked = talloc_asprintf_append_buffer(cracked, "/%s"
+                                                       ldb_dn_escape_value(tmpctx, dn->components[i].value));
                if (!cracked) {
                        goto done;
                }
        }
 
        /* Last one, possibly a newline for the 'ex' format */
-       if (ex_format) {
-               cracked = talloc_asprintf(tmpctx, "%s\n%s", cracked, 
-                                         ldb_dn_escape_value(tmpctx, dn->components[i].value));
-       } else {
-               cracked = talloc_asprintf(tmpctx, "%s/%s", cracked, 
-                                         ldb_dn_escape_value(tmpctx, dn->components[i].value));
-       }
+       cracked = talloc_asprintf_append_buffer(cracked, "%s%s", format,
+                                               ldb_dn_escape_value(tmpctx, dn->components[i].value));
 
        talloc_steal(mem_ctx, cracked);
 done:
@@ -1386,6 +1423,7 @@ int ldb_dn_set_component(struct ldb_dn *dn, int num, const char *name, const str
                dn->valid_case = false;
        }
        LDB_FREE(dn->casefold);
+       LDB_FREE(dn->linearized);
 
        return LDB_SUCCESS;
 }