From 3f7dcaceba0adbc4a436780bad776255425bf1b2 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 15 Nov 2007 01:12:10 +0100 Subject: r25957: Rework the cracknames code to use less gendb_search() and instead call ldb_search_exp_fmt(). While it is a bit more verbose to code with, it returns better error codes, and allows us to handle the case where the base DN doesn't exist better. Andrew Bartlett (This used to be commit be6ef043a3f811e6b08d3e5fe7094a72d974134a) --- source4/dsdb/samdb/cracknames.c | 163 ++++++++++++++++++++++++++++------------ 1 file changed, 116 insertions(+), 47 deletions(-) (limited to 'source4/dsdb/samdb/cracknames.c') diff --git a/source4/dsdb/samdb/cracknames.c b/source4/dsdb/samdb/cracknames.c index 3754be2e96..a4565844ec 100644 --- a/source4/dsdb/samdb/cracknames.c +++ b/source4/dsdb/samdb/cracknames.c @@ -107,12 +107,12 @@ static enum drsuapi_DsNameStatus LDB_lookup_spn_alias(krb5_context context, stru ret = ldb_search(ldb_ctx, service_dn, LDB_SCOPE_BASE, "(objectClass=nTDSService)", directory_attrs, &res); - if (ret != LDB_SUCCESS) { + if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) { DEBUG(1, ("ldb_search: dn: %s not found: %s", service_dn_str, ldb_errstring(ldb_ctx))); return DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; - } else if (res->count != 1) { + } else if (ret == LDB_ERR_NO_SUCH_OBJECT || res->count != 1) { talloc_free(res); - DEBUG(1, ("ldb_search: dn: %s found %d times!", service_dn_str, res->count)); + DEBUG(1, ("ldb_search: dn: %s not found", service_dn_str)); return DRSUAPI_DS_NAME_STATUS_NOT_FOUND; } talloc_steal(tmp_ctx, res); @@ -269,7 +269,7 @@ static WERROR DsCrackNameUPN(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, char **realm; char *unparsed_name_short; const char *domain_attrs[] = { NULL }; - struct ldb_message **domain_res = NULL; + struct ldb_result *domain_res = NULL; /* Prevent recursion */ if (!name) { @@ -284,26 +284,28 @@ static WERROR DsCrackNameUPN(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, return WERR_OK; } - domain_filter = NULL; realm = krb5_princ_realm(smb_krb5_context->krb5_context, principal); - domain_filter = talloc_asprintf(mem_ctx, - "(&(&(|(&(dnsRoot=%s)(nETBIOSName=*))(nETBIOSName=%s))(objectclass=crossRef))(ncName=*))", - ldb_binary_encode_string(mem_ctx, *realm), - ldb_binary_encode_string(mem_ctx, *realm)); - - ldb_ret = gendb_search(sam_ctx, mem_ctx, samdb_partitions_dn(sam_ctx, mem_ctx), - &domain_res, domain_attrs, - "%s", domain_filter); - switch (ldb_ret) { + + ldb_ret = ldb_search_exp_fmt(sam_ctx, mem_ctx, &domain_res, + samdb_partitions_dn(sam_ctx, mem_ctx), + LDB_SCOPE_ONELEVEL, + domain_attrs, + "(&(&(|(&(dnsRoot=%s)(nETBIOSName=*))(nETBIOSName=%s))(objectclass=crossRef))(ncName=*))", + ldb_binary_encode_string(mem_ctx, *realm), + ldb_binary_encode_string(mem_ctx, *realm)); + + if (ldb_ret != LDB_SUCCESS) { + DEBUG(2, ("DsCrackNameUPN domain ref search failed: %s", ldb_errstring(sam_ctx))); + info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; + return WERR_OK; + } + + switch (domain_res->count) { case 1: break; case 0: return dns_domain_from_principal(mem_ctx, smb_krb5_context, name, info1); - case -1: - DEBUG(2, ("DsCrackNameUPN domain ref search failed: %s", ldb_errstring(sam_ctx))); - info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; - return WERR_OK; default: info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE; return WERR_OK; @@ -321,6 +323,9 @@ static WERROR DsCrackNameUPN(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, /* This may need to be extended for more userPrincipalName variations */ result_filter = talloc_asprintf(mem_ctx, "(&(objectClass=user)(samAccountName=%s))", ldb_binary_encode_string(mem_ctx, unparsed_name_short)); + + domain_filter = talloc_asprintf(mem_ctx, "(dn=%s)", ldb_dn_get_linearized(domain_res->msgs[0]->dn)); + if (!result_filter || !domain_filter) { free(unparsed_name_short); return WERR_NOMEM; @@ -666,15 +671,15 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ struct drsuapi_DsNameInfo1 *info1) { int ldb_ret; - struct ldb_message **domain_res = NULL; + struct ldb_result *domain_res = NULL; const char * const *domain_attrs; const char * const *result_attrs; struct ldb_message **result_res = NULL; struct ldb_message *result = NULL; struct ldb_dn *result_basedn = NULL; - struct ldb_dn *partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx); int i; char *p; + struct ldb_dn *partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx); const char * const _domain_attrs_1779[] = { "ncName", "dnsRoot", NULL}; const char * const _result_attrs_null[] = { NULL }; @@ -725,24 +730,30 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ if (domain_filter) { /* if we have a domain_filter look it up and set the result_basedn and the dns_domain_name */ - ldb_ret = gendb_search(sam_ctx, mem_ctx, partitions_basedn, &domain_res, domain_attrs, - "%s", domain_filter); - switch (ldb_ret) { + ldb_ret = ldb_search_exp_fmt(sam_ctx, mem_ctx, &domain_res, + partitions_basedn, + LDB_SCOPE_ONELEVEL, + domain_attrs, + "%s", domain_filter); + + if (ldb_ret != LDB_SUCCESS) { + DEBUG(2, ("DsCrackNameOneFilter domain ref search failed: %s", ldb_errstring(sam_ctx))); + info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; + return WERR_OK; + } + + switch (domain_res->count) { case 1: break; case 0: info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; return WERR_OK; - case -1: - DEBUG(2, ("DsCrackNameOneFilter domain ref search failed: %s", ldb_errstring(sam_ctx))); - info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; - return WERR_OK; default: info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE; return WERR_OK; } - info1->dns_domain_name = samdb_result_string(domain_res[0], "dnsRoot", NULL); + info1->dns_domain_name = samdb_result_string(domain_res->msgs[0], "dnsRoot", NULL); W_ERROR_HAVE_NO_MEMORY(info1->dns_domain_name); info1->status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY; } else { @@ -751,16 +762,24 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ } if (result_filter) { + int ret; + struct ldb_result *res; if (domain_res) { - result_basedn = samdb_result_dn(sam_ctx, mem_ctx, domain_res[0], "ncName", NULL); + result_basedn = samdb_result_dn(sam_ctx, mem_ctx, domain_res->msgs[0], "ncName", NULL); - ldb_ret = gendb_search(sam_ctx, mem_ctx, result_basedn, &result_res, - result_attrs, "%s", result_filter); + ret = ldb_search_exp_fmt(sam_ctx, mem_ctx, &res, + result_basedn, LDB_SCOPE_SUBTREE, + result_attrs, "%s", result_filter); + if (ret != LDB_SUCCESS) { + talloc_free(result_res); + info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; + return WERR_OK; + } + ldb_ret = res->count; + result_res = res->msgs; } else { /* search with the 'phantom root' flag */ struct ldb_request *req; - int ret; - struct ldb_result *res; res = talloc_zero(mem_ctx, struct ldb_result); W_ERROR_HAVE_NO_MEMORY(res); @@ -810,7 +829,7 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ ldb_ret = gendb_search_dn(sam_ctx, mem_ctx, name_dn, &result_res, result_attrs); } else if (domain_res) { - name_dn = samdb_result_dn(sam_ctx, mem_ctx, domain_res[0], "ncName", NULL); + name_dn = samdb_result_dn(sam_ctx, mem_ctx, domain_res->msgs[0], "ncName", NULL); ldb_ret = gendb_search_dn(sam_ctx, mem_ctx, name_dn, &result_res, result_attrs); } else { @@ -909,13 +928,30 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ const char *_acc = "", *_dom = ""; if (samdb_find_attribute(sam_ctx, result, "objectClass", "domain")) { - ldb_ret = gendb_search(sam_ctx, mem_ctx, partitions_basedn, &domain_res, domain_attrs, - "(ncName=%s)", ldb_dn_get_linearized(result->dn)); - if (ldb_ret != 1) { + + ldb_ret = ldb_search_exp_fmt(sam_ctx, mem_ctx, &domain_res, + partitions_basedn, + LDB_SCOPE_ONELEVEL, + domain_attrs, + "(ncName=%s)", ldb_dn_get_linearized(result->dn)); + + if (ldb_ret != LDB_SUCCESS) { + DEBUG(2, ("DsCrackNameOneFilter domain ref search failed: %s", ldb_errstring(sam_ctx))); + info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; + return WERR_OK; + } + + switch (domain_res->count) { + case 1: + break; + case 0: info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; return WERR_OK; + default: + info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE; + return WERR_OK; } - _dom = samdb_result_string(domain_res[0], "nETBIOSName", NULL); + _dom = samdb_result_string(domain_res->msgs[0], "nETBIOSName", NULL); W_ERROR_HAVE_NO_MEMORY(_dom); } else { _acc = samdb_result_string(result, "sAMAccountName", NULL); @@ -927,26 +963,59 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ _dom = "BUILTIN"; } else { const char *attrs[] = { NULL }; - struct ldb_message **domain_res2; + struct ldb_result *domain_res2; struct dom_sid *dom_sid = dom_sid_dup(mem_ctx, sid); if (!dom_sid) { return WERR_OK; } dom_sid->num_auths--; - ldb_ret = gendb_search(sam_ctx, mem_ctx, NULL, &domain_res, attrs, - "(&(objectSid=%s)(objectClass=domain))", ldap_encode_ndr_dom_sid(mem_ctx, dom_sid)); - if (ldb_ret != 1) { - info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; + ldb_ret = ldb_search_exp_fmt(sam_ctx, mem_ctx, &domain_res, + NULL, + LDB_SCOPE_BASE, + attrs, + "(&(objectSid=%s)(objectClass=domain))", + ldap_encode_ndr_dom_sid(mem_ctx, dom_sid)); + + if (ldb_ret != LDB_SUCCESS) { + DEBUG(2, ("DsCrackNameOneFilter domain search failed: %s", ldb_errstring(sam_ctx))); + info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; return WERR_OK; } - ldb_ret = gendb_search(sam_ctx, mem_ctx, partitions_basedn, &domain_res2, domain_attrs, - "(ncName=%s)", ldb_dn_get_linearized(domain_res[0]->dn)); - if (ldb_ret != 1) { + + switch (domain_res->count) { + case 1: + break; + case 0: info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; return WERR_OK; + default: + info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE; + return WERR_OK; } + + ldb_ret = ldb_search_exp_fmt(sam_ctx, mem_ctx, &domain_res2, + partitions_basedn, + LDB_SCOPE_ONELEVEL, + domain_attrs, + "(ncName=%s)", ldb_dn_get_linearized(domain_res->msgs[0]->dn)); - _dom = samdb_result_string(domain_res2[0], "nETBIOSName", NULL); + if (ldb_ret != LDB_SUCCESS) { + DEBUG(2, ("DsCrackNameOneFilter domain ref search failed: %s", ldb_errstring(sam_ctx))); + info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; + return WERR_OK; + } + + switch (domain_res2->count) { + case 1: + break; + case 0: + info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; + return WERR_OK; + default: + info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE; + return WERR_OK; + } + _dom = samdb_result_string(domain_res2->msgs[0], "nETBIOSName", NULL); W_ERROR_HAVE_NO_MEMORY(_dom); } } -- cgit