dsdb: Avoid ldb_dn_validate() call on trusted input when not required
authorAndrew Bartlett <abartlet@samba.org>
Thu, 1 Sep 2016 02:54:25 +0000 (14:54 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 27 Sep 2016 18:47:34 +0000 (20:47 +0200)
This call is very costly, because of the time required
to strictly check the syntax of the extended DN components.

This allows a 20% decrease in time taken for some link-heavy tests.

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Autobuild-User(master): Andrew Bartlett <abartlet@samba.org>
Autobuild-Date(master): Tue Sep 27 20:47:34 CEST 2016 on sn-devel-144

source4/dsdb/common/dsdb_dn.c
source4/dsdb/samdb/ldb_modules/extended_dn_out.c

index ccfbe365089dcac2e58081c2e009d279f7ad5023..0c55c0b24dfcb6a2010f2841989017c5082a60da 100644 (file)
@@ -71,8 +71,8 @@ struct dsdb_dn *dsdb_dn_construct(TALLOC_CTX *mem_ctx, struct ldb_dn *dn, DATA_B
        return dsdb_dn_construct_internal(mem_ctx, dn, extra_part, dn_format, oid);
 }
 
-struct dsdb_dn *dsdb_dn_parse(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, 
-                             const struct ldb_val *dn_blob, const char *dn_oid)
+struct dsdb_dn *dsdb_dn_parse_trusted(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, 
+                                     const struct ldb_val *dn_blob, const char *dn_oid)
 {
        struct dsdb_dn *dsdb_dn;
        struct ldb_dn *dn;
@@ -97,7 +97,7 @@ struct dsdb_dn *dsdb_dn_parse(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
        case DSDB_NORMAL_DN:
        {
                dn = ldb_dn_from_ldb_val(mem_ctx, ldb, dn_blob);
-               if (!dn || !ldb_dn_validate(dn)) {
+               if (!dn) {
                        talloc_free(dn);
                        return NULL;
                }
@@ -204,7 +204,7 @@ struct dsdb_dn *dsdb_dn_parse(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
        dval.length = strlen(dn_str);
                
        dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &dval);
-       if (!dn || !ldb_dn_validate(dn)) {
+       if (!dn) {
                DEBUG(10, (__location__ ": err\n"));
                goto failed;
        }
@@ -219,6 +219,22 @@ failed:
        return NULL;
 }
 
+struct dsdb_dn *dsdb_dn_parse(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, 
+                             const struct ldb_val *dn_blob, const char *dn_oid)
+{
+       struct dsdb_dn *dsdb_dn = dsdb_dn_parse_trusted(mem_ctx, ldb,
+                                                       dn_blob, dn_oid);
+       if (dsdb_dn == NULL) {
+               return NULL;
+       }
+       if (ldb_dn_validate(dsdb_dn->dn) == false) {
+               DEBUG(10, ("could not parse %.*s as a %s DN",
+                          (int)dn_blob->length, dn_blob->data,
+                          dn_oid));
+               return NULL;
+       }
+       return dsdb_dn;
+}
 
 static char *dsdb_dn_get_with_postfix(TALLOC_CTX *mem_ctx, 
                                     struct dsdb_dn *dsdb_dn,
index d29a50ce05369bfca46571c0668b5f701ea92b3a..ad4603fbbb953d9762a2de20bf6803b5592ada1a 100644 (file)
@@ -548,9 +548,9 @@ static int extended_callback(struct ldb_request *req, struct ldb_reply *ares,
                        }
 
 
-                       dsdb_dn = dsdb_dn_parse(msg, ldb, plain_dn, attribute->syntax->ldap_oid);
+                       dsdb_dn = dsdb_dn_parse_trusted(msg, ldb, plain_dn, attribute->syntax->ldap_oid);
 
-                       if (!dsdb_dn || !ldb_dn_validate(dsdb_dn->dn)) {
+                       if (!dsdb_dn) {
                                ldb_asprintf_errstring(ldb, 
                                                       "could not parse %.*s in %s on %s as a %s DN", 
                                                       (int)plain_dn->length, plain_dn->data,
@@ -572,13 +572,6 @@ static int extended_callback(struct ldb_request *req, struct ldb_reply *ares,
                                talloc_free(hex_string);
                        }
 
-                       /* don't let users see the internal extended
-                          GUID components */
-                       if (!have_reveal_control) {
-                               const char *accept[] = { "GUID", "SID", NULL };
-                               ldb_dn_extended_filter(dn, accept);
-                       }
-
                        if (p->normalise) {
                                ret = dsdb_fix_dn_rdncase(ldb, dn);
                                if (ret != LDB_SUCCESS) {
@@ -633,6 +626,21 @@ static int extended_callback(struct ldb_request *req, struct ldb_reply *ares,
                        }
                        
                        if (make_extended_dn) {
+                               if (!ldb_dn_validate(dsdb_dn->dn)) {
+                                       ldb_asprintf_errstring(ldb, 
+                                                              "could not parse %.*s in %s on %s as a %s DN", 
+                                                              (int)plain_dn->length, plain_dn->data,
+                                                              msg->elements[i].name, ldb_dn_get_linearized(msg->dn),
+                                                              attribute->syntax->ldap_oid);
+                                       talloc_free(dsdb_dn);
+                                       return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_INVALID_DN_SYNTAX);
+                               }
+                               /* don't let users see the internal extended
+                                  GUID components */
+                               if (!have_reveal_control) {
+                                       const char *accept[] = { "GUID", "SID", NULL };
+                                       ldb_dn_extended_filter(dn, accept);
+                               }
                                dn_str = dsdb_dn_get_extended_linearized(msg->elements[i].values,
                                                                         dsdb_dn, ac->extended_type);
                        } else {