summaryrefslogtreecommitdiff
path: root/source4/dsdb/samdb
diff options
context:
space:
mode:
Diffstat (limited to 'source4/dsdb/samdb')
-rw-r--r--source4/dsdb/samdb/cracknames.c108
-rw-r--r--source4/dsdb/samdb/samdb.c61
2 files changed, 144 insertions, 25 deletions
diff --git a/source4/dsdb/samdb/cracknames.c b/source4/dsdb/samdb/cracknames.c
index 64bc812022..aa4b2fe121 100644
--- a/source4/dsdb/samdb/cracknames.c
+++ b/source4/dsdb/samdb/cracknames.c
@@ -306,24 +306,58 @@ WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
/* here we need to set the domain_filter and/or the result_filter */
switch (format_offered) {
- case DRSUAPI_DS_NAME_FORMAT_CANONICAL: {
- char *str;
+ case DRSUAPI_DS_NAME_FORMAT_CANONICAL:
+ case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX:
+ {
+ char *str, *s, *account;
+
+ if (strlen(name) == 0) {
+ info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
+ return WERR_OK;
+ }
str = talloc_strdup(mem_ctx, name);
W_ERROR_HAVE_NO_MEMORY(str);
- if (strlen(str) == 0 || str[strlen(str)-1] != '/') {
+ if (format_offered == DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX) {
+ /* Look backwards for the \n, and replace it with / */
+ s = strrchr(str, '\n');
+ if (!s) {
+ info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
+ return WERR_OK;
+ }
+ s[0] = '/';
+ }
+
+ s = strchr(str, '/');
+ if (!s) {
+ /* there must be at least one / */
info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
return WERR_OK;
}
- str[strlen(str)-1] = '\0';
-
- domain_filter = talloc_asprintf(mem_ctx,
- "(&(&(&(dnsRoot=%s)(objectclass=crossRef)))(nETBIOSName=*)(ncName=*))",
- ldb_binary_encode_string(mem_ctx, str));
+ s[0] = '\0';
+ s++;
+
+ domain_filter = talloc_asprintf(mem_ctx, "(&(objectClass=crossRef)(ncName=%s))",
+ ldb_dn_get_linearized(samdb_dns_domain_to_dn(sam_ctx, mem_ctx, str)));
W_ERROR_HAVE_NO_MEMORY(domain_filter);
-
+
+ /* There may not be anything after the domain component (search for the domain itself) */
+ if (s[0]) {
+
+ account = strrchr(s, '/');
+ if (!account) {
+ account = s;
+ } else {
+ account++;
+ }
+ account = ldb_binary_encode_string(mem_ctx, account);
+ W_ERROR_HAVE_NO_MEMORY(account);
+ result_filter = talloc_asprintf(mem_ctx, "(name=%s)",
+ account);
+ W_ERROR_HAVE_NO_MEMORY(result_filter);
+ }
break;
}
case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT: {
@@ -586,8 +620,10 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_
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;
struct ldb_dn *partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx);
+ int i;
const char * const _domain_attrs_1779[] = { "ncName", "dnsRoot", NULL};
const char * const _result_attrs_null[] = { NULL };
@@ -647,6 +683,7 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_
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:
@@ -674,6 +711,7 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_
switch (ldb_ret) {
case 1:
+ result = result_res[0];
break;
case 0:
switch (format_offered) {
@@ -691,24 +729,52 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_
info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
return WERR_OK;
case -1:
+ DEBUG(2, ("DsCrackNameOneFilter result 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;
+ switch (format_offered) {
+ case DRSUAPI_DS_NAME_FORMAT_CANONICAL:
+ case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX:
+ {
+ const char *canonical_name;
+ /* We may need to manually filter further */
+ for (i = 0; i < ldb_ret; i++) {
+ switch (format_offered) {
+ case DRSUAPI_DS_NAME_FORMAT_CANONICAL:
+ canonical_name = ldb_dn_canonical_string(mem_ctx, result_res[i]->dn);
+ break;
+ case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX:
+ canonical_name = ldb_dn_canonical_ex_string(mem_ctx, result_res[i]->dn);
+ break;
+ }
+ if (strcasecmp_m(canonical_name, name) == 0) {
+ result = result_res[i];
+ break;
+ }
+ }
+ if (!result) {
+ info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+ return WERR_OK;
+ }
+ }
+ default:
+ info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
+ return WERR_OK;
+ }
}
- /* here we can use result_res[0] and domain_res[0] */
+ /* here we can use result and domain_res[0] */
switch (format_desired) {
case DRSUAPI_DS_NAME_FORMAT_FQDN_1779: {
- info1->result_name = ldb_dn_alloc_linearized(mem_ctx, result_res[0]->dn);
+ info1->result_name = ldb_dn_alloc_linearized(mem_ctx, result->dn);
W_ERROR_HAVE_NO_MEMORY(info1->result_name);
info1->status = DRSUAPI_DS_NAME_STATUS_OK;
return WERR_OK;
}
case DRSUAPI_DS_NAME_FORMAT_CANONICAL: {
- info1->result_name = samdb_result_string(result_res[0], "canonicalName", NULL);
+ info1->result_name = samdb_result_string(result, "canonicalName", NULL);
info1->status = DRSUAPI_DS_NAME_STATUS_OK;
return WERR_OK;
}
@@ -717,10 +783,10 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_
return DsCrackNameOneSyntactical(mem_ctx,
DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX,
- result_res[0]->dn, name, info1);
+ result->dn, name, info1);
}
case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT: {
- const struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, result_res[0], "objectSid");
+ const struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, result, "objectSid");
const char *_acc = "", *_dom = "";
if (!sid || (sid->num_auths < 4) || (sid->num_auths > 5)) {
@@ -730,7 +796,7 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_
if (sid->num_auths == 4) {
ldb_ret = gendb_search(sam_ctx, mem_ctx, partitions_basedn, &domain_res, domain_attrs,
- "(ncName=%s)", ldb_dn_get_linearized(result_res[0]->dn));
+ "(ncName=%s)", ldb_dn_get_linearized(result->dn));
if (ldb_ret != 1) {
info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
return WERR_OK;
@@ -762,7 +828,7 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_
_dom = samdb_result_string(domain_res2[0], "nETBIOSName", NULL);
W_ERROR_HAVE_NO_MEMORY(_dom);
- _acc = samdb_result_string(result_res[0], "sAMAccountName", NULL);
+ _acc = samdb_result_string(result, "sAMAccountName", NULL);
W_ERROR_HAVE_NO_MEMORY(_acc);
}
@@ -775,7 +841,7 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_
case DRSUAPI_DS_NAME_FORMAT_GUID: {
struct GUID guid;
- guid = samdb_result_guid(result_res[0], "objectGUID");
+ guid = samdb_result_guid(result, "objectGUID");
info1->result_name = GUID_string2(mem_ctx, &guid);
W_ERROR_HAVE_NO_MEMORY(info1->result_name);
@@ -784,9 +850,9 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_
return WERR_OK;
}
case DRSUAPI_DS_NAME_FORMAT_DISPLAY: {
- info1->result_name = samdb_result_string(result_res[0], "displayName", NULL);
+ info1->result_name = samdb_result_string(result, "displayName", NULL);
if (!info1->result_name) {
- info1->result_name = samdb_result_string(result_res[0], "sAMAccountName", NULL);
+ info1->result_name = samdb_result_string(result, "sAMAccountName", NULL);
}
if (!info1->result_name) {
info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
diff --git a/source4/dsdb/samdb/samdb.c b/source4/dsdb/samdb/samdb.c
index 124797d517..19c6ed773d 100644
--- a/source4/dsdb/samdb/samdb.c
+++ b/source4/dsdb/samdb/samdb.c
@@ -1727,6 +1727,45 @@ NTSTATUS samdb_create_foreign_security_principal(struct ldb_context *sam_ctx, TA
return NT_STATUS_OK;
}
+
+/*
+ Find the DN of a domain, assuming it to be a dotted.dns name
+*/
+
+struct ldb_dn *samdb_dns_domain_to_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *dns_domain)
+{
+ int i;
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+ const char *binary_encoded;
+ const char **split_realm;
+ struct ldb_dn *dn;
+
+ if (!tmp_ctx) {
+ return NULL;
+ }
+
+ split_realm = str_list_make(tmp_ctx, dns_domain, ".");
+ if (!split_realm) {
+ talloc_free(tmp_ctx);
+ return NULL;
+ }
+ dn = ldb_dn_new(mem_ctx, ldb, NULL);
+ for (i=0; split_realm[i]; i++) {
+ binary_encoded = ldb_binary_encode_string(tmp_ctx, split_realm[i]);
+ if (!ldb_dn_add_base_fmt(dn, "dc=%s", binary_encoded)) {
+ DEBUG(2, ("Failed to add dc=%s element to DN %s\n",
+ binary_encoded, ldb_dn_get_linearized(dn)));
+ talloc_free(tmp_ctx);
+ return NULL;
+ }
+ }
+ if (!ldb_dn_validate(dn)) {
+ DEBUG(2, ("Failed to validated DN %s\n",
+ ldb_dn_get_linearized(dn)));
+ return NULL;
+ }
+ return dn;
+}
/*
Find the DN of a domain, be it the netbios or DNS name
*/
@@ -1737,6 +1776,9 @@ struct ldb_dn *samdb_domain_to_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
const char * const domain_ref_attrs[] = {
"ncName", NULL
};
+ const char * const domain_ref2_attrs[] = {
+ NULL
+ };
struct ldb_result *res_domain_ref;
char *escaped_domain = ldb_binary_encode_string(mem_ctx, domain_name);
/* find the domain's DN */
@@ -1745,15 +1787,26 @@ struct ldb_dn *samdb_domain_to_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
samdb_partitions_dn(ldb, mem_ctx),
LDB_SCOPE_ONELEVEL,
domain_ref_attrs,
- "(&(&(|(&(dnsRoot=%s)(nETBIOSName=*))(nETBIOSName=%s))(objectclass=crossRef))(ncName=*))",
- escaped_domain, escaped_domain);
+ "(&(nETBIOSName=%s)(objectclass=crossRef))",
+ escaped_domain);
if (ret_domain != 0) {
return NULL;
}
if (res_domain_ref->count == 0) {
- DEBUG(3,("sam_search_user: Couldn't find domain [%s] in samdb.\n",
- domain_name));
+ ret_domain = ldb_search_exp_fmt(ldb, mem_ctx,
+ &res_domain_ref,
+ samdb_dns_domain_to_dn(ldb, mem_ctx, domain_name),
+ LDB_SCOPE_BASE,
+ domain_ref2_attrs,
+ "(objectclass=domain)");
+ if (ret_domain != 0) {
+ return NULL;
+ }
+
+ if (res_domain_ref->count == 1) {
+ return res_domain_ref->msgs[0]->dn;
+ }
return NULL;
}