From 3d05128da085a1d8873942d205d3ccf843969b98 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 1 Sep 2016 14:54:25 +1200 Subject: [PATCH] dsdb: Avoid ldb_dn_validate() call on trusted input when not required 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 Reviewed-by: Garming Sam Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Tue Sep 27 20:47:34 CEST 2016 on sn-devel-144 --- source4/dsdb/common/dsdb_dn.c | 24 ++++++++++++++--- .../dsdb/samdb/ldb_modules/extended_dn_out.c | 26 ++++++++++++------- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/source4/dsdb/common/dsdb_dn.c b/source4/dsdb/common/dsdb_dn.c index ccfbe365089..0c55c0b24df 100644 --- a/source4/dsdb/common/dsdb_dn.c +++ b/source4/dsdb/common/dsdb_dn.c @@ -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, diff --git a/source4/dsdb/samdb/ldb_modules/extended_dn_out.c b/source4/dsdb/samdb/ldb_modules/extended_dn_out.c index d29a50ce053..ad4603fbbb9 100644 --- a/source4/dsdb/samdb/ldb_modules/extended_dn_out.c +++ b/source4/dsdb/samdb/ldb_modules/extended_dn_out.c @@ -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 {