LCOV - code coverage report
Current view: top level - source4/dsdb/samdb - cracknames.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 671 998 67.2 %
Date: 2024-04-21 15:09:00 Functions: 13 15 86.7 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    crachnames implementation for the drsuapi pipe
       5             :    DsCrackNames()
       6             : 
       7             :    Copyright (C) Stefan Metzmacher 2004
       8             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
       9             :    Copyright (C) Matthieu Patou <mat@matws.net> 2012
      10             :    Copyright (C) Catalyst .Net Ltd 2017
      11             : 
      12             :    This program is free software; you can redistribute it and/or modify
      13             :    it under the terms of the GNU General Public License as published by
      14             :    the Free Software Foundation; either version 3 of the License, or
      15             :    (at your option) any later version.
      16             : 
      17             :    This program is distributed in the hope that it will be useful,
      18             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      19             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      20             :    GNU General Public License for more details.
      21             : 
      22             :    You should have received a copy of the GNU General Public License
      23             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      24             : */
      25             : 
      26             : #include "includes.h"
      27             : #include "librpc/gen_ndr/drsuapi.h"
      28             : #include "lib/events/events.h"
      29             : #include <ldb.h>
      30             : #include <ldb_errors.h>
      31             : #include "auth/kerberos/kerberos.h"
      32             : #include "libcli/ldap/ldap_ndr.h"
      33             : #include "libcli/security/security.h"
      34             : #include "auth/auth.h"
      35             : #include "../lib/util/util_ldb.h"
      36             : #include "dsdb/samdb/samdb.h"
      37             : #include "dsdb/common/util.h"
      38             : #include "param/param.h"
      39             : 
      40             : #undef strcasecmp
      41             : 
      42             : static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
      43             :                                    struct smb_krb5_context *smb_krb5_context,
      44             :                                    uint32_t format_flags, enum drsuapi_DsNameFormat format_offered,
      45             :                                    enum drsuapi_DsNameFormat format_desired,
      46             :                                    struct ldb_dn *name_dn, const char *name,
      47             :                                    const char *domain_filter, const char *result_filter,
      48             :                                    struct drsuapi_DsNameInfo1 *info1, int scope, struct ldb_dn *search_dn);
      49             : static WERROR DsCrackNameOneSyntactical(TALLOC_CTX *mem_ctx,
      50             :                                         enum drsuapi_DsNameFormat format_offered,
      51             :                                         enum drsuapi_DsNameFormat format_desired,
      52             :                                         struct ldb_dn *name_dn, const char *name,
      53             :                                         struct drsuapi_DsNameInfo1 *info1);
      54             : 
      55         104 : static WERROR dns_domain_from_principal(TALLOC_CTX *mem_ctx, struct smb_krb5_context *smb_krb5_context,
      56             :                                         const char *name,
      57             :                                         struct drsuapi_DsNameInfo1 *info1)
      58             : {
      59           0 :         krb5_error_code ret;
      60           0 :         krb5_principal principal;
      61             :         /* perhaps it's a principal with a realm, so return the right 'domain only' response */
      62         104 :         ret = krb5_parse_name_flags(smb_krb5_context->krb5_context, name,
      63             :                                     KRB5_PRINCIPAL_PARSE_REQUIRE_REALM, &principal);
      64         104 :         if (ret) {
      65           0 :                 info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
      66           0 :                 return WERR_OK;
      67             :         }
      68             : 
      69         104 :         info1->dns_domain_name = smb_krb5_principal_get_realm(
      70             :                 mem_ctx, smb_krb5_context->krb5_context, principal);
      71         104 :         krb5_free_principal(smb_krb5_context->krb5_context, principal);
      72             : 
      73         104 :         W_ERROR_HAVE_NO_MEMORY(info1->dns_domain_name);
      74             : 
      75         104 :         info1->status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY;
      76         104 :         return WERR_OK;
      77             : }
      78             : 
      79        5764 : static enum drsuapi_DsNameStatus LDB_lookup_spn_alias(struct ldb_context *ldb_ctx,
      80             :                                                       TALLOC_CTX *mem_ctx,
      81             :                                                       const char *alias_from,
      82             :                                                       char **alias_to)
      83             : {
      84             :         /*
      85             :          * Some of the logic of this function is mirrored in find_spn_alias()
      86             :          * in source4/dsdb/samdb/ldb_modules/samldb.c. If you change this to
      87             :          * not return the first matched alias, you will need to rethink that
      88             :          * function too.
      89             :          */
      90         537 :         unsigned int i;
      91         537 :         int ret;
      92         537 :         struct ldb_result *res;
      93         537 :         struct ldb_message_element *spnmappings;
      94         537 :         TALLOC_CTX *tmp_ctx;
      95         537 :         struct ldb_dn *service_dn;
      96         537 :         char *service_dn_str;
      97             : 
      98        5764 :         const char *directory_attrs[] = {
      99             :                 "sPNMappings",
     100             :                 NULL
     101             :         };
     102             : 
     103        5764 :         tmp_ctx = talloc_new(mem_ctx);
     104        5764 :         if (!tmp_ctx) {
     105           0 :                 return DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
     106             :         }
     107             : 
     108        5764 :         service_dn = ldb_dn_new(tmp_ctx, ldb_ctx, "CN=Directory Service,CN=Windows NT,CN=Services");
     109        5764 :         if ( ! ldb_dn_add_base(service_dn, ldb_get_config_basedn(ldb_ctx))) {
     110           0 :                 talloc_free(tmp_ctx);
     111           0 :                 return DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
     112             :         }
     113        5764 :         service_dn_str = ldb_dn_alloc_linearized(tmp_ctx, service_dn);
     114        5764 :         if ( ! service_dn_str) {
     115           0 :                 talloc_free(tmp_ctx);
     116           0 :                 return DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
     117             :         }
     118             : 
     119        5764 :         ret = ldb_search(ldb_ctx, tmp_ctx, &res, service_dn, LDB_SCOPE_BASE,
     120             :                          directory_attrs, "(objectClass=nTDSService)");
     121             : 
     122        5764 :         if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
     123           0 :                 DEBUG(1, ("ldb_search: dn: %s not found: %s\n", service_dn_str, ldb_errstring(ldb_ctx)));
     124           0 :                 talloc_free(tmp_ctx);
     125           0 :                 return DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
     126        5764 :         } else if (ret == LDB_ERR_NO_SUCH_OBJECT) {
     127           0 :                 DEBUG(1, ("ldb_search: dn: %s not found\n", service_dn_str));
     128           0 :                 talloc_free(tmp_ctx);
     129           0 :                 return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
     130        5764 :         } else if (res->count != 1) {
     131           0 :                 DEBUG(1, ("ldb_search: dn: %s not found\n", service_dn_str));
     132           0 :                 talloc_free(tmp_ctx);
     133           0 :                 return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
     134             :         }
     135             : 
     136        5764 :         spnmappings = ldb_msg_find_element(res->msgs[0], "sPNMappings");
     137        5764 :         if (!spnmappings || spnmappings->num_values == 0) {
     138           0 :                 DEBUG(1, ("ldb_search: dn: %s no sPNMappings attribute\n", service_dn_str));
     139           0 :                 talloc_free(tmp_ctx);
     140           0 :                 return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
     141             :         }
     142             : 
     143        6150 :         for (i = 0; i < spnmappings->num_values; i++) {
     144         537 :                 char *mapping, *p, *str;
     145        6301 :                 mapping = talloc_strdup(tmp_ctx,
     146        5764 :                                         (const char *)spnmappings->values[i].data);
     147        5764 :                 if (!mapping) {
     148           0 :                         DEBUG(1, ("LDB_lookup_spn_alias: ldb_search: dn: %s did not have an sPNMapping\n", service_dn_str));
     149           0 :                         talloc_free(tmp_ctx);
     150           0 :                         return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
     151             :                 }
     152             : 
     153             :                 /* C string manipulation sucks */
     154             : 
     155        5764 :                 p = strchr(mapping, '=');
     156        5764 :                 if (!p) {
     157           0 :                         DEBUG(1, ("ldb_search: dn: %s sPNMapping malformed: %s\n",
     158             :                                   service_dn_str, mapping));
     159           0 :                         talloc_free(tmp_ctx);
     160           0 :                         return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
     161             :                 }
     162        5764 :                 p[0] = '\0';
     163        5764 :                 p++;
     164       20943 :                 do {
     165      229521 :                         str = p;
     166      229521 :                         p = strchr(p, ',');
     167      229521 :                         if (p) {
     168      229135 :                                 p[0] = '\0';
     169      229135 :                                 p++;
     170             :                         }
     171      229521 :                         if (strcasecmp(str, alias_from) == 0) {
     172        5378 :                                 *alias_to = mapping;
     173        5378 :                                 talloc_steal(mem_ctx, mapping);
     174        5378 :                                 talloc_free(tmp_ctx);
     175        5378 :                                 return DRSUAPI_DS_NAME_STATUS_OK;
     176             :                         }
     177      224143 :                 } while (p);
     178             :         }
     179         386 :         DEBUG(4, ("LDB_lookup_spn_alias: no alias for service %s applicable\n", alias_from));
     180         386 :         talloc_free(tmp_ctx);
     181         386 :         return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
     182             : }
     183             : 
     184             : /* When cracking a ServicePrincipalName, many services may be served
     185             :  * by the host/ servicePrincipalName.  The incoming query is for cifs/
     186             :  * but we translate it here, and search on host/.  This is done after
     187             :  * the cifs/ entry has been searched for, making this a fallback */
     188             : 
     189        5764 : static WERROR DsCrackNameSPNAlias(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
     190             :                                   struct smb_krb5_context *smb_krb5_context,
     191             :                                   uint32_t format_flags, enum drsuapi_DsNameFormat format_offered,
     192             :                                   enum drsuapi_DsNameFormat format_desired,
     193             :                                   const char *name, struct drsuapi_DsNameInfo1 *info1)
     194             : {
     195         537 :         WERROR wret;
     196         537 :         krb5_error_code ret;
     197         537 :         krb5_principal principal;
     198         537 :         krb5_data component;
     199         537 :         const char *service, *dns_name;
     200         537 :         char *new_service;
     201         537 :         char *new_princ;
     202         537 :         enum drsuapi_DsNameStatus namestatus;
     203             : 
     204             :         /* parse principal */
     205        5764 :         ret = krb5_parse_name_flags(smb_krb5_context->krb5_context,
     206             :                                     name, KRB5_PRINCIPAL_PARSE_NO_REALM, &principal);
     207        5764 :         if (ret) {
     208           0 :                 DEBUG(2, ("Could not parse principal: %s: %s\n",
     209             :                           name, smb_get_krb5_error_message(smb_krb5_context->krb5_context,
     210             :                                                            ret, mem_ctx)));
     211           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     212             :         }
     213             : 
     214             :         /* grab cifs/, http/ etc */
     215             : 
     216        5764 :         ret = smb_krb5_princ_component(smb_krb5_context->krb5_context,
     217             :                                        principal, 0, &component);
     218        5764 :         if (ret) {
     219           0 :                 info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
     220           0 :                 krb5_free_principal(smb_krb5_context->krb5_context, principal);
     221           0 :                 return WERR_OK;
     222             :         }
     223        5764 :         service = (const char *)component.data;
     224        5764 :         ret = smb_krb5_princ_component(smb_krb5_context->krb5_context,
     225             :                                        principal, 1, &component);
     226        5764 :         if (ret) {
     227           0 :                 info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
     228           0 :                 krb5_free_principal(smb_krb5_context->krb5_context, principal);
     229           0 :                 return WERR_OK;
     230             :         }
     231        5764 :         dns_name = (const char *)component.data;
     232             : 
     233             :         /* MAP it */
     234        5764 :         namestatus = LDB_lookup_spn_alias(sam_ctx, mem_ctx,
     235             :                                           service, &new_service);
     236             : 
     237        5764 :         if (namestatus == DRSUAPI_DS_NAME_STATUS_NOT_FOUND) {
     238         386 :                 wret = WERR_OK;
     239         386 :                 info1->status                = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY;
     240         386 :                 info1->dns_domain_name       = talloc_strdup(mem_ctx, dns_name);
     241         386 :                 if (!info1->dns_domain_name) {
     242           0 :                         wret = WERR_NOT_ENOUGH_MEMORY;
     243             :                 }
     244         386 :                 krb5_free_principal(smb_krb5_context->krb5_context, principal);
     245         386 :                 return wret;
     246        5378 :         } else if (namestatus != DRSUAPI_DS_NAME_STATUS_OK) {
     247           0 :                 info1->status = namestatus;
     248           0 :                 krb5_free_principal(smb_krb5_context->krb5_context, principal);
     249           0 :                 return WERR_OK;
     250             :         }
     251             : 
     252             :         /* reform principal */
     253        5378 :         new_princ = talloc_asprintf(mem_ctx, "%s/%s", new_service, dns_name);
     254        5378 :         if (!new_princ) {
     255           0 :                 krb5_free_principal(smb_krb5_context->krb5_context, principal);
     256           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     257             :         }
     258             : 
     259        5378 :         wret = DsCrackNameOneName(sam_ctx, mem_ctx, format_flags, format_offered, format_desired,
     260             :                                   new_princ, info1);
     261        5378 :         talloc_free(new_princ);
     262        5378 :         if (W_ERROR_IS_OK(wret) && (info1->status == DRSUAPI_DS_NAME_STATUS_NOT_FOUND)) {
     263           0 :                 info1->status                = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY;
     264           0 :                 info1->dns_domain_name       = talloc_strdup(mem_ctx, dns_name);
     265           0 :                 if (!info1->dns_domain_name) {
     266           0 :                         wret = WERR_NOT_ENOUGH_MEMORY;
     267             :                 }
     268             :         }
     269        5378 :         krb5_free_principal(smb_krb5_context->krb5_context, principal);
     270        5378 :         return wret;
     271             : }
     272             : 
     273             : /* Subcase of CrackNames, for the userPrincipalName */
     274             : 
     275      114991 : static WERROR DsCrackNameUPN(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
     276             :                              struct smb_krb5_context *smb_krb5_context,
     277             :                              uint32_t format_flags, enum drsuapi_DsNameFormat format_offered,
     278             :                              enum drsuapi_DsNameFormat format_desired,
     279             :                              const char *name, struct drsuapi_DsNameInfo1 *info1)
     280             : {
     281        4370 :         int ldb_ret;
     282        4370 :         WERROR status;
     283      114991 :         const char *domain_filter = NULL;
     284      114991 :         const char *result_filter = NULL;
     285        4370 :         krb5_error_code ret;
     286        4370 :         krb5_principal principal;
     287        4370 :         char *realm;
     288      114991 :         char *realm_encoded = NULL;
     289        4370 :         char *unparsed_name_short;
     290      114991 :         const char *unparsed_name_short_encoded = NULL;
     291      114991 :         const char *domain_attrs[] = { NULL };
     292      114991 :         struct ldb_result *domain_res = NULL;
     293             : 
     294             :         /* Prevent recursion */
     295      114991 :         if (!name) {
     296           0 :                 info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
     297           0 :                 return WERR_OK;
     298             :         }
     299             : 
     300      114991 :         ret = krb5_parse_name_flags(smb_krb5_context->krb5_context, name,
     301             :                                     KRB5_PRINCIPAL_PARSE_REQUIRE_REALM, &principal);
     302      114991 :         if (ret) {
     303        2686 :                 info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
     304        2686 :                 return WERR_OK;
     305             :         }
     306             : 
     307      112305 :         realm = smb_krb5_principal_get_realm(
     308             :                 mem_ctx, smb_krb5_context->krb5_context, principal);
     309      112305 :         if (realm == NULL) {
     310           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     311             :         }
     312             : 
     313      112305 :         realm_encoded = ldb_binary_encode_string(mem_ctx, realm);
     314      112305 :         if (realm_encoded == NULL) {
     315           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     316             :         }
     317             : 
     318      112305 :         ldb_ret = ldb_search(sam_ctx, mem_ctx, &domain_res,
     319             :                              samdb_partitions_dn(sam_ctx, mem_ctx),
     320             :                              LDB_SCOPE_ONELEVEL,
     321             :                              domain_attrs,
     322             :                              "(&(objectClass=crossRef)(|(dnsRoot=%s)(netbiosName=%s))"
     323             :                              "(systemFlags:"LDB_OID_COMPARATOR_AND":=%u))",
     324             :                              realm_encoded,
     325             :                              realm_encoded,
     326             :                              SYSTEM_FLAG_CR_NTDS_DOMAIN);
     327      112305 :         TALLOC_FREE(realm_encoded);
     328      112305 :         TALLOC_FREE(realm);
     329             : 
     330      112305 :         if (ldb_ret != LDB_SUCCESS) {
     331           0 :                 DEBUG(2, ("DsCrackNameUPN domain ref search failed: %s\n", ldb_errstring(sam_ctx)));
     332           0 :                 info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
     333           0 :                 krb5_free_principal(smb_krb5_context->krb5_context, principal);
     334           0 :                 return WERR_OK;
     335             :         }
     336             : 
     337      112305 :         switch (domain_res->count) {
     338      107837 :         case 1:
     339      112207 :                 break;
     340          98 :         case 0:
     341          98 :                 krb5_free_principal(smb_krb5_context->krb5_context, principal);
     342          98 :                 return dns_domain_from_principal(mem_ctx, smb_krb5_context,
     343             :                                                  name, info1);
     344           0 :         default:
     345           0 :                 info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
     346           0 :                 krb5_free_principal(smb_krb5_context->krb5_context, principal);
     347           0 :                 return WERR_OK;
     348             :         }
     349             : 
     350             :         /*
     351             :          * The important thing here is that a samAccountName may have
     352             :          * a space in it, and this must not be kerberos escaped to
     353             :          * match this filter, so we specify
     354             :          * KRB5_PRINCIPAL_UNPARSE_DISPLAY
     355             :          */
     356      112207 :         ret = krb5_unparse_name_flags(smb_krb5_context->krb5_context, principal,
     357             :                                       KRB5_PRINCIPAL_UNPARSE_NO_REALM |
     358             :                                       KRB5_PRINCIPAL_UNPARSE_DISPLAY,
     359             :                                       &unparsed_name_short);
     360      112207 :         krb5_free_principal(smb_krb5_context->krb5_context, principal);
     361             : 
     362      112207 :         if (ret) {
     363           0 :                 free(unparsed_name_short);
     364           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     365             :         }
     366             : 
     367      112207 :         unparsed_name_short_encoded = ldb_binary_encode_string(mem_ctx, unparsed_name_short);
     368      112207 :         if (unparsed_name_short_encoded == NULL) {
     369           0 :                 free(unparsed_name_short);
     370           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     371             :         }
     372             : 
     373             :         /* This may need to be extended for more userPrincipalName variations */
     374      112207 :         result_filter = talloc_asprintf(mem_ctx, "(&(samAccountName=%s)(objectClass=user))",
     375             :                                         unparsed_name_short_encoded);
     376             : 
     377      112207 :         domain_filter = talloc_asprintf(mem_ctx, "(distinguishedName=%s)", ldb_dn_get_linearized(domain_res->msgs[0]->dn));
     378             : 
     379      112207 :         if (!result_filter || !domain_filter) {
     380           0 :                 free(unparsed_name_short);
     381           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     382             :         }
     383      112207 :         status = DsCrackNameOneFilter(sam_ctx, mem_ctx,
     384             :                                       smb_krb5_context,
     385             :                                       format_flags, format_offered, format_desired,
     386             :                                       NULL, unparsed_name_short, domain_filter, result_filter,
     387             :                                       info1, LDB_SCOPE_SUBTREE, NULL);
     388      112207 :         free(unparsed_name_short);
     389             : 
     390      112207 :         return status;
     391             : }
     392             : 
     393             : /*
     394             :  * This function will workout the filtering parameter in order to be able to do
     395             :  * the adapted search when the incoming format is format_functional.
     396             :  * This boils down to defining the search_dn (passed as pointer to ldb_dn *) and the
     397             :  * ldap filter request.
     398             :  * Main input parameters are:
     399             :  * * name, which is the portion of the functional name after the
     400             :  * first '/'.
     401             :  * * domain_filter, which is a ldap search filter used to find the NC DN given the
     402             :  * function name to crack.
     403             :  */
     404          50 : static WERROR get_format_functional_filtering_param(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
     405             :                         char *name, struct drsuapi_DsNameInfo1 *info1,
     406             :                         struct ldb_dn **psearch_dn, const char *domain_filter, const char **presult_filter)
     407             : {
     408          50 :         struct ldb_result *domain_res = NULL;
     409          50 :         const char * const domain_attrs[] = {"ncName", NULL};
     410          50 :         struct ldb_dn *partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx);
     411           0 :         int ldb_ret;
     412          50 :         char *account,  *s, *result_filter = NULL;
     413          50 :         struct ldb_dn *search_dn = NULL;
     414             : 
     415          50 :         *psearch_dn = NULL;
     416          50 :         *presult_filter = NULL;
     417             : 
     418          50 :         ldb_ret = ldb_search(sam_ctx, mem_ctx, &domain_res,
     419             :                                 partitions_basedn,
     420             :                                 LDB_SCOPE_ONELEVEL,
     421             :                                 domain_attrs,
     422             :                                 "%s", domain_filter);
     423             : 
     424          50 :         if (ldb_ret != LDB_SUCCESS) {
     425           0 :                 DEBUG(2, ("DsCrackNameOne domain ref search failed: %s\n", ldb_errstring(sam_ctx)));
     426           0 :                 info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
     427           0 :                 return WERR_FOOBAR;
     428             :         }
     429             : 
     430          50 :         if (domain_res->count == 1) {
     431          50 :                 struct ldb_dn *tmp_dn = samdb_result_dn(sam_ctx, mem_ctx, domain_res->msgs[0], "ncName", NULL);
     432          50 :                 const char * const name_attrs[] = {"name", NULL};
     433             : 
     434          50 :                 account = name;
     435          50 :                 s = strchr(account, '/');
     436          50 :                 talloc_free(domain_res);
     437         100 :                 while(s) {
     438          50 :                         s[0] = '\0';
     439          50 :                         s++;
     440             : 
     441          50 :                         ldb_ret = ldb_search(sam_ctx, mem_ctx, &domain_res,
     442             :                                                 tmp_dn,
     443             :                                                 LDB_SCOPE_ONELEVEL,
     444             :                                                 name_attrs,
     445             :                                                 "name=%s", account);
     446             : 
     447          50 :                         if (ldb_ret != LDB_SUCCESS) {
     448           0 :                                 DEBUG(2, ("DsCrackNameOne domain ref search failed: %s\n", ldb_errstring(sam_ctx)));
     449           0 :                                 info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
     450           0 :                                 return WERR_OK;
     451             :                         }
     452          50 :                         talloc_free(tmp_dn);
     453          50 :                         switch (domain_res->count) {
     454          50 :                         case 1:
     455          50 :                                 break;
     456           0 :                         case 0:
     457           0 :                                 talloc_free(domain_res);
     458           0 :                                 info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
     459           0 :                                 return WERR_OK;
     460           0 :                         default:
     461           0 :                                 talloc_free(domain_res);
     462           0 :                                 info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
     463           0 :                                 return WERR_OK;
     464             :                         }
     465             : 
     466          50 :                         tmp_dn = talloc_steal(mem_ctx, domain_res->msgs[0]->dn);
     467          50 :                         talloc_free(domain_res);
     468          50 :                         search_dn = tmp_dn;
     469          50 :                         account = s;
     470          50 :                         s = strchr(account, '/');
     471             :                 }
     472          50 :                 account = ldb_binary_encode_string(mem_ctx, account);
     473          50 :                 W_ERROR_HAVE_NO_MEMORY(account);
     474          50 :                 result_filter = talloc_asprintf(mem_ctx, "(name=%s)",
     475             :                                                 account);
     476          50 :                 W_ERROR_HAVE_NO_MEMORY(result_filter);
     477             :         }
     478          50 :         *psearch_dn = search_dn;
     479          50 :         *presult_filter = result_filter;
     480          50 :         return WERR_OK;
     481             : }
     482             : 
     483             : /* Crack a single 'name', from format_offered into format_desired, returning the result in info1 */
     484             : 
     485      277092 : WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
     486             :                           uint32_t format_flags, enum drsuapi_DsNameFormat format_offered,
     487             :                           enum drsuapi_DsNameFormat format_desired,
     488             :                           const char *name, struct drsuapi_DsNameInfo1 *info1)
     489             : {
     490        9713 :         krb5_error_code ret;
     491      277092 :         const char *domain_filter = NULL;
     492      277092 :         const char *result_filter = NULL;
     493      277092 :         struct ldb_dn *name_dn = NULL;
     494      277092 :         struct ldb_dn *search_dn = NULL;
     495             : 
     496      277092 :         struct smb_krb5_context *smb_krb5_context = NULL;
     497      277092 :         int scope = LDB_SCOPE_SUBTREE;
     498             : 
     499      277092 :         info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
     500      277092 :         info1->dns_domain_name = NULL;
     501      277092 :         info1->result_name = NULL;
     502             : 
     503      277092 :         if (!name) {
     504           0 :                 return WERR_INVALID_PARAMETER;
     505             :         }
     506             : 
     507             :         /* TODO: - fill the correct names in all cases!
     508             :          *       - handle format_flags
     509             :          */
     510      277092 :         if (format_desired == DRSUAPI_DS_NAME_FORMAT_UNKNOWN) {
     511          20 :                 return WERR_OK;
     512             :         }
     513             :         /* here we need to set the domain_filter and/or the result_filter */
     514      277072 :         switch (format_offered) {
     515           0 :         case DRSUAPI_DS_NAME_FORMAT_UNKNOWN:
     516             :         {
     517           0 :                 unsigned int i;
     518           0 :                 enum drsuapi_DsNameFormat formats[] = {
     519             :                         DRSUAPI_DS_NAME_FORMAT_FQDN_1779, DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
     520             :                         DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT, DRSUAPI_DS_NAME_FORMAT_CANONICAL,
     521             :                         DRSUAPI_DS_NAME_FORMAT_GUID, DRSUAPI_DS_NAME_FORMAT_DISPLAY,
     522             :                         DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
     523             :                         DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
     524             :                         DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX
     525             :                 };
     526           0 :                 WERROR werr;
     527           0 :                 for (i=0; i < ARRAY_SIZE(formats); i++) {
     528           0 :                         werr = DsCrackNameOneName(sam_ctx, mem_ctx, format_flags, formats[i], format_desired, name, info1);
     529           0 :                         if (!W_ERROR_IS_OK(werr)) {
     530           0 :                                 return werr;
     531             :                         }
     532           0 :                         if (info1->status != DRSUAPI_DS_NAME_STATUS_NOT_FOUND &&
     533           0 :                             (formats[i] != DRSUAPI_DS_NAME_FORMAT_CANONICAL ||
     534           0 :                              info1->status != DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR))
     535             :                         {
     536           0 :                                 return werr;
     537             :                         }
     538             :                 }
     539           0 :                 return werr;
     540             :         }
     541             : 
     542      129246 :         case DRSUAPI_DS_NAME_FORMAT_CANONICAL:
     543             :         case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX:
     544             :         {
     545        4036 :                 char *str, *s, *account;
     546      129246 :                 const char *str_encoded = NULL;
     547      129246 :                 scope = LDB_SCOPE_ONELEVEL;
     548             : 
     549      129246 :                 if (strlen(name) == 0) {
     550           0 :                         info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
     551           0 :                         return WERR_OK;
     552             :                 }
     553             : 
     554      129246 :                 str = talloc_strdup(mem_ctx, name);
     555      129246 :                 W_ERROR_HAVE_NO_MEMORY(str);
     556             : 
     557      129246 :                 if (format_offered == DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX) {
     558             :                         /* Look backwards for the \n, and replace it with / */
     559          25 :                         s = strrchr(str, '\n');
     560          25 :                         if (!s) {
     561           0 :                                 info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
     562           0 :                                 return WERR_OK;
     563             :                         }
     564          25 :                         s[0] = '/';
     565             :                 }
     566             : 
     567      129246 :                 s = strchr(str, '/');
     568      129246 :                 if (!s) {
     569             :                         /* there must be at least one / */
     570           1 :                         info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
     571           1 :                         return WERR_OK;
     572             :                 }
     573             : 
     574      129245 :                 s[0] = '\0';
     575      129245 :                 s++;
     576             : 
     577      129245 :                 str_encoded = ldb_binary_encode_string(mem_ctx, str);
     578      129245 :                 if (str_encoded == NULL) {
     579           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     580             :                 }
     581             : 
     582      129245 :                 domain_filter = talloc_asprintf(mem_ctx, "(&(objectClass=crossRef)(dnsRoot=%s)(systemFlags:%s:=%u))",
     583             :                                                 str_encoded,
     584             :                                                 LDB_OID_COMPARATOR_AND,
     585             :                                                 SYSTEM_FLAG_CR_NTDS_DOMAIN);
     586      129245 :                 W_ERROR_HAVE_NO_MEMORY(domain_filter);
     587             : 
     588             :                 /* There may not be anything after the domain component (search for the domain itself) */
     589      129245 :                 account = s;
     590      129245 :                 if (account && *account) {
     591          50 :                         WERROR werr = get_format_functional_filtering_param(sam_ctx,
     592             :                                                                                 mem_ctx,
     593             :                                                                                 account,
     594             :                                                                                 info1,
     595             :                                                                                 &search_dn,
     596             :                                                                                 domain_filter,
     597             :                                                                                 &result_filter);
     598          50 :                         if (!W_ERROR_IS_OK(werr)) {
     599           0 :                                 return werr;
     600             :                         }
     601          50 :                         if (info1->status != DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR)
     602           0 :                                 return WERR_OK;
     603             :                 }
     604      125209 :                 break;
     605             :         }
     606         580 :         case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT: {
     607          72 :                 char *p;
     608          72 :                 char *domain;
     609         580 :                 char *domain_encoded = NULL;
     610         580 :                 const char *account = NULL;
     611             : 
     612         580 :                 domain = talloc_strdup(mem_ctx, name);
     613         580 :                 W_ERROR_HAVE_NO_MEMORY(domain);
     614             : 
     615         580 :                 p = strchr(domain, '\\');
     616         580 :                 if (!p) {
     617             :                         /* invalid input format */
     618           2 :                         info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
     619           2 :                         return WERR_OK;
     620             :                 }
     621         578 :                 p[0] = '\0';
     622             : 
     623         578 :                 if (p[1]) {
     624          63 :                         account = &p[1];
     625             :                 }
     626             : 
     627         578 :                 domain_encoded = ldb_binary_encode_string(mem_ctx, domain);
     628         578 :                 if (domain_encoded == NULL) {
     629           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     630             :                 }
     631             : 
     632         578 :                 domain_filter = talloc_asprintf(mem_ctx,
     633             :                                                 "(&(objectClass=crossRef)(netbiosName=%s)(systemFlags:%s:=%u))",
     634             :                                                 domain_encoded,
     635             :                                                 LDB_OID_COMPARATOR_AND,
     636             :                                                 SYSTEM_FLAG_CR_NTDS_DOMAIN);
     637         578 :                 W_ERROR_HAVE_NO_MEMORY(domain_filter);
     638         578 :                 if (account) {
     639          63 :                         const char *account_encoded = NULL;
     640             : 
     641          63 :                         account_encoded = ldb_binary_encode_string(mem_ctx, account);
     642          63 :                         if (account_encoded == NULL) {
     643           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
     644             :                         }
     645             : 
     646          63 :                         result_filter = talloc_asprintf(mem_ctx, "(sAMAccountName=%s)",
     647             :                                                         account_encoded);
     648          63 :                         W_ERROR_HAVE_NO_MEMORY(result_filter);
     649             :                 }
     650             : 
     651         578 :                 talloc_free(domain);
     652         578 :                 break;
     653             :         }
     654             : 
     655             :                 /* A LDAP DN as a string */
     656         415 :         case DRSUAPI_DS_NAME_FORMAT_FQDN_1779: {
     657         415 :                 domain_filter = NULL;
     658         415 :                 name_dn = ldb_dn_new(mem_ctx, sam_ctx, name);
     659         415 :                 if (! ldb_dn_validate(name_dn)) {
     660           2 :                         info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
     661           2 :                         return WERR_OK;
     662             :                 }
     663         413 :                 break;
     664             :         }
     665             : 
     666             :                 /* A GUID as a string */
     667          56 :         case DRSUAPI_DS_NAME_FORMAT_GUID: {
     668           0 :                 struct GUID guid;
     669           0 :                 char *ldap_guid;
     670           0 :                 NTSTATUS nt_status;
     671          56 :                 domain_filter = NULL;
     672             : 
     673          56 :                 nt_status = GUID_from_string(name, &guid);
     674          56 :                 if (!NT_STATUS_IS_OK(nt_status)) {
     675           2 :                         info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
     676           2 :                         return WERR_OK;
     677             :                 }
     678             : 
     679          54 :                 ldap_guid = ldap_encode_ndr_GUID(mem_ctx, &guid);
     680          54 :                 if (!ldap_guid) {
     681           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     682             :                 }
     683          54 :                 result_filter = talloc_asprintf(mem_ctx, "(objectGUID=%s)",
     684             :                                                 ldap_guid);
     685          54 :                 W_ERROR_HAVE_NO_MEMORY(result_filter);
     686          54 :                 break;
     687             :         }
     688          23 :         case DRSUAPI_DS_NAME_FORMAT_DISPLAY: {
     689          23 :                 const char *name_encoded = NULL;
     690             : 
     691          23 :                 domain_filter = NULL;
     692             : 
     693          23 :                 name_encoded = ldb_binary_encode_string(mem_ctx, name);
     694          23 :                 if (name_encoded == NULL) {
     695           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     696             :                 }
     697             : 
     698          23 :                 result_filter = talloc_asprintf(mem_ctx, "(|(displayName=%s)(samAccountName=%s))",
     699             :                                                 name_encoded,
     700             :                                                 name_encoded);
     701          23 :                 W_ERROR_HAVE_NO_MEMORY(result_filter);
     702          23 :                 break;
     703             :         }
     704             : 
     705             :                 /* A S-1234-5678 style string */
     706         567 :         case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY: {
     707         567 :                 struct dom_sid *sid = dom_sid_parse_talloc(mem_ctx, name);
     708          72 :                 char *ldap_sid;
     709             : 
     710         567 :                 domain_filter = NULL;
     711         567 :                 if (!sid) {
     712           2 :                         info1->dns_domain_name = NULL;
     713           2 :                         info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
     714           2 :                         return WERR_OK;
     715             :                 }
     716         565 :                 ldap_sid = ldap_encode_ndr_dom_sid(mem_ctx,
     717             :                                                    sid);
     718         565 :                 if (!ldap_sid) {
     719           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     720             :                 }
     721         565 :                 result_filter = talloc_asprintf(mem_ctx, "(objectSid=%s)",
     722             :                                                 ldap_sid);
     723         565 :                 W_ERROR_HAVE_NO_MEMORY(result_filter);
     724         493 :                 break;
     725             :         }
     726      114532 :         case DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL: {
     727        4373 :                 krb5_principal principal;
     728        4373 :                 char *unparsed_name;
     729      114532 :                 const char *unparsed_name_encoded = NULL;
     730             : 
     731      114532 :                 ret = smb_krb5_init_context(mem_ctx,
     732      114532 :                                             (struct loadparm_context *)ldb_get_opaque(sam_ctx, "loadparm"),
     733             :                                             &smb_krb5_context);
     734             : 
     735      114532 :                 if (ret) {
     736           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     737             :                 }
     738             : 
     739             :                 /* Ensure we reject complete junk first */
     740      114532 :                 ret = krb5_parse_name(smb_krb5_context->krb5_context, name, &principal);
     741      114532 :                 if (ret) {
     742           0 :                         info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
     743           0 :                         return WERR_OK;
     744             :                 }
     745             : 
     746      114532 :                 domain_filter = NULL;
     747             : 
     748             :                 /*
     749             :                  * By getting the unparsed name here, we ensure the
     750             :                  * escaping is removed correctly (and trust the client
     751             :                  * less).  The important thing here is that a
     752             :                  * userPrincipalName may have a space in it, and this
     753             :                  * must not be kerberos escaped to match this filter,
     754             :                  * so we specify KRB5_PRINCIPAL_UNPARSE_DISPLAY
     755             :                  */
     756      114532 :                 ret = krb5_unparse_name_flags(smb_krb5_context->krb5_context,
     757             :                                               principal,
     758             :                                               KRB5_PRINCIPAL_UNPARSE_DISPLAY,
     759             :                                               &unparsed_name);
     760      114532 :                 if (ret) {
     761           0 :                         krb5_free_principal(smb_krb5_context->krb5_context, principal);
     762           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     763             :                 }
     764             : 
     765      114532 :                 krb5_free_principal(smb_krb5_context->krb5_context, principal);
     766             : 
     767             :                 /* The ldb_binary_encode_string() here avoids LDAP filter injection attacks */
     768      114532 :                 unparsed_name_encoded = ldb_binary_encode_string(mem_ctx, unparsed_name);
     769      114532 :                 if (unparsed_name_encoded == NULL) {
     770           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     771             :                 }
     772             : 
     773      114532 :                 result_filter = talloc_asprintf(mem_ctx, "(&(userPrincipalName=%s)(objectClass=user))",
     774             :                                                 unparsed_name_encoded);
     775             : 
     776      114532 :                 free(unparsed_name);
     777      114532 :                 W_ERROR_HAVE_NO_MEMORY(result_filter);
     778      114532 :                 break;
     779             :         }
     780       31653 :         case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL: {
     781        1160 :                 krb5_principal principal;
     782        1160 :                 char *unparsed_name_short;
     783       31653 :                 const char *unparsed_name_short_encoded = NULL;
     784       31653 :                 bool principal_is_host = false;
     785             : 
     786       31653 :                 ret = smb_krb5_init_context(mem_ctx,
     787       31653 :                                             (struct loadparm_context *)ldb_get_opaque(sam_ctx, "loadparm"),
     788             :                                             &smb_krb5_context);
     789             : 
     790       31653 :                 if (ret) {
     791           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     792             :                 }
     793             : 
     794       31653 :                 ret = krb5_parse_name(smb_krb5_context->krb5_context, name, &principal);
     795       63210 :                 if (ret == 0 &&
     796       31653 :                     krb5_princ_size(smb_krb5_context->krb5_context,
     797             :                                                         principal) < 2) {
     798           8 :                         info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
     799           8 :                         krb5_free_principal(smb_krb5_context->krb5_context, principal);
     800           8 :                         return WERR_OK;
     801       31645 :                 } else if (ret == 0) {
     802       31645 :                         krb5_free_principal(smb_krb5_context->krb5_context, principal);
     803             :                 }
     804       31645 :                 ret = krb5_parse_name_flags(smb_krb5_context->krb5_context, name,
     805             :                                             KRB5_PRINCIPAL_PARSE_NO_REALM, &principal);
     806       31645 :                 if (ret) {
     807           6 :                         return dns_domain_from_principal(mem_ctx, smb_krb5_context,
     808             :                                                          name, info1);
     809             :                 }
     810             : 
     811       31639 :                 domain_filter = NULL;
     812             : 
     813       31639 :                 ret = krb5_unparse_name_flags(smb_krb5_context->krb5_context, principal,
     814             :                                               KRB5_PRINCIPAL_UNPARSE_NO_REALM, &unparsed_name_short);
     815       31639 :                 if (ret) {
     816           0 :                         krb5_free_principal(smb_krb5_context->krb5_context, principal);
     817           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     818             :                 }
     819             : 
     820       31639 :                 unparsed_name_short_encoded = ldb_binary_encode_string(mem_ctx, unparsed_name_short);
     821       31639 :                 if (unparsed_name_short_encoded == NULL) {
     822           0 :                         krb5_free_principal(smb_krb5_context->krb5_context, principal);
     823           0 :                         free(unparsed_name_short);
     824           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     825             :                 }
     826             : 
     827       31639 :                 if ((krb5_princ_size(smb_krb5_context->krb5_context, principal) == 2)) {
     828        1160 :                         krb5_data component;
     829             : 
     830       31323 :                         ret = smb_krb5_princ_component(smb_krb5_context->krb5_context,
     831             :                                                        principal, 0, &component);
     832       31323 :                         if (ret) {
     833           0 :                                 krb5_free_principal(smb_krb5_context->krb5_context, principal);
     834           0 :                                 free(unparsed_name_short);
     835           0 :                                 return WERR_INTERNAL_ERROR;
     836             :                         }
     837             : 
     838       31323 :                         principal_is_host = strcasecmp(component.data, "host") == 0;
     839             :                 }
     840             : 
     841       31639 :                 if (principal_is_host) {
     842             :                         /* the 'cn' attribute is just the leading part of the name */
     843         545 :                         krb5_data component;
     844         545 :                         char *computer_name;
     845       18183 :                         const char *computer_name_encoded = NULL;
     846       18728 :                         ret = smb_krb5_princ_component(
     847       18183 :                                 smb_krb5_context->krb5_context,
     848             :                                 principal, 1, &component);
     849       18183 :                         if (ret) {
     850           0 :                                 krb5_free_principal(smb_krb5_context->krb5_context, principal);
     851           0 :                                 free(unparsed_name_short);
     852           0 :                                 return WERR_INTERNAL_ERROR;
     853             :                         }
     854       18728 :                         computer_name = talloc_strndup(mem_ctx, (char *)component.data,
     855       18183 :                                                         strcspn((char *)component.data, "."));
     856       18183 :                         if (computer_name == NULL) {
     857           0 :                                 krb5_free_principal(smb_krb5_context->krb5_context, principal);
     858           0 :                                 free(unparsed_name_short);
     859           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
     860             :                         }
     861             : 
     862       18183 :                         computer_name_encoded = ldb_binary_encode_string(mem_ctx, computer_name);
     863       18183 :                         if (computer_name_encoded == NULL) {
     864           0 :                                 krb5_free_principal(smb_krb5_context->krb5_context, principal);
     865           0 :                                 free(unparsed_name_short);
     866           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
     867             :                         }
     868             : 
     869       18183 :                         result_filter = talloc_asprintf(mem_ctx, "(|(&(servicePrincipalName=%s)(objectClass=user))(&(cn=%s)(objectClass=computer)))",
     870             :                                                         unparsed_name_short_encoded,
     871             :                                                         computer_name_encoded);
     872             :                 } else {
     873       13456 :                         result_filter = talloc_asprintf(mem_ctx, "(&(servicePrincipalName=%s)(objectClass=user))",
     874             :                                                         unparsed_name_short_encoded);
     875             :                 }
     876       31639 :                 krb5_free_principal(smb_krb5_context->krb5_context, principal);
     877       31639 :                 free(unparsed_name_short);
     878       31639 :                 W_ERROR_HAVE_NO_MEMORY(result_filter);
     879             : 
     880       31639 :                 break;
     881             :         }
     882           0 :         default: {
     883           0 :                 info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
     884           0 :                 return WERR_OK;
     885             :         }
     886             :         }
     887             : 
     888      277049 :         if (format_flags & DRSUAPI_DS_NAME_FLAG_SYNTACTICAL_ONLY) {
     889           4 :                 return DsCrackNameOneSyntactical(mem_ctx, format_offered, format_desired,
     890             :                                                  name_dn, name, info1);
     891             :         }
     892             : 
     893      277045 :         return DsCrackNameOneFilter(sam_ctx, mem_ctx,
     894             :                                     smb_krb5_context,
     895             :                                     format_flags, format_offered, format_desired,
     896             :                                     name_dn, name,
     897             :                                     domain_filter, result_filter,
     898             :                                     info1, scope, search_dn);
     899             : }
     900             : 
     901             : /* Subcase of CrackNames.  It is possible to translate a LDAP-style DN
     902             :  * (FQDN_1779) into a canonical name without actually searching the
     903             :  * database */
     904             : 
     905          29 : static WERROR DsCrackNameOneSyntactical(TALLOC_CTX *mem_ctx,
     906             :                                         enum drsuapi_DsNameFormat format_offered,
     907             :                                         enum drsuapi_DsNameFormat format_desired,
     908             :                                         struct ldb_dn *name_dn, const char *name,
     909             :                                         struct drsuapi_DsNameInfo1 *info1)
     910             : {
     911           0 :         char *cracked;
     912          29 :         if (format_offered != DRSUAPI_DS_NAME_FORMAT_FQDN_1779) {
     913           0 :                 info1->status = DRSUAPI_DS_NAME_STATUS_NO_SYNTACTICAL_MAPPING;
     914           0 :                 return WERR_OK;
     915             :         }
     916             : 
     917          29 :         switch (format_desired) {
     918           2 :         case DRSUAPI_DS_NAME_FORMAT_CANONICAL:
     919           2 :                 cracked = ldb_dn_canonical_string(mem_ctx, name_dn);
     920           2 :                 break;
     921          27 :         case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX:
     922          27 :                 cracked = ldb_dn_canonical_ex_string(mem_ctx, name_dn);
     923          27 :                 break;
     924           0 :         default:
     925           0 :                 info1->status = DRSUAPI_DS_NAME_STATUS_NO_SYNTACTICAL_MAPPING;
     926           0 :                 return WERR_OK;
     927             :         }
     928          29 :         info1->status = DRSUAPI_DS_NAME_STATUS_OK;
     929          29 :         info1->result_name   = cracked;
     930          29 :         if (!cracked) {
     931           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     932             :         }
     933             : 
     934          29 :         return WERR_OK;
     935             : }
     936             : 
     937             : /* Given a filter for the domain, and one for the result, perform the
     938             :  * ldb search. The format offered and desired flags change the
     939             :  * behaviours, including what attributes to return.
     940             :  *
     941             :  * The smb_krb5_context is required because we use the krb5 libs for principal parsing
     942             :  */
     943             : 
     944      389252 : static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
     945             :                                    struct smb_krb5_context *smb_krb5_context,
     946             :                                    uint32_t format_flags, enum drsuapi_DsNameFormat format_offered,
     947             :                                    enum drsuapi_DsNameFormat format_desired,
     948             :                                    struct ldb_dn *name_dn, const char *name,
     949             :                                    const char *domain_filter, const char *result_filter,
     950             :                                    struct drsuapi_DsNameInfo1 *info1,
     951             :                                    int scope, struct ldb_dn *search_dn)
     952             : {
     953       14083 :         int ldb_ret;
     954      389252 :         struct ldb_result *domain_res = NULL;
     955       14083 :         const char * const *domain_attrs;
     956       14083 :         const char * const *result_attrs;
     957      389252 :         struct ldb_message **result_res = NULL;
     958      389252 :         struct ldb_message *result = NULL;
     959       14083 :         int i;
     960       14083 :         char *p;
     961      389252 :         struct ldb_dn *partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx);
     962             : 
     963      389252 :         const char * const _domain_attrs_1779[] = { "ncName", "dnsRoot", NULL};
     964      389252 :         const char * const _result_attrs_null[] = { NULL };
     965             : 
     966      389252 :         const char * const _domain_attrs_canonical[] = { "ncName", "dnsRoot", NULL};
     967      389252 :         const char * const _result_attrs_canonical[] = { "canonicalName", NULL };
     968             : 
     969      389252 :         const char * const _domain_attrs_nt4[] = { "ncName", "dnsRoot", "nETBIOSName", NULL};
     970      389252 :         const char * const _result_attrs_nt4[] = { "sAMAccountName", "objectSid", "objectClass", NULL};
     971             : 
     972      389252 :         const char * const _domain_attrs_guid[] = { "ncName", "dnsRoot", NULL};
     973      389252 :         const char * const _result_attrs_guid[] = { "objectGUID", NULL};
     974             : 
     975      389252 :         const char * const _domain_attrs_upn[] = { "ncName", "dnsRoot", NULL};
     976      389252 :         const char * const _result_attrs_upn[] = { "userPrincipalName", NULL};
     977             : 
     978      389252 :         const char * const _domain_attrs_spn[] = { "ncName", "dnsRoot", NULL};
     979      389252 :         const char * const _result_attrs_spn[] = { "servicePrincipalName", NULL};
     980             : 
     981      389252 :         const char * const _domain_attrs_display[] = { "ncName", "dnsRoot", NULL};
     982      389252 :         const char * const _result_attrs_display[] = { "displayName", "samAccountName", NULL};
     983             : 
     984      389252 :         const char * const _domain_attrs_sid[] = { "ncName", "dnsRoot", NULL};
     985      389252 :         const char * const _result_attrs_sid[] = { "objectSid", NULL};
     986             : 
     987      389252 :         const char * const _domain_attrs_none[] = { "ncName", "dnsRoot" , NULL};
     988      389252 :         const char * const _result_attrs_none[] = { NULL};
     989             : 
     990             :         /* here we need to set the attrs lists for domain and result lookups */
     991      389252 :         switch (format_desired) {
     992      359777 :         case DRSUAPI_DS_NAME_FORMAT_FQDN_1779:
     993             :         case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX:
     994      359777 :                 domain_attrs = _domain_attrs_1779;
     995      359777 :                 result_attrs = _result_attrs_null;
     996      359777 :                 break;
     997          27 :         case DRSUAPI_DS_NAME_FORMAT_CANONICAL:
     998          27 :                 domain_attrs = _domain_attrs_canonical;
     999          27 :                 result_attrs = _result_attrs_canonical;
    1000          27 :                 break;
    1001       17126 :         case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT:
    1002       17126 :                 domain_attrs = _domain_attrs_nt4;
    1003       17126 :                 result_attrs = _result_attrs_nt4;
    1004       17126 :                 break;
    1005          39 :         case DRSUAPI_DS_NAME_FORMAT_GUID:
    1006          39 :                 domain_attrs = _domain_attrs_guid;
    1007          39 :                 result_attrs = _result_attrs_guid;
    1008          39 :                 break;
    1009          25 :         case DRSUAPI_DS_NAME_FORMAT_DISPLAY:
    1010          25 :                 domain_attrs = _domain_attrs_display;
    1011          25 :                 result_attrs = _result_attrs_display;
    1012          25 :                 break;
    1013          25 :         case DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL:
    1014          25 :                 domain_attrs = _domain_attrs_upn;
    1015          25 :                 result_attrs = _result_attrs_upn;
    1016          25 :                 break;
    1017          25 :         case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL:
    1018          25 :                 domain_attrs = _domain_attrs_spn;
    1019          25 :                 result_attrs = _result_attrs_spn;
    1020          25 :                 break;
    1021          23 :         case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY:
    1022          23 :                 domain_attrs = _domain_attrs_sid;
    1023          23 :                 result_attrs = _result_attrs_sid;
    1024          23 :                 break;
    1025          22 :         default:
    1026          22 :                 domain_attrs = _domain_attrs_none;
    1027          22 :                 result_attrs = _result_attrs_none;
    1028          22 :                 break;
    1029             :         }
    1030             : 
    1031      389252 :         if (domain_filter) {
    1032             :                 /* if we have a domain_filter look it up and set the result_basedn and the dns_domain_name */
    1033      242030 :                 ldb_ret = ldb_search(sam_ctx, mem_ctx, &domain_res,
    1034             :                                              partitions_basedn,
    1035             :                                              LDB_SCOPE_ONELEVEL,
    1036             :                                              domain_attrs,
    1037             :                                              "%s", domain_filter);
    1038             : 
    1039      242030 :                 if (ldb_ret != LDB_SUCCESS) {
    1040           0 :                         DEBUG(2, ("DsCrackNameOneFilter domain ref search failed: %s\n", ldb_errstring(sam_ctx)));
    1041           0 :                         info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
    1042           0 :                         return WERR_OK;
    1043             :                 }
    1044             : 
    1045      242030 :                 switch (domain_res->count) {
    1046      233542 :                 case 1:
    1047      242020 :                         break;
    1048          10 :                 case 0:
    1049          10 :                         info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
    1050          10 :                         return WERR_OK;
    1051           0 :                 default:
    1052           0 :                         info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
    1053           0 :                         return WERR_OK;
    1054             :                 }
    1055             : 
    1056      242020 :                 info1->dns_domain_name       = ldb_msg_find_attr_as_string(domain_res->msgs[0], "dnsRoot", NULL);
    1057      242020 :                 W_ERROR_HAVE_NO_MEMORY(info1->dns_domain_name);
    1058      242020 :                 info1->status                = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY;
    1059             :         } else {
    1060      147222 :                 info1->dns_domain_name       = NULL;
    1061      147222 :                 info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
    1062             :         }
    1063             : 
    1064      389242 :         if (result_filter) {
    1065        9975 :                 int ret;
    1066        9975 :                 struct ldb_result *res;
    1067      259129 :                 uint32_t dsdb_flags = 0;
    1068      259129 :                 struct ldb_dn *real_search_dn = NULL;
    1069      259129 :                 info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
    1070             : 
    1071             :                 /*
    1072             :                  * From 4.1.4.2.11 of MS-DRSR
    1073             :                  * if DS_NAME_FLAG_GCVERIFY in flags then
    1074             :                  * rt := select all O from all
    1075             :                  * where attrValue in GetAttrVals(O, att, false)
    1076             :                  * else
    1077             :                  * rt := select all O from subtree DefaultNC()
    1078             :                  * where attrValue in GetAttrVals(O, att, false)
    1079             :                  * endif
    1080             :                  * return rt
    1081             :                  */
    1082      259129 :                 if (format_flags & DRSUAPI_DS_NAME_FLAG_GCVERIFY ||
    1083             :                     format_offered == DRSUAPI_DS_NAME_FORMAT_GUID)
    1084             :                 {
    1085          54 :                         dsdb_flags = DSDB_SEARCH_SEARCH_ALL_PARTITIONS;
    1086      259075 :                 } else if (domain_res) {
    1087      112316 :                         if (!search_dn) {
    1088      112266 :                                 struct ldb_dn *tmp_dn = samdb_result_dn(sam_ctx, mem_ctx, domain_res->msgs[0], "ncName", NULL);
    1089      112266 :                                 real_search_dn = tmp_dn;
    1090             :                         } else {
    1091          50 :                                 real_search_dn = search_dn;
    1092             :                         }
    1093             :                 } else {
    1094      146759 :                         real_search_dn = ldb_get_default_basedn(sam_ctx);
    1095             :                 }
    1096      259129 :                 if (format_offered == DRSUAPI_DS_NAME_FORMAT_GUID){
    1097          54 :                          dsdb_flags |= DSDB_SEARCH_SHOW_RECYCLED;
    1098             :                 }
    1099             :                 /* search with the 'phantom root' flag */
    1100      259129 :                 ret = dsdb_search(sam_ctx, mem_ctx, &res,
    1101             :                                   real_search_dn,
    1102             :                                   scope,
    1103             :                                   result_attrs,
    1104             :                                   dsdb_flags,
    1105             :                                   "%s", result_filter);
    1106      259129 :                 if (ret != LDB_SUCCESS) {
    1107           0 :                         DEBUG(2, ("DsCrackNameOneFilter search from '%s' with flags 0x%08x failed: %s\n",
    1108             :                                   ldb_dn_get_linearized(real_search_dn),
    1109             :                                   dsdb_flags,
    1110             :                                   ldb_errstring(sam_ctx)));
    1111           0 :                         info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
    1112           0 :                         return WERR_OK;
    1113             :                 }
    1114             : 
    1115      259129 :                 ldb_ret = res->count;
    1116      259129 :                 result_res = res->msgs;
    1117      130113 :         } else if (format_offered == DRSUAPI_DS_NAME_FORMAT_FQDN_1779) {
    1118         409 :                 ldb_ret = gendb_search_dn(sam_ctx, mem_ctx, name_dn, &result_res,
    1119             :                                           result_attrs);
    1120      129704 :         } else if (domain_res) {
    1121      129704 :                 name_dn = samdb_result_dn(sam_ctx, mem_ctx, domain_res->msgs[0], "ncName", NULL);
    1122      129704 :                 ldb_ret = gendb_search_dn(sam_ctx, mem_ctx, name_dn, &result_res,
    1123             :                                           result_attrs);
    1124             :         } else {
    1125             :                 /* Can't happen */
    1126           0 :                 DEBUG(0, ("LOGIC ERROR: DsCrackNameOneFilter domain ref search not available: This can't happen...\n"));
    1127           0 :                 info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
    1128           0 :                 return WERR_OK;
    1129             :         }
    1130             : 
    1131      389242 :         switch (ldb_ret) {
    1132      268474 :         case 1:
    1133      268474 :                 result = result_res[0];
    1134      268474 :                 break;
    1135      120768 :         case 0:
    1136        4907 :                 switch (format_offered) {
    1137        5764 :                 case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL:
    1138      116398 :                         return DsCrackNameSPNAlias(sam_ctx, mem_ctx,
    1139             :                                                    smb_krb5_context,
    1140             :                                                    format_flags, format_offered, format_desired,
    1141             :                                                    name, info1);
    1142             : 
    1143      114991 :                 case DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL:
    1144      114991 :                         return DsCrackNameUPN(sam_ctx, mem_ctx, smb_krb5_context,
    1145             :                                               format_flags, format_offered, format_desired,
    1146             :                                               name, info1);
    1147          13 :                 default:
    1148          13 :                         break;
    1149             :                 }
    1150          13 :                 info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
    1151          13 :                 return WERR_OK;
    1152           0 :         case -1:
    1153           0 :                 DEBUG(2, ("DsCrackNameOneFilter result search failed: %s\n", ldb_errstring(sam_ctx)));
    1154           0 :                 info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
    1155           0 :                 return WERR_OK;
    1156           0 :         default:
    1157           0 :                 switch (format_offered) {
    1158           0 :                 case DRSUAPI_DS_NAME_FORMAT_CANONICAL:
    1159             :                 case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX:
    1160             :                 {
    1161           0 :                         const char *canonical_name = NULL; /* Not required, but we get warnings... */
    1162             :                         /* We may need to manually filter further */
    1163           0 :                         for (i = 0; i < ldb_ret; i++) {
    1164           0 :                                 switch (format_offered) {
    1165           0 :                                 case DRSUAPI_DS_NAME_FORMAT_CANONICAL:
    1166           0 :                                         canonical_name = ldb_dn_canonical_string(mem_ctx, result_res[i]->dn);
    1167           0 :                                         break;
    1168           0 :                                 case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX:
    1169           0 :                                         canonical_name = ldb_dn_canonical_ex_string(mem_ctx, result_res[i]->dn);
    1170           0 :                                         break;
    1171           0 :                                 default:
    1172           0 :                                         break;
    1173             :                                 }
    1174           0 :                                 if (strcasecmp_m(canonical_name, name) == 0) {
    1175           0 :                                         result = result_res[i];
    1176           0 :                                         break;
    1177             :                                 }
    1178             :                         }
    1179           0 :                         if (!result) {
    1180           0 :                                 info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
    1181           0 :                                 return WERR_OK;
    1182             :                         }
    1183             :                 }
    1184           0 :                 FALL_THROUGH;
    1185             :                 default:
    1186           0 :                         info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
    1187           0 :                         return WERR_OK;
    1188             :                 }
    1189             :         }
    1190             : 
    1191      268474 :         info1->dns_domain_name = ldb_dn_canonical_string(mem_ctx, result->dn);
    1192      268474 :         W_ERROR_HAVE_NO_MEMORY(info1->dns_domain_name);
    1193      268474 :         p = strchr(info1->dns_domain_name, '/');
    1194      268474 :         if (p) {
    1195      268474 :                 p[0] = '\0';
    1196             :         }
    1197             : 
    1198             :         /* here we can use result and domain_res[0] */
    1199      268474 :         switch (format_desired) {
    1200      259488 :         case DRSUAPI_DS_NAME_FORMAT_FQDN_1779: {
    1201      259488 :                 info1->result_name   = ldb_dn_alloc_linearized(mem_ctx, result->dn);
    1202      259488 :                 W_ERROR_HAVE_NO_MEMORY(info1->result_name);
    1203             : 
    1204      259488 :                 info1->status                = DRSUAPI_DS_NAME_STATUS_OK;
    1205      259488 :                 return WERR_OK;
    1206             :         }
    1207          25 :         case DRSUAPI_DS_NAME_FORMAT_CANONICAL: {
    1208          25 :                 info1->result_name   = ldb_msg_find_attr_as_string(result, "canonicalName", NULL);
    1209          25 :                 info1->status                = DRSUAPI_DS_NAME_STATUS_OK;
    1210          25 :                 return WERR_OK;
    1211             :         }
    1212          25 :         case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX: {
    1213             :                 /* Not in the virtual ldb attribute */
    1214          25 :                 return DsCrackNameOneSyntactical(mem_ctx,
    1215             :                                                  DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
    1216             :                                                  DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX,
    1217             :                                                  result->dn, name, info1);
    1218             :         }
    1219        8789 :         case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT: {
    1220             : 
    1221        8789 :                 const struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, result, "objectSid");
    1222        8789 :                 const char *_acc = "", *_dom = "";
    1223        8789 :                 if (sid == NULL) {
    1224           0 :                         info1->status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING;
    1225           0 :                         return WERR_OK;
    1226             :                 }
    1227             : 
    1228        8789 :                 if (samdb_find_attribute(sam_ctx, result, "objectClass",
    1229             :                                          "domain")) {
    1230             :                         /* This can also find a DomainDNSZones entry,
    1231             :                          * but it won't have the SID we just
    1232             :                          * checked.  */
    1233          15 :                         ldb_ret = ldb_search(sam_ctx, mem_ctx, &domain_res,
    1234             :                                                      partitions_basedn,
    1235             :                                                      LDB_SCOPE_ONELEVEL,
    1236             :                                                      domain_attrs,
    1237             :                                                      "(ncName=%s)", ldb_dn_get_linearized(result->dn));
    1238             : 
    1239          15 :                         if (ldb_ret != LDB_SUCCESS) {
    1240           0 :                                 DEBUG(2, ("DsCrackNameOneFilter domain ref search failed: %s\n", ldb_errstring(sam_ctx)));
    1241           0 :                                 info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
    1242           0 :                                 return WERR_OK;
    1243             :                         }
    1244             : 
    1245          15 :                         switch (domain_res->count) {
    1246          15 :                         case 1:
    1247          15 :                                 break;
    1248           0 :                         case 0:
    1249           0 :                                 info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
    1250           0 :                                 return WERR_OK;
    1251           0 :                         default:
    1252           0 :                                 info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
    1253           0 :                                 return WERR_OK;
    1254             :                         }
    1255          15 :                         _dom = ldb_msg_find_attr_as_string(domain_res->msgs[0], "nETBIOSName", NULL);
    1256          15 :                         W_ERROR_HAVE_NO_MEMORY(_dom);
    1257             :                 } else {
    1258        8774 :                         _acc = ldb_msg_find_attr_as_string(result, "sAMAccountName", NULL);
    1259        8774 :                         if (!_acc) {
    1260           2 :                                 info1->status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING;
    1261           2 :                                 return WERR_OK;
    1262             :                         }
    1263        8772 :                         if (dom_sid_in_domain(&global_sid_Builtin, sid)) {
    1264           2 :                                 _dom = "BUILTIN";
    1265             :                         } else {
    1266        8770 :                                 const char *attrs[] = { NULL };
    1267         960 :                                 struct ldb_result *domain_res2;
    1268        8770 :                                 struct dom_sid *dom_sid = dom_sid_dup(mem_ctx, sid);
    1269        8770 :                                 if (!dom_sid) {
    1270           0 :                                         return WERR_OK;
    1271             :                                 }
    1272        8770 :                                 dom_sid->num_auths--;
    1273        8770 :                                 ldb_ret = ldb_search(sam_ctx, mem_ctx, &domain_res,
    1274             :                                                              NULL,
    1275             :                                                              LDB_SCOPE_BASE,
    1276             :                                                              attrs,
    1277             :                                                              "(&(objectSid=%s)(objectClass=domain))",
    1278             :                                                              ldap_encode_ndr_dom_sid(mem_ctx, dom_sid));
    1279             : 
    1280        8770 :                                 if (ldb_ret != LDB_SUCCESS) {
    1281           0 :                                         DEBUG(2, ("DsCrackNameOneFilter domain search failed: %s\n", ldb_errstring(sam_ctx)));
    1282           0 :                                         info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
    1283           0 :                                         return WERR_OK;
    1284             :                                 }
    1285             : 
    1286        8770 :                                 switch (domain_res->count) {
    1287        7810 :                                 case 1:
    1288        8770 :                                         break;
    1289           0 :                                 case 0:
    1290           0 :                                         info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
    1291           0 :                                         return WERR_OK;
    1292           0 :                                 default:
    1293           0 :                                         info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
    1294           0 :                                         return WERR_OK;
    1295             :                                 }
    1296             : 
    1297        8770 :                                 ldb_ret = ldb_search(sam_ctx, mem_ctx, &domain_res2,
    1298             :                                                              partitions_basedn,
    1299             :                                                              LDB_SCOPE_ONELEVEL,
    1300             :                                                              domain_attrs,
    1301        8770 :                                                              "(ncName=%s)", ldb_dn_get_linearized(domain_res->msgs[0]->dn));
    1302             : 
    1303        8770 :                                 if (ldb_ret != LDB_SUCCESS) {
    1304           0 :                                         DEBUG(2, ("DsCrackNameOneFilter domain ref search failed: %s\n", ldb_errstring(sam_ctx)));
    1305           0 :                                         info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
    1306           0 :                                         return WERR_OK;
    1307             :                                 }
    1308             : 
    1309        8770 :                                 switch (domain_res2->count) {
    1310        7810 :                                 case 1:
    1311        8770 :                                         break;
    1312           0 :                                 case 0:
    1313           0 :                                         info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
    1314           0 :                                         return WERR_OK;
    1315           0 :                                 default:
    1316           0 :                                         info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
    1317           0 :                                         return WERR_OK;
    1318             :                                 }
    1319        8770 :                                 _dom = ldb_msg_find_attr_as_string(domain_res2->msgs[0], "nETBIOSName", NULL);
    1320        8770 :                                 W_ERROR_HAVE_NO_MEMORY(_dom);
    1321             :                         }
    1322             :                 }
    1323             : 
    1324        8787 :                 info1->result_name   = talloc_asprintf(mem_ctx, "%s\\%s", _dom, _acc);
    1325        8787 :                 W_ERROR_HAVE_NO_MEMORY(info1->result_name);
    1326             : 
    1327        8787 :                 info1->status                = DRSUAPI_DS_NAME_STATUS_OK;
    1328        8787 :                 return WERR_OK;
    1329             :         }
    1330          37 :         case DRSUAPI_DS_NAME_FORMAT_GUID: {
    1331           0 :                 struct GUID guid;
    1332             : 
    1333          37 :                 guid = samdb_result_guid(result, "objectGUID");
    1334             : 
    1335          37 :                 info1->result_name   = GUID_string2(mem_ctx, &guid);
    1336          37 :                 W_ERROR_HAVE_NO_MEMORY(info1->result_name);
    1337             : 
    1338          37 :                 info1->status                = DRSUAPI_DS_NAME_STATUS_OK;
    1339          37 :                 return WERR_OK;
    1340             :         }
    1341          23 :         case DRSUAPI_DS_NAME_FORMAT_DISPLAY: {
    1342          23 :                 info1->result_name   = ldb_msg_find_attr_as_string(result, "displayName", NULL);
    1343          23 :                 if (!info1->result_name) {
    1344           0 :                         info1->result_name   = ldb_msg_find_attr_as_string(result, "sAMAccountName", NULL);
    1345             :                 }
    1346          23 :                 if (!info1->result_name) {
    1347           0 :                         info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
    1348             :                 } else {
    1349          23 :                         info1->status = DRSUAPI_DS_NAME_STATUS_OK;
    1350             :                 }
    1351          23 :                 return WERR_OK;
    1352             :         }
    1353          23 :         case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL: {
    1354           0 :                 struct ldb_message_element *el
    1355          23 :                         = ldb_msg_find_element(result,
    1356             :                                                "servicePrincipalName");
    1357          23 :                 if (el == NULL) {
    1358           1 :                         info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
    1359           1 :                         return WERR_OK;
    1360          22 :                 } else if (el->num_values > 1) {
    1361          21 :                         info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
    1362          21 :                         return WERR_OK;
    1363             :                 }
    1364             : 
    1365           1 :                 info1->result_name = ldb_msg_find_attr_as_string(result, "servicePrincipalName", NULL);
    1366           1 :                 if (!info1->result_name) {
    1367           0 :                         info1->status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING;
    1368             :                 } else {
    1369           1 :                         info1->status = DRSUAPI_DS_NAME_STATUS_OK;
    1370             :                 }
    1371           1 :                 return WERR_OK;
    1372             :         }
    1373          20 :         case DRSUAPI_DS_NAME_FORMAT_DNS_DOMAIN: {
    1374          20 :                 info1->dns_domain_name = NULL;
    1375          20 :                 info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
    1376          20 :                 return WERR_OK;
    1377             :         }
    1378          21 :         case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY: {
    1379          21 :                 const struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, result, "objectSid");
    1380             : 
    1381          21 :                 if (sid == NULL) {
    1382           0 :                         info1->status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING;
    1383           0 :                         return WERR_OK;
    1384             :                 }
    1385             : 
    1386          21 :                 info1->result_name = dom_sid_string(mem_ctx, sid);
    1387          21 :                 W_ERROR_HAVE_NO_MEMORY(info1->result_name);
    1388             : 
    1389          21 :                 info1->status = DRSUAPI_DS_NAME_STATUS_OK;
    1390          21 :                 return WERR_OK;
    1391             :         }
    1392          23 :         case DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL: {
    1393          23 :                 info1->result_name = ldb_msg_find_attr_as_string(result, "userPrincipalName", NULL);
    1394          23 :                 if (!info1->result_name) {
    1395          22 :                         info1->status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING;
    1396             :                 } else {
    1397           1 :                         info1->status = DRSUAPI_DS_NAME_STATUS_OK;
    1398             :                 }
    1399          23 :                 return WERR_OK;
    1400             :         }
    1401           0 :         default:
    1402           0 :                 info1->status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING;
    1403           0 :                 return WERR_OK;
    1404             :         }
    1405             : }
    1406             : 
    1407             : /* Given a user Principal Name (such as foo@bar.com),
    1408             :  * return the user and domain DNs.  This is used in the KDC to then
    1409             :  * return the Keys and evaluate policy */
    1410             : 
    1411      106150 : NTSTATUS crack_user_principal_name(struct ldb_context *sam_ctx,
    1412             :                                    TALLOC_CTX *mem_ctx,
    1413             :                                    const char *user_principal_name,
    1414             :                                    struct ldb_dn **user_dn,
    1415             :                                    struct ldb_dn **domain_dn)
    1416             : {
    1417        3413 :         WERROR werr;
    1418        3413 :         struct drsuapi_DsNameInfo1 info1;
    1419      106150 :         werr = DsCrackNameOneName(sam_ctx, mem_ctx, 0,
    1420             :                                   DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
    1421             :                                   DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
    1422             :                                   user_principal_name,
    1423             :                                   &info1);
    1424      106150 :         if (!W_ERROR_IS_OK(werr)) {
    1425           0 :                 return werror_to_ntstatus(werr);
    1426             :         }
    1427      106150 :         switch (info1.status) {
    1428       99961 :         case DRSUAPI_DS_NAME_STATUS_OK:
    1429      103374 :                 break;
    1430        2776 :         case DRSUAPI_DS_NAME_STATUS_NOT_FOUND:
    1431             :         case DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY:
    1432             :         case DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE:
    1433        2776 :                 return NT_STATUS_NO_SUCH_USER;
    1434           0 :         case DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR:
    1435             :         default:
    1436           0 :                 return NT_STATUS_UNSUCCESSFUL;
    1437             :         }
    1438             : 
    1439      103374 :         *user_dn = ldb_dn_new(mem_ctx, sam_ctx, info1.result_name);
    1440             : 
    1441      103374 :         if (domain_dn) {
    1442      103351 :                 werr = DsCrackNameOneName(sam_ctx, mem_ctx, 0,
    1443             :                                           DRSUAPI_DS_NAME_FORMAT_CANONICAL,
    1444             :                                           DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
    1445      103351 :                                           talloc_asprintf(mem_ctx, "%s/",
    1446             :                                                           info1.dns_domain_name),
    1447             :                                           &info1);
    1448      103351 :                 if (!W_ERROR_IS_OK(werr)) {
    1449           0 :                         return werror_to_ntstatus(werr);
    1450             :                 }
    1451      103351 :                 switch (info1.status) {
    1452       99938 :                 case DRSUAPI_DS_NAME_STATUS_OK:
    1453      103351 :                         break;
    1454           0 :                 case DRSUAPI_DS_NAME_STATUS_NOT_FOUND:
    1455             :                 case DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY:
    1456             :                 case DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE:
    1457           0 :                         return NT_STATUS_NO_SUCH_USER;
    1458           0 :                 case DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR:
    1459             :                 default:
    1460           0 :                         return NT_STATUS_UNSUCCESSFUL;
    1461             :                 }
    1462             : 
    1463      103351 :                 *domain_dn = ldb_dn_new(mem_ctx, sam_ctx, info1.result_name);
    1464             :         }
    1465             : 
    1466      103374 :         return NT_STATUS_OK;
    1467             : }
    1468             : 
    1469             : /* Given a Service Principal Name (such as host/foo.bar.com@BAR.COM),
    1470             :  * return the user and domain DNs.  This is used in the KDC to then
    1471             :  * return the Keys and evaluate policy */
    1472             : 
    1473       26224 : NTSTATUS crack_service_principal_name(struct ldb_context *sam_ctx,
    1474             :                                       TALLOC_CTX *mem_ctx,
    1475             :                                       const char *service_principal_name,
    1476             :                                       struct ldb_dn **user_dn,
    1477             :                                       struct ldb_dn **domain_dn)
    1478             : {
    1479         623 :         WERROR werr;
    1480         623 :         struct drsuapi_DsNameInfo1 info1;
    1481       26224 :         werr = DsCrackNameOneName(sam_ctx, mem_ctx, 0,
    1482             :                                   DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
    1483             :                                   DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
    1484             :                                   service_principal_name,
    1485             :                                   &info1);
    1486       26224 :         if (!W_ERROR_IS_OK(werr)) {
    1487           0 :                 return werror_to_ntstatus(werr);
    1488             :         }
    1489       26224 :         switch (info1.status) {
    1490       25221 :         case DRSUAPI_DS_NAME_STATUS_OK:
    1491       25844 :                 break;
    1492         380 :         case DRSUAPI_DS_NAME_STATUS_NOT_FOUND:
    1493             :         case DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY:
    1494             :         case DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE:
    1495         380 :                 return NT_STATUS_NO_SUCH_USER;
    1496           0 :         case DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR:
    1497             :         default:
    1498           0 :                 return NT_STATUS_UNSUCCESSFUL;
    1499             :         }
    1500             : 
    1501       25844 :         *user_dn = ldb_dn_new(mem_ctx, sam_ctx, info1.result_name);
    1502             : 
    1503       25844 :         if (domain_dn) {
    1504       25844 :                 werr = DsCrackNameOneName(sam_ctx, mem_ctx, 0,
    1505             :                                           DRSUAPI_DS_NAME_FORMAT_CANONICAL,
    1506             :                                           DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
    1507       25844 :                                           talloc_asprintf(mem_ctx, "%s/",
    1508             :                                                           info1.dns_domain_name),
    1509             :                                           &info1);
    1510       25844 :                 if (!W_ERROR_IS_OK(werr)) {
    1511           0 :                         return werror_to_ntstatus(werr);
    1512             :                 }
    1513       25844 :                 switch (info1.status) {
    1514       25221 :                 case DRSUAPI_DS_NAME_STATUS_OK:
    1515       25844 :                         break;
    1516           0 :                 case DRSUAPI_DS_NAME_STATUS_NOT_FOUND:
    1517             :                 case DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY:
    1518             :                 case DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE:
    1519           0 :                         return NT_STATUS_NO_SUCH_USER;
    1520           0 :                 case DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR:
    1521             :                 default:
    1522           0 :                         return NT_STATUS_UNSUCCESSFUL;
    1523             :                 }
    1524             : 
    1525       25844 :                 *domain_dn = ldb_dn_new(mem_ctx, sam_ctx, info1.result_name);
    1526             :         }
    1527             : 
    1528       25844 :         return NT_STATUS_OK;
    1529             : }
    1530             : 
    1531        8750 : NTSTATUS crack_name_to_nt4_name(TALLOC_CTX *mem_ctx,
    1532             :                                 struct ldb_context *ldb,
    1533             :                                 enum drsuapi_DsNameFormat format_offered,
    1534             :                                 const char *name,
    1535             :                                 const char **nt4_domain, const char **nt4_account)
    1536             : {
    1537         960 :         WERROR werr;
    1538         960 :         struct drsuapi_DsNameInfo1 info1;
    1539         960 :         char *p;
    1540             : 
    1541             :         /* Handle anonymous bind */
    1542        8750 :         if (!name || !*name) {
    1543           0 :                 *nt4_domain = "";
    1544           0 :                 *nt4_account = "";
    1545           0 :                 return NT_STATUS_OK;
    1546             :         }
    1547             : 
    1548        8750 :         werr = DsCrackNameOneName(ldb, mem_ctx, 0,
    1549             :                                   format_offered,
    1550             :                                   DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
    1551             :                                   name,
    1552             :                                   &info1);
    1553        8750 :         if (!W_ERROR_IS_OK(werr)) {
    1554           0 :                 return werror_to_ntstatus(werr);
    1555             :         }
    1556        8750 :         switch (info1.status) {
    1557        7785 :         case DRSUAPI_DS_NAME_STATUS_OK:
    1558        8745 :                 break;
    1559           5 :         case DRSUAPI_DS_NAME_STATUS_NOT_FOUND:
    1560             :         case DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY:
    1561             :         case DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE:
    1562           5 :                 return NT_STATUS_NO_SUCH_USER;
    1563           0 :         case DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR:
    1564             :         default:
    1565           0 :                 return NT_STATUS_UNSUCCESSFUL;
    1566             :         }
    1567             : 
    1568        8745 :         *nt4_domain = talloc_strdup(mem_ctx, info1.result_name);
    1569        8745 :         if (*nt4_domain == NULL) {
    1570           0 :                 return NT_STATUS_NO_MEMORY;
    1571             :         }
    1572             : 
    1573        8745 :         p = strchr(*nt4_domain, '\\');
    1574        8745 :         if (!p) {
    1575           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1576             :         }
    1577        8745 :         p[0] = '\0';
    1578             : 
    1579        8745 :         *nt4_account = talloc_strdup(mem_ctx, &p[1]);
    1580        8745 :         if (*nt4_account == NULL) {
    1581           0 :                 return NT_STATUS_NO_MEMORY;
    1582             :         }
    1583             : 
    1584        8745 :         return NT_STATUS_OK;
    1585             : }
    1586             : 
    1587         466 : NTSTATUS crack_auto_name_to_nt4_name(TALLOC_CTX *mem_ctx,
    1588             :                                      struct ldb_context *ldb,
    1589             :                                      const char *name,
    1590             :                                      const char **nt4_domain,
    1591             :                                      const char **nt4_account)
    1592             : {
    1593         466 :         enum drsuapi_DsNameFormat format_offered = DRSUAPI_DS_NAME_FORMAT_UNKNOWN;
    1594             : 
    1595             :         /* Handle anonymous bind */
    1596         466 :         if (!name || !*name) {
    1597          18 :                 *nt4_domain = "";
    1598          18 :                 *nt4_account = "";
    1599          18 :                 return NT_STATUS_OK;
    1600             :         }
    1601             : 
    1602             :         /*
    1603             :          * Here we only consider a subset of the possible name forms listed in
    1604             :          * [MS-ADTS] 5.1.1.1.1, and we don't retry with a different name form if
    1605             :          * the first attempt fails.
    1606             :          */
    1607             : 
    1608         448 :         if (strchr_m(name, '=')) {
    1609         355 :                 format_offered = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
    1610          93 :         } else if (strchr_m(name, '@')) {
    1611          45 :                 format_offered = DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL;
    1612          48 :         } else if (strchr_m(name, '\\')) {
    1613          36 :                 format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
    1614          12 :         } else if (strchr_m(name, '\n')) {
    1615           2 :                 format_offered = DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX;
    1616          10 :         } else if (strchr_m(name, '/')) {
    1617           2 :                 format_offered = DRSUAPI_DS_NAME_FORMAT_CANONICAL;
    1618           8 :         } else if ((name[0] == 'S' || name[0] == 's') && name[1] == '-') {
    1619           6 :                 format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY;
    1620             :         } else {
    1621           2 :                 return NT_STATUS_NO_SUCH_USER;
    1622             :         }
    1623             : 
    1624         446 :         return crack_name_to_nt4_name(mem_ctx, ldb, format_offered, name, nt4_domain, nt4_account);
    1625             : }
    1626             : 
    1627             : 
    1628           0 : WERROR dcesrv_drsuapi_ListRoles(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
    1629             :                                 const struct drsuapi_DsNameRequest1 *req1,
    1630             :                                 struct drsuapi_DsNameCtr1 **ctr1)
    1631             : {
    1632           0 :         struct drsuapi_DsNameInfo1 *names;
    1633           0 :         uint32_t i;
    1634           0 :         uint32_t count = 5;/*number of fsmo role owners we are going to return*/
    1635             : 
    1636           0 :         *ctr1 = talloc(mem_ctx, struct drsuapi_DsNameCtr1);
    1637           0 :         W_ERROR_HAVE_NO_MEMORY(*ctr1);
    1638           0 :         names = talloc_array(mem_ctx, struct drsuapi_DsNameInfo1, count);
    1639           0 :         W_ERROR_HAVE_NO_MEMORY(names);
    1640             : 
    1641           0 :         for (i = 0; i < count; i++) {
    1642           0 :                 WERROR werr;
    1643           0 :                 struct ldb_dn *role_owner_dn, *fsmo_role_dn, *server_dn;
    1644           0 :                 werr = dsdb_get_fsmo_role_info(mem_ctx, sam_ctx, i,
    1645             :                                                &fsmo_role_dn, &role_owner_dn);
    1646           0 :                 if(!W_ERROR_IS_OK(werr)) {
    1647           0 :                         return werr;
    1648             :                 }
    1649           0 :                 server_dn = ldb_dn_copy(mem_ctx, role_owner_dn);
    1650           0 :                 ldb_dn_remove_child_components(server_dn, 1);
    1651           0 :                 names[i].status = DRSUAPI_DS_NAME_STATUS_OK;
    1652           0 :                 names[i].dns_domain_name = samdb_dn_to_dnshostname(sam_ctx, mem_ctx,
    1653             :                                                                    server_dn);
    1654           0 :                 if(!names[i].dns_domain_name) {
    1655           0 :                         DEBUG(4, ("list_roles: Failed to find dNSHostName for server %s\n",
    1656             :                                   ldb_dn_get_linearized(server_dn)));
    1657             :                 }
    1658           0 :                 names[i].result_name = talloc_strdup(mem_ctx, ldb_dn_get_linearized(role_owner_dn));
    1659             :         }
    1660             : 
    1661           0 :         (*ctr1)->count = count;
    1662           0 :         (*ctr1)->array = names;
    1663             : 
    1664           0 :         return WERR_OK;
    1665             : }
    1666             : 
    1667        1395 : WERROR dcesrv_drsuapi_CrackNamesByNameFormat(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
    1668             :                                              const struct drsuapi_DsNameRequest1 *req1,
    1669             :                                              struct drsuapi_DsNameCtr1 **ctr1)
    1670             : {
    1671         144 :         struct drsuapi_DsNameInfo1 *names;
    1672         144 :         uint32_t i, count;
    1673         144 :         WERROR status;
    1674             : 
    1675        1395 :         *ctr1 = talloc_zero(mem_ctx, struct drsuapi_DsNameCtr1);
    1676        1395 :         W_ERROR_HAVE_NO_MEMORY(*ctr1);
    1677             : 
    1678        1395 :         count = req1->count;
    1679        1395 :         names = talloc_array(mem_ctx, struct drsuapi_DsNameInfo1, count);
    1680        1395 :         W_ERROR_HAVE_NO_MEMORY(names);
    1681             : 
    1682        2790 :         for (i=0; i < count; i++) {
    1683        1395 :                 status = DsCrackNameOneName(sam_ctx, mem_ctx,
    1684        1395 :                                             req1->format_flags,
    1685        1395 :                                             req1->format_offered,
    1686        1395 :                                             req1->format_desired,
    1687        1395 :                                             req1->names[i].str,
    1688        1395 :                                             &names[i]);
    1689        1395 :                 if (!W_ERROR_IS_OK(status)) {
    1690           0 :                         return status;
    1691             :                 }
    1692             :         }
    1693             : 
    1694        1395 :         (*ctr1)->count = count;
    1695        1395 :         (*ctr1)->array = names;
    1696             : 
    1697        1395 :         return WERR_OK;
    1698             : }
    1699             : 
    1700           0 : WERROR dcesrv_drsuapi_ListInfoServer(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
    1701             :                                      const struct drsuapi_DsNameRequest1 *req1,
    1702             :                                      struct drsuapi_DsNameCtr1 **_ctr1)
    1703             : {
    1704           0 :         struct drsuapi_DsNameInfo1 *names;
    1705           0 :         struct ldb_result *res;
    1706           0 :         struct ldb_dn *server_dn, *dn;
    1707           0 :         struct drsuapi_DsNameCtr1 *ctr1;
    1708           0 :         int ret, i;
    1709           0 :         const char *str;
    1710           0 :         const char *attrs[] = {
    1711             :                 "dNSHostName",
    1712             :                 "serverReference",
    1713             :                 NULL
    1714             :         };
    1715             : 
    1716           0 :         *_ctr1 = NULL;
    1717             : 
    1718           0 :         ctr1 = talloc_zero(mem_ctx, struct drsuapi_DsNameCtr1);
    1719           0 :         W_ERROR_HAVE_NO_MEMORY(ctr1);
    1720             : 
    1721             :         /*
    1722             :          * No magic value here, we have to return 3 entries according to the
    1723             :          * MS-DRSR.pdf
    1724             :          */
    1725           0 :         ctr1->count = 3;
    1726           0 :         names = talloc_zero_array(ctr1, struct drsuapi_DsNameInfo1,
    1727             :                                   ctr1->count);
    1728           0 :         W_ERROR_HAVE_NO_MEMORY(names);
    1729           0 :         ctr1->array = names;
    1730             : 
    1731           0 :         for (i=0; i < ctr1->count; i++) {
    1732           0 :                 names[i].status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
    1733             :         }
    1734           0 :         *_ctr1 = ctr1;
    1735             : 
    1736           0 :         if (req1->count != 1) {
    1737           0 :                 DEBUG(1, ("Expected a count of 1 for the ListInfoServer crackname \n"));
    1738           0 :                 return WERR_OK;
    1739             :         }
    1740             : 
    1741           0 :         if (req1->names[0].str == NULL) {
    1742           0 :                 return WERR_OK;
    1743             :         }
    1744             : 
    1745           0 :         server_dn = ldb_dn_new(mem_ctx, sam_ctx, req1->names[0].str);
    1746           0 :         W_ERROR_HAVE_NO_MEMORY(server_dn);
    1747             : 
    1748           0 :         ret = ldb_search(sam_ctx, mem_ctx, &res, server_dn, LDB_SCOPE_ONELEVEL,
    1749             :                          NULL, "(objectClass=nTDSDSA)");
    1750             : 
    1751           0 :         if (ret != LDB_SUCCESS) {
    1752           0 :                 DEBUG(1, ("Search for objectClass=nTDSDSA "
    1753             :                           "returned less than 1 objects\n"));
    1754           0 :                 return WERR_OK;
    1755             :         }
    1756             : 
    1757           0 :         if (res->count != 1) {
    1758           0 :                 DEBUG(1, ("Search for objectClass=nTDSDSA "
    1759             :                           "returned less than 1 objects\n"));
    1760           0 :                 return WERR_OK;
    1761             :         }
    1762             : 
    1763           0 :         if (res->msgs[0]->dn) {
    1764           0 :                 names[0].result_name = ldb_dn_alloc_linearized(names, res->msgs[0]->dn);
    1765           0 :                 W_ERROR_HAVE_NO_MEMORY(names[0].result_name);
    1766           0 :                 names[0].status = DRSUAPI_DS_NAME_STATUS_OK;
    1767             :         }
    1768             : 
    1769           0 :         talloc_free(res);
    1770             : 
    1771           0 :         ret = ldb_search(sam_ctx, mem_ctx, &res, server_dn, LDB_SCOPE_BASE,
    1772             :                          attrs, "(objectClass=*)");
    1773           0 :         if (ret != LDB_SUCCESS) {
    1774           0 :                 DEBUG(1, ("Search for objectClass=* on dn %s"
    1775             :                           "returned %s\n", req1->names[0].str,
    1776             :                           ldb_strerror(ret)));
    1777           0 :                 return WERR_OK;
    1778             :         }
    1779             : 
    1780           0 :         if (res->count != 1) {
    1781           0 :                 DEBUG(1, ("Search for objectClass=* on dn %s"
    1782             :                           "returned less than 1 objects\n", req1->names[0].str));
    1783           0 :                 return WERR_OK;
    1784             :         }
    1785             : 
    1786           0 :         str = ldb_msg_find_attr_as_string(res->msgs[0], "dNSHostName", NULL);
    1787           0 :         if (str != NULL) {
    1788           0 :                 names[1].result_name = talloc_strdup(names, str);
    1789           0 :                 W_ERROR_HAVE_NO_MEMORY(names[1].result_name);
    1790           0 :                 names[1].status = DRSUAPI_DS_NAME_STATUS_OK;
    1791             :         }
    1792             : 
    1793           0 :         dn = ldb_msg_find_attr_as_dn(sam_ctx, mem_ctx, res->msgs[0], "serverReference");
    1794           0 :         if (dn != NULL) {
    1795           0 :                 names[2].result_name = ldb_dn_alloc_linearized(names, dn);
    1796           0 :                 W_ERROR_HAVE_NO_MEMORY(names[2].result_name);
    1797           0 :                 names[2].status = DRSUAPI_DS_NAME_STATUS_OK;
    1798             :         }
    1799             : 
    1800           0 :         talloc_free(dn);
    1801           0 :         talloc_free(res);
    1802             : 
    1803           0 :         return WERR_OK;
    1804             : }

Generated by: LCOV version 1.14