summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/rpc_server/drsuapi/drsuapi_cracknames.c634
-rw-r--r--source4/torture/rpc/drsuapi.c139
2 files changed, 613 insertions, 160 deletions
diff --git a/source4/rpc_server/drsuapi/drsuapi_cracknames.c b/source4/rpc_server/drsuapi/drsuapi_cracknames.c
index b6a9105be5..35955a71b2 100644
--- a/source4/rpc_server/drsuapi/drsuapi_cracknames.c
+++ b/source4/rpc_server/drsuapi/drsuapi_cracknames.c
@@ -5,6 +5,7 @@
DsCrackNames()
Copyright (C) Stefan Metzmacher 2004
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -27,19 +28,232 @@
#include "rpc_server/common/common.h"
#include "rpc_server/drsuapi/dcesrv_drsuapi.h"
#include "lib/ldb/include/ldb.h"
+#include "system/kerberos.h"
+#include "auth/kerberos/kerberos.h"
+
+static WERROR DsCrackNameOneFilter(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx,
+ struct smb_krb5_context *smb_krb5_context,
+ uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
+ const struct ldb_dn *name_dn, const char *name,
+ const char *domain_filter, const char *result_filter,
+ struct drsuapi_DsNameInfo1 *info1);
+static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx,
+ uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
+ const char *name, struct drsuapi_DsNameInfo1 *info1);
+
+static enum drsuapi_DsNameStatus LDB_lookup_spn_alias(krb5_context context, struct ldb_context *ldb_ctx,
+ TALLOC_CTX *mem_ctx,
+ const struct ldb_dn *base_dn,
+ const char *alias_from,
+ char **alias_to)
+{
+ int i;
+ int count;
+ struct ldb_message **msg;
+ struct ldb_message_element *spnmappings;
+ struct ldb_dn *service_dn = ldb_dn_string_compose(mem_ctx, base_dn,
+ "CN=Directory Service,CN=Windows NT"
+ ",CN=Services,CN=Configuration");
+ char *service_dn_str = ldb_dn_linearize(mem_ctx, service_dn);
+ const char *directory_attrs[] = {
+ "sPNMappings",
+ NULL
+ };
+
+ count = ldb_search(ldb_ctx, service_dn, LDB_SCOPE_BASE, "(objectClass=nTDSService)",
+ directory_attrs, &msg);
+ talloc_steal(mem_ctx, msg);
+
+ if (count < 1) {
+ DEBUG(1, ("ldb_search: dn: %s not found: %d", service_dn_str, count));
+ return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+ } else if (count > 1) {
+ DEBUG(1, ("ldb_search: dn: %s found %d times!", service_dn_str, count));
+ return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+ }
+
+ spnmappings = ldb_msg_find_element(msg[0], "sPNMappings");
+ if (!spnmappings || spnmappings->num_values == 0) {
+ DEBUG(1, ("ldb_search: dn: %s no sPNMappings attribute", service_dn_str));
+ return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+ }
+
+ for (i = 0; i < spnmappings->num_values; i++) {
+ char *mapping, *p, *str;
+ mapping = talloc_strdup(mem_ctx,
+ (const char *)spnmappings->values[i].data);
+ if (!mapping) {
+ DEBUG(1, ("LDB_lookup_spn_alias: ldb_search: dn: %s did not have an sPNMapping", service_dn_str));
+ return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+ }
+
+ /* C string manipulation sucks */
+
+ p = strchr(mapping, '=');
+ if (!p) {
+ DEBUG(1, ("ldb_search: dn: %s sPNMapping malformed: %s",
+ service_dn_str, mapping));
+ return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+ }
+ p[0] = '\0';
+ p++;
+ do {
+ str = p;
+ p = strchr(p, ',');
+ if (p) {
+ p[0] = '\0';
+ p++;
+ }
+ if (strcasecmp(str, alias_from) == 0) {
+ *alias_to = mapping;
+ return 0;
+ }
+ } while (p);
+ }
+ DEBUG(1, ("LDB_lookup_spn_alias: no alias for service %s applicable", alias_from));
+ return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+}
+
+static WERROR DsCrackNameSPNAlias(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx,
+ struct smb_krb5_context *smb_krb5_context,
+ uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
+ const struct ldb_dn *result_basedn,
+ const char *name, struct drsuapi_DsNameInfo1 *info1)
+{
+ WERROR wret;
+ krb5_error_code ret;
+ krb5_principal principal;
+ const char *service;
+ char *new_service;
+ char *new_princ;
+ enum drsuapi_DsNameStatus namestatus;
+
+ /* parse principal */
+ ret = krb5_parse_name_norealm(smb_krb5_context->krb5_context,
+ name, &principal);
+ if (ret) {
+ DEBUG(2, ("Could not parse principal: %s: %s",
+ name, smb_get_krb5_error_message(smb_krb5_context->krb5_context,
+ ret, mem_ctx)));
+ return WERR_NOMEM;
+ }
+
+ /* grab cifs/, http/ etc */
+ if (principal->name.name_string.len < 2) {
+ DEBUG(5, ("could not find principal in DB, alias not applicable"));
+ info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+ return WERR_OK;
+ }
+ service = principal->name.name_string.val[0];
+
+ /* MAP it */
+ namestatus = LDB_lookup_spn_alias(smb_krb5_context->krb5_context,
+ b_state->sam_ctx, mem_ctx,
+ result_basedn,
+ service, &new_service);
+
+ if (namestatus != DRSUAPI_DS_NAME_STATUS_OK) {
+ info1->status = namestatus;
+ return WERR_OK;
+ }
+
+ if (ret != 0) {
+ info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
+ return WERR_OK;
+ }
+
+ /* ooh, very nasty playing around in the Principal... */
+ free(principal->name.name_string.val[0]);
+ principal->name.name_string.val[0] = strdup(new_service);
+ if (!principal->name.name_string.val[0]) {
+ krb5_free_principal(smb_krb5_context->krb5_context, principal);
+ return WERR_NOMEM;
+ }
+
+ ret = krb5_unparse_name_norealm(smb_krb5_context->krb5_context, principal, &new_princ);
+
+ krb5_free_principal(smb_krb5_context->krb5_context, principal);
+
+ if (ret) {
+ return WERR_NOMEM;
+ }
+
+ /* reform principal */
+ wret = DsCrackNameOneName(b_state, mem_ctx, format_flags, format_offered, format_desired,
+ new_princ, info1);
+ free(new_princ);
+ return wret;
+}
+
+static WERROR DsCrackNameUPN(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx,
+ struct smb_krb5_context *smb_krb5_context,
+ uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
+ const char *name, struct drsuapi_DsNameInfo1 *info1)
+{
+ WERROR status;
+ const char *domain_filter = NULL;
+ const char *result_filter = NULL;
+ krb5_error_code ret;
+ krb5_principal principal;
+ char **realm;
+ char *unparsed_name_short;
+
+ /* Prevent recursion */
+ if (!name) {
+ info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+ return WERR_OK;
+ }
+
+ ret = krb5_parse_name(smb_krb5_context->krb5_context, name, &principal);
+ if (ret) {
+ info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+ 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=*))",
+ *realm, *realm);
+ ret = krb5_unparse_name_norealm(smb_krb5_context->krb5_context, principal, &unparsed_name_short);
+ krb5_free_principal(smb_krb5_context->krb5_context, principal);
+
+ if (ret) {
+ free(unparsed_name_short);
+ return WERR_NOMEM;
+ }
+
+ /* This may need to be extended for more userPrincipalName variations */
+ result_filter = talloc_asprintf(mem_ctx, "(&(objectClass=user)(samAccountName=%s))",
+ unparsed_name_short);
+ if (!result_filter || !domain_filter) {
+ free(unparsed_name_short);
+ return WERR_NOMEM;
+ }
+ status = DsCrackNameOneFilter(b_state, mem_ctx,
+ smb_krb5_context,
+ format_flags, format_offered, format_desired,
+ NULL, unparsed_name_short, domain_filter, result_filter,
+ info1);
+ free(unparsed_name_short);
+ return status;
+}
static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx,
- uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
- const char *name, struct drsuapi_DsNameInfo1 *info1)
+ uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
+ const char *name, struct drsuapi_DsNameInfo1 *info1)
{
- int ret;
+ krb5_error_code ret;
const char *domain_filter = NULL;
- const char * const *domain_attrs;
- struct ldb_message **domain_res = NULL;
- const struct ldb_dn *result_basedn = NULL;
const char *result_filter = NULL;
- const char * const *result_attrs;
- struct ldb_message **result_res = NULL;
+ struct ldb_dn *name_dn;
+
+ struct smb_krb5_context *smb_krb5_context;
+ ret = smb_krb5_init_context(mem_ctx, &smb_krb5_context);
+
+ if (ret) {
+ return WERR_NOMEM;
+ }
info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
info1->dns_domain_name = NULL;
@@ -55,64 +269,186 @@ static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_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;
-
- str = talloc_strdup(mem_ctx, name);
- WERR_TALLOC_CHECK(str);
-
- if (strlen(str) == 0 || str[strlen(str)-1] != '/') {
- info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
- return WERR_OK;
- }
+ case DRSUAPI_DS_NAME_FORMAT_CANONICAL: {
+ char *str;
+
+ str = talloc_strdup(mem_ctx, name);
+ WERR_TALLOC_CHECK(str);
+
+ if (strlen(str) == 0 || str[strlen(str)-1] != '/') {
+ 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=*))",
+ str);
+ WERR_TALLOC_CHECK(domain_filter);
+
+ break;
+ }
+ case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT: {
+ char *p;
+ char *domain;
+ const char *account = NULL;
+
+ domain = talloc_strdup(mem_ctx, name);
+ WERR_TALLOC_CHECK(domain);
+
+ p = strchr(domain, '\\');
+ if (!p) {
+ /* invalid input format */
+ info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+ return WERR_OK;
+ }
+ p[0] = '\0';
+
+ if (p[1]) {
+ account = &p[1];
+ }
+
+ domain_filter = talloc_asprintf(mem_ctx,
+ "(&(&(nETBIOSName=%s)(objectclass=crossRef))(ncName=*))",
+ domain);
+ WERR_TALLOC_CHECK(domain_filter);
+ if (account) {
+ result_filter = talloc_asprintf(mem_ctx, "(sAMAccountName=%s)",
+ account);
+ WERR_TALLOC_CHECK(result_filter);
+ }
+
+ talloc_free(domain);
+ break;
+ }
+ case DRSUAPI_DS_NAME_FORMAT_FQDN_1779: {
+ name_dn = ldb_dn_explode(mem_ctx, name);
+ domain_filter = NULL;
+ if (!name_dn) {
+ info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+ return WERR_OK;
+ }
+ break;
+ }
+ case DRSUAPI_DS_NAME_FORMAT_GUID: {
+ struct GUID guid;
+ char *ldap_guid;
+ NTSTATUS nt_status;
+ domain_filter = NULL;
+
+ nt_status = GUID_from_string(name, &guid);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+ return WERR_OK;
+ }
- str[strlen(str)-1] = '\0';
-
- domain_filter = talloc_asprintf(mem_ctx,
- "(&(&(&(dnsRoot=%s)(objectclass=crossRef)))(nETBIOSName=*)(ncName=*))",
- str);
- WERR_TALLOC_CHECK(domain_filter);
-
- break;
+ ldap_guid = ldap_encode_ndr_GUID(mem_ctx, &guid);
+ if (!ldap_guid) {
+ return WERR_NOMEM;
}
- case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT: {
- char *p;
- char *domain;
- const char *account = NULL;
-
- domain = talloc_strdup(mem_ctx, name);
- WERR_TALLOC_CHECK(domain);
-
- p = strchr(domain, '\\');
- if (!p) {
- /* invalid input format */
- info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
- return WERR_OK;
- }
- p[0] = '\0';
-
- if (p[1]) {
- account = &p[1];
- }
-
- domain_filter = talloc_asprintf(mem_ctx,
- "(&(&(nETBIOSName=%s)(objectclass=crossRef))(ncName=*))",
- domain);
- WERR_TALLOC_CHECK(domain_filter);
- if (account) {
- result_filter = talloc_asprintf(mem_ctx, "(sAMAccountName=%s)",
- account);
- WERR_TALLOC_CHECK(result_filter);
- }
-
- talloc_free(domain);
- break;
+ result_filter = talloc_asprintf(mem_ctx, "(objectGUID=%s)",
+ ldap_guid);
+ WERR_TALLOC_CHECK(result_filter);
+ break;
+ }
+
+ case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY: {
+ struct dom_sid *sid = dom_sid_parse_talloc(mem_ctx, name);
+ char *ldap_sid;
+
+ domain_filter = NULL;
+ if (!sid) {
+ info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+ return WERR_OK;
+ }
+ ldap_sid = ldap_encode_ndr_dom_sid(mem_ctx,
+ sid);
+ if (!ldap_sid) {
+ return WERR_NOMEM;
+ }
+ result_filter = talloc_asprintf(mem_ctx, "(objectSid=%s)",
+ ldap_sid);
+ WERR_TALLOC_CHECK(result_filter);
+ break;
+ }
+ case DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL: {
+ krb5_principal principal;
+ char *unparsed_name;
+ ret = krb5_parse_name(smb_krb5_context->krb5_context, name, &principal);
+ if (ret) {
+ info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+ return WERR_OK;
}
- default: {
+
+ domain_filter = NULL;
+
+ ret = krb5_unparse_name(smb_krb5_context->krb5_context, principal, &unparsed_name);
+ if (ret) {
+ krb5_free_principal(smb_krb5_context->krb5_context, principal);
+ return WERR_NOMEM;
+ }
+
+ krb5_free_principal(smb_krb5_context->krb5_context, principal);
+ result_filter = talloc_asprintf(mem_ctx, "(&(objectClass=user)(userPrincipalName=%s))",
+ unparsed_name);
+
+ free(unparsed_name);
+ WERR_TALLOC_CHECK(result_filter);
+ break;
+ }
+ case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL: {
+ krb5_principal principal;
+ char *unparsed_name_short;
+ ret = krb5_parse_name_norealm(smb_krb5_context->krb5_context, name, &principal);
+ if (ret) {
info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
return WERR_OK;
}
+
+ domain_filter = NULL;
+
+ ret = krb5_unparse_name_norealm(smb_krb5_context->krb5_context, principal, &unparsed_name_short);
+ krb5_free_principal(smb_krb5_context->krb5_context, principal);
+ if (ret) {
+ return WERR_NOMEM;
+ }
+
+ result_filter = talloc_asprintf(mem_ctx, "(&(objectClass=user)(servicePrincipalName=%s))",
+ unparsed_name_short);
+ free(unparsed_name_short);
+ WERR_TALLOC_CHECK(result_filter);
+
+ break;
}
+ default: {
+ info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+ return WERR_OK;
+ }
+
+ }
+
+ return DsCrackNameOneFilter(b_state, mem_ctx,
+ smb_krb5_context,
+ format_flags, format_offered, format_desired,
+ name_dn, name,
+ domain_filter, result_filter,
+ info1);
+}
+
+static WERROR DsCrackNameOneFilter(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx,
+ struct smb_krb5_context *smb_krb5_context,
+ uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
+ const struct ldb_dn *name_dn, const char *name,
+ const char *domain_filter, const char *result_filter,
+ struct drsuapi_DsNameInfo1 *info1)
+{
+ int ldb_ret;
+ struct ldb_message **domain_res = NULL;
+ const char * const *domain_attrs;
+ const char * const *result_attrs;
+ struct ldb_message **result_res = NULL;
+ const struct ldb_dn *result_basedn;
/* here we need to set the attrs lists for domain and result lookups */
switch (format_desired) {
@@ -126,7 +462,7 @@ static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX
}
case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT: {
const char * const _domain_attrs[] = { "ncName", "dnsRoot", "nETBIOSName", NULL};
- const char * const _result_attrs[] = { "sAMAccountName", NULL};
+ const char * const _result_attrs[] = { "sAMAccountName", "objectSid", NULL};
domain_attrs = _domain_attrs;
result_attrs = _result_attrs;
@@ -144,21 +480,27 @@ static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX
return WERR_OK;
}
- /* if we have a domain_filter look it up and set the result_basedn and the dns_domain_name */
- ret = gendb_search(b_state->sam_ctx, mem_ctx, NULL, &domain_res, domain_attrs,
- "%s", domain_filter);
- switch (ret) {
- case 1:
- break;
- case 0:
- info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
- return WERR_OK;
- case -1:
- info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
- return WERR_OK;
- default:
- info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
- return WERR_OK;
+ 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(b_state->sam_ctx, mem_ctx, NULL, &domain_res, domain_attrs,
+ "%s", domain_filter);
+ } else {
+ ldb_ret = gendb_search(b_state->sam_ctx, mem_ctx, NULL, &domain_res, domain_attrs,
+ "(ncName=%s)", ldb_dn_linearize(mem_ctx, samdb_base_dn(mem_ctx)));
+ }
+
+ switch (ldb_ret) {
+ case 1:
+ break;
+ case 0:
+ info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+ return WERR_OK;
+ case -1:
+ 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);
@@ -167,67 +509,121 @@ static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX
if (result_filter) {
result_basedn = samdb_result_dn(mem_ctx, domain_res[0], "ncName", NULL);
+
+ ldb_ret = gendb_search(b_state->sam_ctx, mem_ctx, result_basedn, &result_res,
+ result_attrs, "%s", result_filter);
+ } else if (format_offered == DRSUAPI_DS_NAME_FORMAT_FQDN_1779) {
+ ldb_ret = gendb_search_dn(b_state->sam_ctx, mem_ctx, name_dn, &result_res,
+ result_attrs);
+ } else {
+ name_dn = samdb_result_dn(mem_ctx, domain_res[0], "ncName", NULL);
+ ldb_ret = gendb_search_dn(b_state->sam_ctx, mem_ctx, name_dn, &result_res,
+ result_attrs);
+ }
- ret = gendb_search(b_state->sam_ctx, mem_ctx, result_basedn, &result_res,
- result_attrs, "%s", result_filter);
- switch (ret) {
- case 1:
- break;
- case 0:
- return WERR_OK;
- case -1:
- info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
- return WERR_OK;
- default:
- info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
- return WERR_OK;
+ switch (ldb_ret) {
+ case 1:
+ break;
+ case 0:
+ switch (format_offered) {
+ case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL:
+ return DsCrackNameSPNAlias(b_state, mem_ctx,
+ smb_krb5_context,
+ format_flags, format_offered, format_desired,
+ result_basedn, name, info1);
+
+ case DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL:
+ return DsCrackNameUPN(b_state, mem_ctx, smb_krb5_context,
+ format_flags, format_offered, format_desired,
+ name, info1);
}
- } else {
- result_res = domain_res;
+ break;
+ case -1:
+ info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
+ 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] */
switch (format_desired) {
- case DRSUAPI_DS_NAME_FORMAT_FQDN_1779: {
- info1->result_name = ldb_dn_linearize(mem_ctx, result_res[0]->dn);
- WERR_TALLOC_CHECK(info1->result_name);
+ case DRSUAPI_DS_NAME_FORMAT_FQDN_1779: {
+ info1->result_name = ldb_dn_linearize(mem_ctx, result_res[0]->dn);
+ WERR_TALLOC_CHECK(info1->result_name);
- info1->status = DRSUAPI_DS_NAME_STATUS_OK;
+ info1->status = DRSUAPI_DS_NAME_STATUS_OK;
+ return WERR_OK;
+ }
+ case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT: {
+ const struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, result_res[0], "objectSid");
+ const char *_dom;
+ const char *_acc = "";
+
+ if ((sid->num_auths < 4) || (sid->num_auths > 5)) {
+ info1->status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING;
return WERR_OK;
}
- case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT: {
- const char *_dom;
- const char *_acc = "";
+ if (sid->num_auths == 4) {
+ ldb_ret = gendb_search(b_state->sam_ctx, mem_ctx, NULL, &domain_res, domain_attrs,
+ "(ncName=%s)", ldb_dn_linearize(mem_ctx, result_res[0]->dn));
+ if (ldb_ret != 1) {
+ info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+ return WERR_OK;
+ }
_dom = samdb_result_string(domain_res[0], "nETBIOSName", NULL);
WERR_TALLOC_CHECK(_dom);
-
- if (result_filter) {
- _acc = samdb_result_string(result_res[0], "sAMAccountName", NULL);
- WERR_TALLOC_CHECK(_acc);
+
+ } else if (sid->num_auths == 5) {
+ const char *attrs[] = { NULL };
+ struct ldb_message **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(b_state->sam_ctx, mem_ctx, NULL, &domain_res2, attrs,
+ "(objectSid=%s)", ldap_encode_ndr_dom_sid(mem_ctx, dom_sid));
+ if (ldb_ret != 1) {
+ info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+ return WERR_OK;
+ }
+ ldb_ret = gendb_search(b_state->sam_ctx, mem_ctx, NULL, &domain_res, domain_attrs,
+ "(ncName=%s)", ldb_dn_linearize(mem_ctx, domain_res2[0]->dn));
+ if (ldb_ret != 1) {
+ info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+ return WERR_OK;
+ }
+
+ _dom = samdb_result_string(domain_res2[0], "nETBIOSName", NULL);
+ WERR_TALLOC_CHECK(_dom);
- info1->result_name = talloc_asprintf(mem_ctx, "%s\\%s", _dom, _acc);
- WERR_TALLOC_CHECK(info1->result_name);
-
- info1->status = DRSUAPI_DS_NAME_STATUS_OK;
- return WERR_OK;
+ _acc = samdb_result_string(result_res[0], "sAMAccountName", NULL);
+ WERR_TALLOC_CHECK(_acc);
}
- case DRSUAPI_DS_NAME_FORMAT_GUID: {
- struct GUID guid;
-
- guid = samdb_result_guid(result_res[0], "objectGUID");
- info1->result_name = GUID_string2(mem_ctx, &guid);
- WERR_TALLOC_CHECK(info1->result_name);
-
- info1->status = DRSUAPI_DS_NAME_STATUS_OK;
- return WERR_OK;
- }
- default:
- return WERR_OK;
+ info1->result_name = talloc_asprintf(mem_ctx, "%s\\%s", _dom, _acc);
+ WERR_TALLOC_CHECK(info1->result_name);
+
+ info1->status = DRSUAPI_DS_NAME_STATUS_OK;
+ return WERR_OK;
}
-
+ case DRSUAPI_DS_NAME_FORMAT_GUID: {
+ struct GUID guid;
+
+ guid = samdb_result_guid(result_res[0], "objectGUID");
+
+ info1->result_name = GUID_string2(mem_ctx, &guid);
+ WERR_TALLOC_CHECK(info1->result_name);
+
+ info1->status = DRSUAPI_DS_NAME_STATUS_OK;
+ return WERR_OK;
+ }
+ default:
+ return WERR_OK;
+ }
+
return WERR_INVALID_PARAM;
}
diff --git a/source4/torture/rpc/drsuapi.c b/source4/torture/rpc/drsuapi.c
index 197157b2b2..078b03710a 100644
--- a/source4/torture/rpc/drsuapi.c
+++ b/source4/torture/rpc/drsuapi.c
@@ -238,7 +238,7 @@ static BOOL test_DsCrackNamesMatrix(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
}
static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
- struct DsPrivate *priv)
+ struct DsPrivate *priv, const char *test_dc)
{
NTSTATUS status;
struct drsuapi_DsCrackNames r;
@@ -323,7 +323,7 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
names[0].str = priv->domain_guid_str;
- printf("testing DsCrackNames with name '%s' desired format:%d\n",
+ printf("testing DsCrackNames with GUID '%s' desired format:%d\n",
names[0].str, r.in.req.req1.format_desired);
status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
@@ -377,7 +377,7 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
- names[0].str = talloc_asprintf(mem_ctx, "%s%s$", nt4_domain, priv->dcinfo.netbios_name);
+ names[0].str = talloc_asprintf(mem_ctx, "%s%s$", nt4_domain, test_dc);
printf("testing DsCrackNames with name '%s' desired format:%d\n",
names[0].str, r.in.req.req1.format_desired);
@@ -406,7 +406,7 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL;
r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
- names[0].str = talloc_asprintf(mem_ctx, "%s$@%s", priv->dcinfo.netbios_name, dns_domain);
+ names[0].str = talloc_asprintf(mem_ctx, "%s$@%s", test_dc, dns_domain);
user_principal_name = names[0].str;
printf("testing DsCrackNames with name '%s' desired format:%d\n",
@@ -439,7 +439,7 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL;
r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
- names[0].str = talloc_asprintf(mem_ctx, "HOST/%s", priv->dcinfo.netbios_name);
+ names[0].str = talloc_asprintf(mem_ctx, "HOST/%s", test_dc);
service_principal_name = names[0].str;
printf("testing DsCrackNames with name '%s' desired format:%d\n",
@@ -472,7 +472,7 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL;
r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
- names[0].str = talloc_asprintf(mem_ctx, "cifs/%s.%s", priv->dcinfo.netbios_name, dns_domain);
+ names[0].str = talloc_asprintf(mem_ctx, "cifs/%s.%s", test_dc, dns_domain);
printf("testing DsCrackNames with name '%s' desired format:%d\n",
names[0].str, r.in.req.req1.format_desired);
@@ -520,6 +520,9 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
} else if (!W_ERROR_IS_OK(r.out.result)) {
printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
ret = False;
+ } else if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
+ printf("DsCrackNames failed on name - %d\n", r.out.ctr.ctr1->array[0].status);
+ ret = False;
}
if (!ret) {
@@ -711,39 +714,11 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
}
- r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY;
- r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
- names[0].str = SID_BUILTIN_ADMINISTRATORS;
-
- printf("testing DsCrackNames with SID '%s' desired format:%d\n",
- names[0].str, r.in.req.req1.format_desired);
-
- status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
- if (!NT_STATUS_IS_OK(status)) {
- const char *errstr = nt_errstr(status);
- if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
- errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
- }
- printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
- ret = False;
- } else if (!W_ERROR_IS_OK(r.out.result)) {
- printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
- ret = False;
- } else if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
- printf("DsCrackNames failed on name - %d\n", r.out.ctr.ctr1->array[0].status);
- ret = False;
- }
-
- if (!ret) {
- return ret;
- }
-
-
/* NEGATIVE tests. This should parse, but not succeed */
r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL;
r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
names[0].str = talloc_asprintf(mem_ctx, "cifs/%s.%s@%s",
- priv->dcinfo.netbios_name, dns_domain,
+ test_dc, dns_domain,
dns_domain);
printf("testing DsCrackNames with Service Principal '%s' desired format:%d\n",
@@ -964,7 +939,7 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
/* NEGATIVE tests. This should parse, but not succeed */
r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL;
r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
- names[0].str = talloc_asprintf(mem_ctx, "%s$", priv->dcinfo.netbios_name);
+ names[0].str = talloc_asprintf(mem_ctx, "%s$", test_dc);
printf("testing DsCrackNames with user principal name '%s' desired format:%d\n",
names[0].str, r.in.req.req1.format_desired);
@@ -988,7 +963,7 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
/* NEGATIVE tests. This should parse, but not succeed */
r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL;
r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
- names[0].str = talloc_asprintf(mem_ctx, "%s$", priv->dcinfo.netbios_name);
+ names[0].str = talloc_asprintf(mem_ctx, "%s$", test_dc);
printf("testing DsCrackNames with service principal name '%s' desired format:%d\n",
names[0].str, r.in.req.req1.format_desired);
@@ -1042,6 +1017,90 @@ static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
return ret;
}
+ r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY;
+ r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
+ names[0].str = SID_BUILTIN;
+
+ printf("testing DsCrackNames with SID '%s' desired format:%d\n",
+ names[0].str, r.in.req.req1.format_desired);
+
+ status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ const char *errstr = nt_errstr(status);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
+ errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
+ }
+ printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
+ ret = False;
+ } else if (!W_ERROR_IS_OK(r.out.result)) {
+ printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
+ ret = False;
+ } else if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
+ printf("DsCrackNames failed on name - %d\n", r.out.ctr.ctr1->array[0].status);
+ ret = False;
+ }
+
+ if (!ret) {
+ return ret;
+ }
+
+
+ r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY;
+ r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
+ names[0].str = SID_BUILTIN_ADMINISTRATORS;
+
+ printf("testing DsCrackNames with SID '%s' desired format:%d\n",
+ names[0].str, r.in.req.req1.format_desired);
+
+ status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ const char *errstr = nt_errstr(status);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
+ errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
+ }
+ printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
+ ret = False;
+ } else if (!W_ERROR_IS_OK(r.out.result)) {
+ printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
+ ret = False;
+ } else if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_NO_MAPPING) {
+ printf("DsCrackNames incorrect error on name - %d\n", r.out.ctr.ctr1->array[0].status);
+ ret = False;
+ }
+
+ if (!ret) {
+ return ret;
+ }
+
+
+ r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY;
+ r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
+ names[0].str = SID_BUILTIN_ADMINISTRATORS;
+
+ printf("testing DsCrackNames with SID '%s' desired format:%d\n",
+ names[0].str, r.in.req.req1.format_desired);
+
+ status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ const char *errstr = nt_errstr(status);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
+ errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
+ }
+ printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
+ ret = False;
+ } else if (!W_ERROR_IS_OK(r.out.result)) {
+ printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
+ ret = False;
+ } else if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_NO_MAPPING) {
+ printf("DsCrackNames incorrect error on name - %d\n", r.out.ctr.ctr1->array[0].status);
+ ret = False;
+ }
+
+ if (!ret) {
+ return ret;
+ }
+
+
/* NEGATIVE tests. This should parse, but not succeed */
r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL;
r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
@@ -1662,7 +1721,7 @@ BOOL torture_rpc_drsuapi(void)
ret &= test_DsGetDCInfo(p, mem_ctx, &priv);
- ret &= test_DsCrackNames(p, mem_ctx, &priv);
+ ret &= test_DsCrackNames(p, mem_ctx, &priv, priv.dcinfo.netbios_name);
ret &= test_DsWriteAccountSpn(p, mem_ctx, &priv);
@@ -1707,9 +1766,7 @@ BOOL torture_rpc_drsuapi_cracknames(void)
ret &= test_DsBind(p, mem_ctx, &priv);
- ret &= test_DsGetDCInfo(p, mem_ctx, &priv);
-
- ret &= test_DsCrackNames(p, mem_ctx, &priv);
+ ret &= test_DsCrackNames(p, mem_ctx, &priv, lp_parm_string(-1, "torture", "host"));
ret &= test_DsUnbind(p, mem_ctx, &priv);