Exemplo n.º 1
0
/*
  lookup a name for 1 SID
*/
static NTSTATUS dcesrv_lsa_lookup_sid(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
                                      struct dom_sid *sid, const char *sid_str,
                                      const char **authority_name,
                                      const char **name, enum lsa_SidType *rtype)
{
    NTSTATUS status;
    int ret;
    uint32_t atype;
    struct ldb_message **res;
    struct ldb_dn *domain_dn;
    const char * const attrs[] = { "sAMAccountName", "sAMAccountType", "cn", NULL};

    status = lookup_well_known_sids(mem_ctx, sid_str, authority_name, name, rtype);
    if (NT_STATUS_IS_OK(status)) {
        return status;
    }

    if (dom_sid_in_domain(state->domain_sid, sid)) {
        *authority_name = state->domain_name;
        domain_dn = state->domain_dn;
    } else if (dom_sid_in_domain(state->builtin_sid, sid)) {
        *authority_name = NAME_BUILTIN;
        domain_dn = state->builtin_dn;
    } else {
        /* Not well known, our domain or built in */

        /* In future, we must look at SID histories, and at trusted domains via winbind */

        return NT_STATUS_NOT_FOUND;
    }

    ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs,
                       "objectSid=%s", ldap_encode_ndr_dom_sid(mem_ctx, sid));
    if (ret == 1) {
        *name = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
        if (!*name) {
            *name = ldb_msg_find_attr_as_string(res[0], "cn", NULL);
            if (!*name) {
                *name = talloc_strdup(mem_ctx, sid_str);
                NT_STATUS_HAVE_NO_MEMORY(*name);
            }
        }

        atype = samdb_result_uint(res[0], "sAMAccountType", 0);

        *rtype = ds_atype_map(atype);

        return NT_STATUS_OK;
    }

    /* need to re-add a check for an allocated sid */

    return NT_STATUS_NOT_FOUND;
}
Exemplo n.º 2
0
/*
  add privilege bits for one sid to a security_token
*/
static NTSTATUS samdb_privilege_setup_sid(struct ldb_context *pdb, TALLOC_CTX *mem_ctx,
					  struct security_token *token,
					  const struct dom_sid *sid)
{
	const char * const attrs[] = { "privilege", NULL };
	struct ldb_message **res = NULL;
	struct ldb_message_element *el;
	unsigned int i;
	int ret;
	char *sidstr;

	sidstr = ldap_encode_ndr_dom_sid(mem_ctx, sid);
	NT_STATUS_HAVE_NO_MEMORY(sidstr);

	ret = gendb_search(pdb, mem_ctx, NULL, &res, attrs, "objectSid=%s", sidstr);
	talloc_free(sidstr);
	if (ret != 1) {
		/* not an error to not match */
		return NT_STATUS_OK;
	}

	el = ldb_msg_find_element(res[0], "privilege");
	if (el == NULL) {
		return NT_STATUS_OK;
	}

	for (i=0;i<el->num_values;i++) {
		const char *priv_str = (const char *)el->values[i].data;
		enum sec_privilege privilege = sec_privilege_id(priv_str);
		if (privilege == SEC_PRIV_INVALID) {
			uint32_t right_bit = sec_right_bit(priv_str);
			security_token_set_right_bit(token, right_bit);
			if (right_bit == 0) {
				DEBUG(1,("Unknown privilege '%s' in samdb\n",
					 priv_str));
			}
			continue;
		}
		security_token_set_privilege(token, privilege);
	}

	return NT_STATUS_OK;
}
Exemplo n.º 3
0
/*
  find the members of a group, given a group rid and domain
 */
