diff options
author | Andrew Bartlett <abartlet@samba.org> | 2005-09-02 03:19:27 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:36:24 -0500 |
commit | b3c0dacd20c1d8002b02eceb21036dc74a684d36 (patch) | |
tree | 2a411b4dda6df02281c554bee27dc22b8778e45c /source4/rpc_server/drsuapi/drsuapi_cracknames.c | |
parent | 9319cace3bb5320e943ec75348efefe199323499 (diff) | |
download | samba-b3c0dacd20c1d8002b02eceb21036dc74a684d36.tar.gz samba-b3c0dacd20c1d8002b02eceb21036dc74a684d36.tar.bz2 samba-b3c0dacd20c1d8002b02eceb21036dc74a684d36.zip |
r9941: Update the CrackNames test, and provide a much improved server-side
DRSUAPI CrackNames.
We can't pass the full cracknames test until the initial provision is
updated, the seperate DomainControllerInfo and canonical names support
is added.
Andrew Bartlett
(This used to be commit ed24d88f0e8c6371acf6638a1c5f2112bc0bf285)
Diffstat (limited to 'source4/rpc_server/drsuapi/drsuapi_cracknames.c')
-rw-r--r-- | source4/rpc_server/drsuapi/drsuapi_cracknames.c | 634 |
1 files changed, 515 insertions, 119 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; } |