static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
				TALLOC_CTX *mem_ctx,
				const struct dom_sid *group_sid,
				enum lsa_SidType type,
				uint32 *num_names,
				struct dom_sid **sid_mem, char ***names,
				uint32 **name_types)
{
	ADS_STATUS rc;
	ADS_STRUCT *ads = NULL;
	char *ldap_exp;
	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
	char *sidbinstr;
	char **members = NULL;
	int i;
	size_t num_members = 0;
	ads_control args;
	struct dom_sid *sid_mem_nocache = NULL;
	char **names_nocache = NULL;
	enum lsa_SidType *name_types_nocache = NULL;
	char **domains_nocache = NULL;     /* only needed for rpccli_lsa_lookup_sids */
	uint32 num_nocache = 0;
	TALLOC_CTX *tmp_ctx = NULL;

	DEBUG(10,("ads: lookup_groupmem %s sid=%s\n", domain->name,
		  sid_string_dbg(group_sid)));

	*num_names = 0;

	tmp_ctx = talloc_new(mem_ctx);
	if (!tmp_ctx) {
		DEBUG(1, ("ads: lookup_groupmem: talloc failed\n"));
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	if ( !winbindd_can_contact_domain( domain ) ) {
		DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
			  domain->name));
		return NT_STATUS_OK;
	}

	ads = ads_cached_connection(domain);

	if (!ads) {
		domain->last_status = NT_STATUS_SERVER_DISABLED;
		goto done;
	}

	if ((sidbinstr = ldap_encode_ndr_dom_sid(talloc_tos(), group_sid)) == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	/* search for all members of the group */
	ldap_exp = talloc_asprintf(tmp_ctx, "(objectSid=%s)", sidbinstr);
	TALLOC_FREE(sidbinstr);
	if (ldap_exp == NULL) {
		DEBUG(1, ("ads: lookup_groupmem: talloc_asprintf for ldap_exp failed!\n"));
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	args.control = ADS_EXTENDED_DN_OID;
	args.val = ADS_EXTENDED_DN_HEX_STRING;
	args.critical = True;

	rc = ads_ranged_search(ads, tmp_ctx, LDAP_SCOPE_SUBTREE, ads->config.bind_path,
			       ldap_exp, &args, "member", &members, &num_members);

	if (!ADS_ERR_OK(rc)) {
		DEBUG(0,("ads_ranged_search failed with: %s\n", ads_errstr(rc)));
		status = NT_STATUS_UNSUCCESSFUL;
		goto done;
	}

	DEBUG(10, ("ads lookup_groupmem: got %d sids via extended dn call\n", (int)num_members));

	/* Now that we have a list of sids, we need to get the
	 * lists of names and name_types belonging to these sids.
	 * even though conceptually not quite clean,  we use the
	 * RPC call lsa_lookup_sids for this since it can handle a
	 * list of sids. ldap calls can just resolve one sid at a time.
	 *
	 * At this stage, the sids are still hidden in the exetended dn
	 * member output format. We actually do a little better than
	 * stated above: In extracting the sids from the member strings,
	 * we try to resolve as many sids as possible from the
	 * cache. Only the rest is passed to the lsa_lookup_sids call. */

	if (num_members) {
		(*sid_mem) = talloc_zero_array(mem_ctx, struct dom_sid, num_members);
		(*names) = talloc_zero_array(mem_ctx, char *, num_members);
		(*name_types) = talloc_zero_array(mem_ctx, uint32, num_members);
		(sid_mem_nocache) = talloc_zero_array(tmp_ctx, struct dom_sid, num_members);

		if ((members == NULL) || (*sid_mem == NULL) ||
		    (*names == NULL) || (*name_types == NULL) ||
		    (sid_mem_nocache == NULL))
		{
			DEBUG(1, ("ads: lookup_groupmem: talloc failed\n"));
			status = NT_STATUS_NO_MEMORY;
			goto done;
		}
	}
	else {
Exemplo n.º 4
0
/* Lookup user information from a rid */
static NTSTATUS query_user(struct winbindd_domain *domain, 
			   TALLOC_CTX *mem_ctx, 
			   const struct dom_sid *sid,
			   struct wbint_userinfo *info)
{
	ADS_STRUCT *ads = NULL;
	const char *attrs[] = { "*", NULL };
	ADS_STATUS rc;
	int count;
	LDAPMessage *msg = NULL;
	char *ldap_exp;
	char *sidstr;
	uint32 group_rid;
	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
	struct netr_SamInfo3 *user = NULL;
	gid_t gid = -1;
	int ret;
	char *ads_name;

	DEBUG(3,("ads: query_user\n"));

	info->homedir = NULL;
	info->shell = NULL;

	/* try netsamlogon cache first */

	if (winbindd_use_cache() && (user = netsamlogon_cache_get( mem_ctx, sid )) != NULL )
	{
		DEBUG(5,("query_user: Cache lookup succeeded for %s\n", 
			 sid_string_dbg(sid)));

		sid_compose(&info->user_sid, &domain->sid, user->base.rid);
		sid_compose(&info->group_sid, &domain->sid, user->base.primary_gid);

		info->acct_name = talloc_strdup(mem_ctx, user->base.account_name.string);
		info->full_name = talloc_strdup(mem_ctx, user->base.full_name.string);

		nss_get_info_cached( domain, sid, mem_ctx,
			      &info->homedir, &info->shell, &info->full_name, 
			      &gid );
		info->primary_gid = gid;

		TALLOC_FREE(user);

		return NT_STATUS_OK;
	}

	if ( !winbindd_can_contact_domain(domain)) {
		DEBUG(8,("query_user: No incoming trust from domain %s\n",
			 domain->name));

		/* We still need to generate some basic information
		   about the user even if we cannot contact the 
		   domain.  Most of this stuff we can deduce. */

		sid_copy( &info->user_sid, sid );

		/* Assume "Domain Users" for the primary group */

		sid_compose(&info->group_sid, &domain->sid, DOMAIN_RID_USERS );

		/* Try to fill in what the nss_info backend can do */

		nss_get_info_cached( domain, sid, mem_ctx,
			      &info->homedir, &info->shell, &info->full_name, 
			      &gid);
		info->primary_gid = gid;

		return NT_STATUS_OK;
	}

	/* no cache...do the query */

	if ( (ads = ads_cached_connection(domain)) == NULL ) {
		domain->last_status = NT_STATUS_SERVER_DISABLED;
		return NT_STATUS_SERVER_DISABLED;
	}

	sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);

	ret = asprintf(&ldap_exp, "(objectSid=%s)", sidstr);
	TALLOC_FREE(sidstr);
	if (ret == -1) {
		return NT_STATUS_NO_MEMORY;
	}
	rc = ads_search_retry(ads, &msg, ldap_exp, attrs);
	SAFE_FREE(ldap_exp);
	if (!ADS_ERR_OK(rc) || !msg) {
		DEBUG(1,("query_user(sid=%s) ads_search: %s\n",
			 sid_string_dbg(sid), ads_errstr(rc)));
		return ads_ntstatus(rc);
	}

	count = ads_count_replies(ads, msg);
	if (count != 1) {
		DEBUG(1,("query_user(sid=%s): Not found\n",
			 sid_string_dbg(sid)));
		ads_msgfree(ads, msg);
		return NT_STATUS_NO_SUCH_USER;
	}

	info->acct_name = ads_pull_username(ads, mem_ctx, msg);

	if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group_rid)) {
		DEBUG(1,("No primary group for %s !?\n",
			 sid_string_dbg(sid)));
		ads_msgfree(ads, msg);
		return NT_STATUS_NO_SUCH_USER;
	}
	sid_copy(&info->user_sid, sid);
	sid_compose(&info->group_sid, &domain->sid, group_rid);

	/*
	 * We have to fetch the "name" attribute before doing the
	 * nss_get_info_cached call. nss_get_info_cached might destroy
	 * the ads struct, potentially invalidating the ldap message.
	 */
	ads_name = ads_pull_string(ads, mem_ctx, msg, "name");

	ads_msgfree(ads, msg);
	msg = NULL;

	status = nss_get_info_cached( domain, sid, mem_ctx,
		      &info->homedir, &info->shell, &info->full_name, 
		      &gid);
	info->primary_gid = gid;
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("nss_get_info_cached failed: %s\n",
			  nt_errstr(status)));
		return status;
	}

	if (info->full_name == NULL) {
		info->full_name = ads_name;
	} else {
		TALLOC_FREE(ads_name);
	}

	status = NT_STATUS_OK;

	DEBUG(3,("ads query_user gave %s\n", info->acct_name));
	return NT_STATUS_OK;
}
Exemplo n.º 5
0
static int samldb_fill_foreignSecurityPrincipal_object(struct ldb_module *module, const struct ldb_message *msg, 
						       struct ldb_message **ret_msg)
{
	struct ldb_message *msg2;
	const char *rdn_name;
	struct dom_sid *dom_sid;
	struct dom_sid *sid;
	const char *dom_attrs[] = { "name", NULL };
	struct ldb_message **dom_msgs;
	const char *errstr;
	int ret;

	TALLOC_CTX *mem_ctx = talloc_new(msg);
	if (!mem_ctx) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* build the new msg */
	msg2 = ldb_msg_copy(mem_ctx, msg);
	if (!msg2) {
		ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_foreignSecurityPrincpal_object: ldb_msg_copy failed!\n");
		talloc_free(mem_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	ret = samdb_copy_template(module->ldb, msg2, 
				  "(&(CN=TemplateForeignSecurityPrincipal)(objectclass=foreignSecurityPrincipalTemplate))",
				  &errstr);
	if (ret != 0) {
		ldb_asprintf_errstring(module->ldb, 
				       "samldb_fill_foreignSecurityPrincipal_object: "
				       "Error copying template: %s",
				    errstr);
		talloc_free(mem_ctx);
		return ret;
	}

	rdn_name = ldb_dn_get_rdn_name(msg2->dn);

	if (strcasecmp(rdn_name, "cn") != 0) {
		ldb_asprintf_errstring(module->ldb, "Bad RDN (%s=) for ForeignSecurityPrincipal, should be CN=!", rdn_name);
		talloc_free(mem_ctx);
		return LDB_ERR_CONSTRAINT_VIOLATION;
	}

	/* Slightly different for the foreign sids.  We don't want
	 * domain SIDs ending up there, it would cause all sorts of
	 * pain */

	sid = dom_sid_parse_talloc(msg2, (const char *)ldb_dn_get_rdn_val(msg2->dn)->data);
	if (!sid) {
		ldb_set_errstring(module->ldb, "No valid found SID in ForeignSecurityPrincipal CN!");
		talloc_free(mem_ctx);
		return LDB_ERR_CONSTRAINT_VIOLATION;
	}

	if ( ! samldb_msg_add_sid(module, msg2, "objectSid", sid)) {
		talloc_free(sid);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	dom_sid = dom_sid_dup(mem_ctx, sid);
	if (!dom_sid) {
		talloc_free(mem_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	}
	/* get the domain component part of the provided SID */
	dom_sid->num_auths--;

	/* find the domain DN */

	ret = gendb_search(module->ldb,
			   mem_ctx, NULL, &dom_msgs, dom_attrs,
			   "(&(objectSid=%s)(objectclass=domain))",
			   ldap_encode_ndr_dom_sid(mem_ctx, dom_sid));
	if (ret >= 1) {
		/* We don't really like the idea of foreign sids that are not foreign, but it happens */
		const char *name = samdb_result_string(dom_msgs[0], "name", NULL);
		ldb_debug(module->ldb, LDB_DEBUG_TRACE, "NOTE (strange but valid): Adding foreign SID record with SID %s, but this domian (%s) is already in the database", 
			  dom_sid_string(mem_ctx, sid), name); 
	} else if (ret == -1) {
		ldb_asprintf_errstring(module->ldb,
					"samldb_fill_foreignSecurityPrincipal_object: error searching for a domain with this sid: %s\n", 
					dom_sid_string(mem_ctx, dom_sid));
		talloc_free(dom_msgs);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* This isn't an operation on a domain we know about, so just
	 * check for the SID, looking for duplicates via the common
	 * code */
	ret = samldb_notice_sid(module, msg2, sid);
	if (ret == 0) {
		talloc_steal(msg, msg2);
		*ret_msg = msg2;
	}
	
	return ret;
}
Exemplo n.º 6
0
int samldb_notice_sid(struct ldb_module *module, 
		      TALLOC_CTX *mem_ctx, const struct dom_sid *sid)
{
	int ret;
	struct ldb_dn *dom_dn;
	struct dom_sid *dom_sid;
	const char *attrs[] = { NULL };
	struct ldb_result *dom_res;
	struct ldb_result *res;
	uint32_t old_rid;

	/* find if this SID already exists */
	ret = ldb_search_exp_fmt(module->ldb, mem_ctx, &res,
				 NULL, LDB_SCOPE_SUBTREE, attrs,
				 "(objectSid=%s)", ldap_encode_ndr_dom_sid(mem_ctx, sid));
	if (ret == LDB_SUCCESS) {
		if (res->count > 0) {
			talloc_free(res);
			ldb_asprintf_errstring(module->ldb,
						"Attempt to add record with SID %s rejected,"
						" because this SID is already in the database",
						dom_sid_string(mem_ctx, sid));
			/* We have a duplicate SID, we must reject the add */
			return LDB_ERR_CONSTRAINT_VIOLATION;
		}
		talloc_free(res);
	} else {
		ldb_asprintf_errstring(module->ldb,
					"samldb_notice_sid: error searching to see if sid %s is in use: %s\n", 
					dom_sid_string(mem_ctx, sid), 
					ldb_errstring(module->ldb));
		return ret;
	}

	dom_sid = dom_sid_dup(mem_ctx, sid);
	if (!dom_sid) {
		return LDB_ERR_OPERATIONS_ERROR;
	}
	/* get the domain component part of the provided SID */
	dom_sid->num_auths--;

	/* find the domain DN */
	ret = ldb_search_exp_fmt(module->ldb, mem_ctx, &dom_res,
				 NULL, LDB_SCOPE_SUBTREE, attrs,
				 "(&(objectSid=%s)(objectclass=domain))",
				 ldap_encode_ndr_dom_sid(mem_ctx, dom_sid));
	if (ret == LDB_SUCCESS) {
		if (dom_res->count == 0) {
			talloc_free(dom_res);
			/* This isn't an operation on a domain we know about, so nothing to update */
			return LDB_SUCCESS;
		}

		if (dom_res->count > 1) {
			talloc_free(dom_res);
			ldb_asprintf_errstring(module->ldb,
					"samldb_notice_sid: error retrieving domain from sid: duplicate (found %d) domain: %s!\n", 
					dom_res->count, dom_sid_string(dom_res, dom_sid));
			return LDB_ERR_OPERATIONS_ERROR;
		}
	} else {
		ldb_asprintf_errstring(module->ldb,
					"samldb_notice_sid: error retrieving domain from sid: %s: %s\n", 
					dom_sid_string(dom_res, dom_sid), 
					ldb_errstring(module->ldb));
		return ret;
	}

	dom_dn = dom_res->msgs[0]->dn;

	ret = samldb_find_next_rid(module, mem_ctx, 
				   dom_dn, &old_rid);
	if (ret) {
		talloc_free(dom_res);
		return ret;
	}

	if (old_rid <= sid->sub_auths[sid->num_auths - 1]) {
		ret = samldb_set_next_rid(module->ldb, mem_ctx, dom_dn, old_rid, 
					  sid->sub_auths[sid->num_auths - 1] + 1);
	}
	talloc_free(dom_res);
	return ret;
}
Exemplo n.º 7
0
WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
                          uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
                          const char *name, struct drsuapi_DsNameInfo1 *info1)
{
    krb5_error_code ret;
    const char *domain_filter = NULL;
    const char *result_filter = NULL;
    struct ldb_dn *name_dn = NULL;

    struct smb_krb5_context *smb_krb5_context = NULL;

    info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
    info1->dns_domain_name = NULL;
    info1->result_name = NULL;

    if (!name) {
        return WERR_INVALID_PARAM;
    }

    /* TODO: - fill the correct names in all cases!
     *       - handle format_flags
     */

    /* here we need to set the domain_filter and/or the result_filter */
    switch (format_offered) {
    case DRSUAPI_DS_NAME_FORMAT_UNKNOWN:
    {
        int i;
        enum drsuapi_DsNameFormat formats[] = {
            DRSUAPI_DS_NAME_FORMAT_FQDN_1779, DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
            DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT, DRSUAPI_DS_NAME_FORMAT_CANONICAL,
            DRSUAPI_DS_NAME_FORMAT_GUID, DRSUAPI_DS_NAME_FORMAT_DISPLAY,
            DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
            DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
            DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX
        };
        WERROR werr;
        for (i=0; i < ARRAY_SIZE(formats); i++) {
            werr = DsCrackNameOneName(sam_ctx, mem_ctx, format_flags, formats[i], format_desired, name, info1);
            if (!W_ERROR_IS_OK(werr)) {
                return werr;
            }
            if (info1->status != DRSUAPI_DS_NAME_STATUS_NOT_FOUND) {
                return werr;
            }
        }
        return werr;
    }

    case DRSUAPI_DS_NAME_FORMAT_CANONICAL:
    case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX:
    {
        char *str, *s, *account;

        if (strlen(name) == 0) {
            info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
            return WERR_OK;
        }

        str = talloc_strdup(mem_ctx, name);
        W_ERROR_HAVE_NO_MEMORY(str);

        if (format_offered == DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX) {
            /* Look backwards for the \n, and replace it with / */
            s = strrchr(str, '\n');
            if (!s) {
                info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
                return WERR_OK;
            }
            s[0] = '/';
        }

        s = strchr(str, '/');
        if (!s) {
            /* there must be at least one / */
            info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
            return WERR_OK;
        }

        s[0] = '\0';
        s++;

        domain_filter = talloc_asprintf(mem_ctx, "(&(objectClass=crossRef)(ncName=%s))",
                                        ldb_dn_get_linearized(samdb_dns_domain_to_dn(sam_ctx, mem_ctx, str)));
        W_ERROR_HAVE_NO_MEMORY(domain_filter);

        /* There may not be anything after the domain component (search for the domain itself) */
        if (s[0]) {

            account = strrchr(s, '/');
            if (!account) {
                account = s;
            } else {
                account++;
            }
            account = ldb_binary_encode_string(mem_ctx, account);
            W_ERROR_HAVE_NO_MEMORY(account);
            result_filter = talloc_asprintf(mem_ctx, "(name=%s)",
                                            account);
            W_ERROR_HAVE_NO_MEMORY(result_filter);
        }
        break;
    }
    case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT: {
        char *p;
        char *domain;
        const char *account = NULL;

        domain = talloc_strdup(mem_ctx, name);
        W_ERROR_HAVE_NO_MEMORY(domain);

        p = strchr(domain, '\\');
        if (!p) {
            /* invalid input format */
            info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
            return WERR_OK;
        }
        p[0] = '\0';

        if (p[1]) {
            account = &p[1];
        }

        domain_filter = talloc_asprintf(mem_ctx,
                                        "(&(&(nETBIOSName=%s)(objectclass=crossRef))(ncName=*))",
                                        ldb_binary_encode_string(mem_ctx, domain));
        W_ERROR_HAVE_NO_MEMORY(domain_filter);
        if (account) {
            result_filter = talloc_asprintf(mem_ctx, "(sAMAccountName=%s)",
                                            ldb_binary_encode_string(mem_ctx, account));
            W_ERROR_HAVE_NO_MEMORY(result_filter);
        }

        talloc_free(domain);
        break;
    }

    /* A LDAP DN as a string */
    case DRSUAPI_DS_NAME_FORMAT_FQDN_1779: {
        domain_filter = NULL;
        name_dn = ldb_dn_new(mem_ctx, sam_ctx, name);
        if (! ldb_dn_validate(name_dn)) {
            info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
            return WERR_OK;
        }
        break;
    }

    /* A GUID as a string */
    case DRSUAPI_DS_NAME_FORMAT_GUID: {
        struct GUID guid;
        char *ldap_guid;
        NTSTATUS nt_status;
        domain_filter = NULL;

        nt_status = GUID_from_string(name, &guid);
        if (!NT_STATUS_IS_OK(nt_status)) {
            info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
            return WERR_OK;
        }

        ldap_guid = ldap_encode_ndr_GUID(mem_ctx, &guid);
        if (!ldap_guid) {
            return WERR_NOMEM;
        }
        result_filter = talloc_asprintf(mem_ctx, "(objectGUID=%s)",
                                        ldap_guid);
        W_ERROR_HAVE_NO_MEMORY(result_filter);
        break;
    }
    case DRSUAPI_DS_NAME_FORMAT_DISPLAY: {
        domain_filter = NULL;

        result_filter = talloc_asprintf(mem_ctx, "(|(displayName=%s)(samAccountName=%s))",
                                        ldb_binary_encode_string(mem_ctx, name),
                                        ldb_binary_encode_string(mem_ctx, name));
        W_ERROR_HAVE_NO_MEMORY(result_filter);
        break;
    }

    /* A S-1234-5678 style string */
    case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY: {
        struct dom_sid *sid = dom_sid_parse_talloc(mem_ctx, name);
        char *ldap_sid;

        domain_filter = NULL;
        if (!sid) {
            info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
            return WERR_OK;
        }
        ldap_sid = ldap_encode_ndr_dom_sid(mem_ctx,
                                           sid);
        if (!ldap_sid) {
            return WERR_NOMEM;
        }
        result_filter = talloc_asprintf(mem_ctx, "(objectSid=%s)",
                                        ldap_sid);
        W_ERROR_HAVE_NO_MEMORY(result_filter);
        break;
    }
    case DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL: {
        krb5_principal principal;
        char *unparsed_name;

        ret = smb_krb5_init_context(mem_ctx,
                                    ldb_get_event_context(sam_ctx),
                                    (struct loadparm_context *)ldb_get_opaque(sam_ctx, "loadparm"),
                                    &smb_krb5_context);

        if (ret) {
            return WERR_NOMEM;
        }

        /* Ensure we reject compleate junk first */
        ret = krb5_parse_name(smb_krb5_context->krb5_context, name, &principal);
        if (ret) {
            info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
            return WERR_OK;
        }

        domain_filter = NULL;

        /* By getting the unparsed name here, we ensure the escaping is correct (and trust the client less) */
        ret = krb5_unparse_name(smb_krb5_context->krb5_context, principal, &unparsed_name);
        if (ret) {
            krb5_free_principal(smb_krb5_context->krb5_context, principal);
            return WERR_NOMEM;
        }

        krb5_free_principal(smb_krb5_context->krb5_context, principal);

        /* The ldb_binary_encode_string() here avoid LDAP filter injection attacks */
        result_filter = talloc_asprintf(mem_ctx, "(&(objectClass=user)(userPrincipalName=%s))",
                                        ldb_binary_encode_string(mem_ctx, unparsed_name));

        free(unparsed_name);
        W_ERROR_HAVE_NO_MEMORY(result_filter);
        break;
    }
    case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL: {
        krb5_principal principal;
        char *unparsed_name_short;
        char *service;

        ret = smb_krb5_init_context(mem_ctx,
                                    ldb_get_event_context(sam_ctx),
                                    (struct loadparm_context *)ldb_get_opaque(sam_ctx, "loadparm"),
                                    &smb_krb5_context);

        if (ret) {
            return WERR_NOMEM;
        }

        ret = krb5_parse_name(smb_krb5_context->krb5_context, name, &principal);
        if (ret == 0 && principal->name.name_string.len < 2) {
            info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
            krb5_free_principal(smb_krb5_context->krb5_context, principal);
            return WERR_OK;
        }
        ret = krb5_parse_name_flags(smb_krb5_context->krb5_context, name,
                                    KRB5_PRINCIPAL_PARSE_NO_REALM, &principal);
        if (ret) {
            krb5_free_principal(smb_krb5_context->krb5_context, principal);

            return dns_domain_from_principal(mem_ctx, smb_krb5_context,
                                             name, info1);
        }

        domain_filter = NULL;

        ret = krb5_unparse_name_flags(smb_krb5_context->krb5_context, principal,
                                      KRB5_PRINCIPAL_UNPARSE_NO_REALM, &unparsed_name_short);
        if (ret) {
            krb5_free_principal(smb_krb5_context->krb5_context, principal);
            return WERR_NOMEM;
        }

        service = principal->name.name_string.val[0];
        if ((principal->name.name_string.len == 2) && (strcasecmp(service, "host") == 0)) {
            /* the 'cn' attribute is just the leading part of the name */
            char *computer_name;
            computer_name = talloc_strndup(mem_ctx, principal->name.name_string.val[1],
                                           strcspn(principal->name.name_string.val[1], "."));
            if (computer_name == NULL) {
                return WERR_NOMEM;
            }

            result_filter = talloc_asprintf(mem_ctx, "(|(&(servicePrincipalName=%s)(objectClass=user))(&(cn=%s)(objectClass=computer)))",
                                            ldb_binary_encode_string(mem_ctx, unparsed_name_short),
                                            ldb_binary_encode_string(mem_ctx, computer_name));
        } else {
            result_filter = talloc_asprintf(mem_ctx, "(&(servicePrincipalName=%s)(objectClass=user))",
                                            ldb_binary_encode_string(mem_ctx, unparsed_name_short));
        }
        krb5_free_principal(smb_krb5_context->krb5_context, principal);
        free(unparsed_name_short);
        W_ERROR_HAVE_NO_MEMORY(result_filter);

        break;
    }
    default: {
        info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
        return WERR_OK;
    }

    }

    if (format_flags & DRSUAPI_DS_NAME_FLAG_SYNTACTICAL_ONLY) {
        return DsCrackNameOneSyntactical(mem_ctx, format_offered, format_desired,
                                         name_dn, name, info1);
    }

    return DsCrackNameOneFilter(sam_ctx, mem_ctx,
                                smb_krb5_context,
                                format_flags, format_offered, format_desired,
                                name_dn, name,
                                domain_filter, result_filter,
                                info1);
}
static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
				   struct smb_krb5_context *smb_krb5_context,
				   uint32_t format_flags, enum drsuapi_DsNameFormat format_offered,
				   enum drsuapi_DsNameFormat format_desired,
				   struct ldb_dn *name_dn, const char *name, 
				   const char *domain_filter, const char *result_filter, 
				   struct drsuapi_DsNameInfo1 *info1,
				   int scope, struct ldb_dn *search_dn)
{
	int ldb_ret;
	struct ldb_result *domain_res = NULL;
	const char * const *domain_attrs;
	const char * const *result_attrs;
	struct ldb_message **result_res = NULL;
	struct ldb_message *result = NULL;
	int i;
	char *p;
	struct ldb_dn *partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx);

	const char * const _domain_attrs_1779[] = { "ncName", "dnsRoot", NULL};
	const char * const _result_attrs_null[] = { NULL };

	const char * const _domain_attrs_canonical[] = { "ncName", "dnsRoot", NULL};
	const char * const _result_attrs_canonical[] = { "canonicalName", NULL };

	const char * const _domain_attrs_nt4[] = { "ncName", "dnsRoot", "nETBIOSName", NULL};
	const char * const _result_attrs_nt4[] = { "sAMAccountName", "objectSid", "objectClass", NULL};

	const char * const _domain_attrs_guid[] = { "ncName", "dnsRoot", NULL};
	const char * const _result_attrs_guid[] = { "objectGUID", NULL};

	const char * const _domain_attrs_display[] = { "ncName", "dnsRoot", NULL};
	const char * const _result_attrs_display[] = { "displayName", "samAccountName", NULL};

	const char * const _domain_attrs_none[] = { "ncName", "dnsRoot" , NULL};
	const char * const _result_attrs_none[] = { NULL};

	/* here we need to set the attrs lists for domain and result lookups */
	switch (format_desired) {
	case DRSUAPI_DS_NAME_FORMAT_FQDN_1779:
	case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX:
		domain_attrs = _domain_attrs_1779;
		result_attrs = _result_attrs_null;
		break;
	case DRSUAPI_DS_NAME_FORMAT_CANONICAL:
		domain_attrs = _domain_attrs_canonical;
		result_attrs = _result_attrs_canonical;
		break;
	case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT:
		domain_attrs = _domain_attrs_nt4;
		result_attrs = _result_attrs_nt4;
		break;
	case DRSUAPI_DS_NAME_FORMAT_GUID:		
		domain_attrs = _domain_attrs_guid;
		result_attrs = _result_attrs_guid;
		break;
	case DRSUAPI_DS_NAME_FORMAT_DISPLAY:		
		domain_attrs = _domain_attrs_display;
		result_attrs = _result_attrs_display;
		break;
	default:
		domain_attrs = _domain_attrs_none;
		result_attrs = _result_attrs_none;
		break;
	}

	if (domain_filter) {
		/* if we have a domain_filter look it up and set the result_basedn and the dns_domain_name */
		ldb_ret = ldb_search(sam_ctx, mem_ctx, &domain_res,
					     partitions_basedn,
					     LDB_SCOPE_ONELEVEL,
					     domain_attrs,
					     "%s", domain_filter);

		if (ldb_ret != LDB_SUCCESS) {
			DEBUG(2, ("DsCrackNameOneFilter domain ref search failed: %s\n", ldb_errstring(sam_ctx)));
			info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
			return WERR_OK;
		}

		switch (domain_res->count) {
		case 1:
			break;
		case 0:
			info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
			return WERR_OK;
		default:
			info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
			return WERR_OK;
		}

		info1->dns_domain_name	= ldb_msg_find_attr_as_string(domain_res->msgs[0], "dnsRoot", NULL);
		W_ERROR_HAVE_NO_MEMORY(info1->dns_domain_name);
		info1->status		= DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY;
	} else {
		info1->dns_domain_name	= NULL;
		info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
	}

	if (result_filter) {
		int ret;
		struct ldb_result *res;
		uint32_t dsdb_flags = 0;
		struct ldb_dn *real_search_dn = NULL;
		info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;

		/*
		 * From 4.1.4.2.11 of MS-DRSR
		 * if DS_NAME_FLAG_GCVERIFY in flags then
		 * rt := select all O from all
		 * where attrValue in GetAttrVals(O, att, false)
		 * else
		 * rt := select all O from subtree DefaultNC()
		 * where attrValue in GetAttrVals(O, att, false)
		 * endif
		 * return rt
		 */
		if (format_flags & DRSUAPI_DS_NAME_FLAG_GCVERIFY ||
		    format_offered == DRSUAPI_DS_NAME_FORMAT_GUID)
		{
			dsdb_flags = DSDB_SEARCH_SEARCH_ALL_PARTITIONS;
		} else if (domain_res) {
			if (!search_dn) {
				struct ldb_dn *tmp_dn = samdb_result_dn(sam_ctx, mem_ctx, domain_res->msgs[0], "ncName", NULL);
				real_search_dn = tmp_dn;
			} else {
				real_search_dn = search_dn;
			}
		} else {
			real_search_dn = ldb_get_default_basedn(sam_ctx);
		}
		if (format_desired == DRSUAPI_DS_NAME_FORMAT_GUID){
			 dsdb_flags |= DSDB_SEARCH_SHOW_RECYCLED;
		}
		/* search with the 'phantom root' flag */
		ret = dsdb_search(sam_ctx, mem_ctx, &res,
				  real_search_dn,
				  scope,
				  result_attrs,
				  dsdb_flags,
				  "%s", result_filter);
		if (ret != LDB_SUCCESS) {
			DEBUG(2, ("DsCrackNameOneFilter search from '%s' with flags 0x%08x failed: %s\n",
				  ldb_dn_get_linearized(real_search_dn),
				  dsdb_flags,
				  ldb_errstring(sam_ctx)));
			info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
			return WERR_OK;
		}

		ldb_ret = res->count;
		result_res = res->msgs;
	} else if (format_offered == DRSUAPI_DS_NAME_FORMAT_FQDN_1779) {
		ldb_ret = gendb_search_dn(sam_ctx, mem_ctx, name_dn, &result_res,
					  result_attrs);
	} else if (domain_res) {
		name_dn = samdb_result_dn(sam_ctx, mem_ctx, domain_res->msgs[0], "ncName", NULL);
		ldb_ret = gendb_search_dn(sam_ctx, mem_ctx, name_dn, &result_res,
					  result_attrs);
	} else {
		/* Can't happen */
		DEBUG(0, ("LOGIC ERROR: DsCrackNameOneFilter domain ref search not available: This can't happen...\n"));
		info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
		return WERR_OK;
	}

	switch (ldb_ret) {
	case 1:
		result = result_res[0];
		break;
	case 0:
		switch (format_offered) {
		case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL: 
			return DsCrackNameSPNAlias(sam_ctx, mem_ctx, 
						   smb_krb5_context, 
						   format_flags, format_offered, format_desired,
						   name, info1);

		case DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL:
			return DsCrackNameUPN(sam_ctx, mem_ctx, smb_krb5_context, 
					      format_flags, format_offered, format_desired,
					      name, info1);
		default:
			break;
		}
		info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
		return WERR_OK;
	case -1:
		DEBUG(2, ("DsCrackNameOneFilter result search failed: %s\n", ldb_errstring(sam_ctx)));
		info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
		return WERR_OK;
	default:
		switch (format_offered) {
		case DRSUAPI_DS_NAME_FORMAT_CANONICAL:
		case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX:
		{
			const char *canonical_name = NULL; /* Not required, but we get warnings... */
			/* We may need to manually filter further */
			for (i = 0; i < ldb_ret; i++) {
				switch (format_offered) {
				case DRSUAPI_DS_NAME_FORMAT_CANONICAL:
					canonical_name = ldb_dn_canonical_string(mem_ctx, result_res[i]->dn);
					break;
				case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX:
					canonical_name = ldb_dn_canonical_ex_string(mem_ctx, result_res[i]->dn);
					break;
				default:
					break;
				}
				if (strcasecmp_m(canonical_name, name) == 0) {
					result = result_res[i];
					break;
				}
			}
			if (!result) {
				info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
				return WERR_OK;
			}
		}
		/* FALL TROUGH */
		default:
			info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
			return WERR_OK;
		}
	}

	info1->dns_domain_name = ldb_dn_canonical_string(mem_ctx, result->dn);
	W_ERROR_HAVE_NO_MEMORY(info1->dns_domain_name);
	p = strchr(info1->dns_domain_name, '/');
	if (p) {
		p[0] = '\0';
	}

	/* here we can use result and domain_res[0] */
	switch (format_desired) {
	case DRSUAPI_DS_NAME_FORMAT_FQDN_1779: {
		info1->result_name	= ldb_dn_alloc_linearized(mem_ctx, result->dn);
		W_ERROR_HAVE_NO_MEMORY(info1->result_name);

		info1->status		= DRSUAPI_DS_NAME_STATUS_OK;
		return WERR_OK;
	}
	case DRSUAPI_DS_NAME_FORMAT_CANONICAL: {
		info1->result_name	= ldb_msg_find_attr_as_string(result, "canonicalName", NULL);
		info1->status		= DRSUAPI_DS_NAME_STATUS_OK;
		return WERR_OK;
	}
	case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX: {
		/* Not in the virtual ldb attribute */
		return DsCrackNameOneSyntactical(mem_ctx, 
						 DRSUAPI_DS_NAME_FORMAT_FQDN_1779, 
						 DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX,
						 result->dn, name, info1);
	}
	case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT: {

		const struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, result, "objectSid");
		const char *_acc = "", *_dom = "";
		if (sid == NULL) {
			info1->status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING;
			return WERR_OK;
		}

		if (samdb_find_attribute(sam_ctx, result, "objectClass",
					 "domain")) {
			/* This can also find a DomainDNSZones entry,
			 * but it won't have the SID we just
			 * checked.  */
			ldb_ret = ldb_search(sam_ctx, mem_ctx, &domain_res,
						     partitions_basedn,
						     LDB_SCOPE_ONELEVEL,
						     domain_attrs,
						     "(ncName=%s)", ldb_dn_get_linearized(result->dn));

			if (ldb_ret != LDB_SUCCESS) {
				DEBUG(2, ("DsCrackNameOneFilter domain ref search failed: %s\n", ldb_errstring(sam_ctx)));
				info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
				return WERR_OK;
			}

			switch (domain_res->count) {
			case 1:
				break;
			case 0:
				info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
				return WERR_OK;
			default:
				info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
				return WERR_OK;
			}
			_dom = ldb_msg_find_attr_as_string(domain_res->msgs[0], "nETBIOSName", NULL);
			W_ERROR_HAVE_NO_MEMORY(_dom);
		} else {
			_acc = ldb_msg_find_attr_as_string(result, "sAMAccountName", NULL);
			if (!_acc) {
				info1->status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING;
				return WERR_OK;
			}
			if (dom_sid_in_domain(dom_sid_parse_talloc(mem_ctx, SID_BUILTIN), sid)) {
				_dom = "BUILTIN";
			} else {
				const char *attrs[] = { NULL };
				struct ldb_result *domain_res2;
				struct dom_sid *dom_sid = dom_sid_dup(mem_ctx, sid);
				if (!dom_sid) {
					return WERR_OK;
				}
				dom_sid->num_auths--;
				ldb_ret = ldb_search(sam_ctx, mem_ctx, &domain_res,
							     NULL,
							     LDB_SCOPE_BASE,
							     attrs,
							     "(&(objectSid=%s)(objectClass=domain))", 
							     ldap_encode_ndr_dom_sid(mem_ctx, dom_sid));

				if (ldb_ret != LDB_SUCCESS) {
					DEBUG(2, ("DsCrackNameOneFilter domain search failed: %s\n", ldb_errstring(sam_ctx)));
					info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
					return WERR_OK;
				}

				switch (domain_res->count) {
				case 1:
					break;
				case 0:
					info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
					return WERR_OK;
				default:
					info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
					return WERR_OK;
				}

				ldb_ret = ldb_search(sam_ctx, mem_ctx, &domain_res2,
							     partitions_basedn,
							     LDB_SCOPE_ONELEVEL,
							     domain_attrs,
							     "(ncName=%s)", ldb_dn_get_linearized(domain_res->msgs[0]->dn));

				if (ldb_ret != LDB_SUCCESS) {
					DEBUG(2, ("DsCrackNameOneFilter domain ref search failed: %s\n", ldb_errstring(sam_ctx)));
					info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
					return WERR_OK;
				}

				switch (domain_res2->count) {
				case 1:
					break;
				case 0:
					info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
					return WERR_OK;
				default:
					info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
					return WERR_OK;
				}
				_dom = ldb_msg_find_attr_as_string(domain_res2->msgs[0], "nETBIOSName", NULL);
				W_ERROR_HAVE_NO_MEMORY(_dom);
			}
		}

		info1->result_name	= talloc_asprintf(mem_ctx, "%s\\%s", _dom, _acc);
		W_ERROR_HAVE_NO_MEMORY(info1->result_name);

		info1->status		= DRSUAPI_DS_NAME_STATUS_OK;
		return WERR_OK;
	}
	case DRSUAPI_DS_NAME_FORMAT_GUID: {
		struct GUID guid;

		guid = samdb_result_guid(result, "objectGUID");

		info1->result_name	= GUID_string2(mem_ctx, &guid);
		W_ERROR_HAVE_NO_MEMORY(info1->result_name);

		info1->status		= DRSUAPI_DS_NAME_STATUS_OK;
		return WERR_OK;
	}
	case DRSUAPI_DS_NAME_FORMAT_DISPLAY: {
		info1->result_name	= ldb_msg_find_attr_as_string(result, "displayName", NULL);
		if (!info1->result_name) {
			info1->result_name	= ldb_msg_find_attr_as_string(result, "sAMAccountName", NULL);
		} 
		if (!info1->result_name) {
			info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
		} else {
			info1->status = DRSUAPI_DS_NAME_STATUS_OK;
		}
		return WERR_OK;
	}
	case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL: {
		info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
		return WERR_OK;
	}
	case DRSUAPI_DS_NAME_FORMAT_DNS_DOMAIN:	
	case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY: {
		info1->dns_domain_name = NULL;
		info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
		return WERR_OK;
	}
	default:
		info1->status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING;
		return WERR_OK;
	}
}