Esempio 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;
}
Esempio n. 2
0
/*
  encode a sid in SDDL format
*/
static char *sddl_encode_sid(TALLOC_CTX *mem_ctx, const struct dom_sid *sid,
			     const struct dom_sid *domain_sid)
{
	int i;
	char *sidstr;

	sidstr = dom_sid_string(mem_ctx, sid);
	if (sidstr == NULL) return NULL;

	/* seen if its a well known sid */ 
	for (i=0;sid_codes[i].sid;i++) {
		if (strcmp(sidstr, sid_codes[i].sid) == 0) {
			talloc_free(sidstr);
			return talloc_strdup(mem_ctx, sid_codes[i].code);
		}
	}

	/* or a well known rid in our domain */
	if (dom_sid_in_domain(domain_sid, sid)) {
		uint32_t rid = sid->sub_auths[sid->num_auths-1];
		for (;i<ARRAY_SIZE(sid_codes);i++) {
			if (rid == sid_codes[i].rid) {
				talloc_free(sidstr);
				return talloc_strdup(mem_ctx, sid_codes[i].code);
			}
		}
	}
	
	talloc_free(sidstr);

	/* TODO: encode well known sids as two letter codes */
	return dom_sid_string(mem_ctx, sid);
}
Esempio n. 3
0
static struct wbsrv_domain *find_domain_from_sid(struct wbsrv_service *service,
						 const struct dom_sid *sid)
{
	struct wbsrv_domain *domain;

	for (domain = service->domains; domain!=NULL; domain = domain->next) {
		if (dom_sid_equal(domain->info->sid, sid)) {
			break;
		}
		if (dom_sid_in_domain(domain->info->sid, sid)) {
			break;
		}
	}
	return domain;
}
Esempio n. 4
0
static NTSTATUS wbcsids_to_netr_SidAttrArray(
				const struct dom_sid *domain_sid,
				const struct wbcSidWithAttr *sids,
				size_t num_sids,
				TALLOC_CTX *mem_ctx,
				struct netr_SidAttr **_info3_sids,
				uint32_t *info3_num_sids)
{
	unsigned int i, j = 0;
	struct netr_SidAttr *info3_sids;

	info3_sids = talloc_array(mem_ctx, struct netr_SidAttr, num_sids);
	if (info3_sids == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	/* a wbcDomainSid is the same as a dom_sid */
	for (i = 0; i < num_sids; i++) {
		const struct dom_sid *sid;

		sid = (const struct dom_sid *)&sids[i].sid;

		if (dom_sid_in_domain(domain_sid, sid)) {
			continue;
		}

		info3_sids[j].sid = dom_sid_dup(info3_sids, sid);
		if (info3_sids[j].sid == NULL) {
			talloc_free(info3_sids);
			return NT_STATUS_NO_MEMORY;
		}
		info3_sids[j].attributes = SE_GROUP_MANDATORY |
					   SE_GROUP_ENABLED_BY_DEFAULT |
					   SE_GROUP_ENABLED;
		j++;
	}

	*info3_num_sids = j;
	*_info3_sids = info3_sids;
	return NT_STATUS_OK;
}
Esempio n. 5
0
static NTSTATUS auth_convert_user_info_dc_sambaseinfo(TALLOC_CTX *mem_ctx,
				const struct auth_user_info_dc *user_info_dc,
				struct netr_SamBaseInfo *sam)
{
	NTSTATUS status;
	const struct auth_user_info *info;

	ZERO_STRUCTP(sam);

	if (user_info_dc->num_sids > PRIMARY_USER_SID_INDEX) {
		status = dom_sid_split_rid(sam, &user_info_dc->sids[PRIMARY_USER_SID_INDEX],
					   &sam->domain_sid, &sam->rid);
		if (!NT_STATUS_IS_OK(status)) {
			return status;
		}
	} else {
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (user_info_dc->num_sids > PRIMARY_GROUP_SID_INDEX) {
		status = dom_sid_split_rid(NULL, &user_info_dc->sids[PRIMARY_GROUP_SID_INDEX],
					   NULL, &sam->primary_gid);
		if (!NT_STATUS_IS_OK(status)) {
			return status;
		}
	} else {
		/* if we have to encode something like SYSTEM (with no
		 * second SID in the token) then this is the only
		 * choice */
		sam->primary_gid = sam->rid;
	}

	info = user_info_dc->info;

	sam->logon_time = info->last_logon;
	sam->logoff_time =  info->last_logoff;
	sam->kickoff_time = info->acct_expiry;
	sam->last_password_change = info->last_password_change;
	sam->allow_password_change = info->allow_password_change;
	sam->force_password_change = info->force_password_change;

#define _COPY_STRING_TALLOC(src_name, dst_name) do { \
	if (info->src_name != NULL) {\
		sam->dst_name.string = talloc_strdup(mem_ctx, info->src_name); \
		if (sam->dst_name.string == NULL) { \
			return NT_STATUS_NO_MEMORY; \
		} \
	} \
} while(0)
	_COPY_STRING_TALLOC(account_name, account_name);
	_COPY_STRING_TALLOC(full_name, full_name);
	_COPY_STRING_TALLOC(logon_script, logon_script);
	_COPY_STRING_TALLOC(profile_path, profile_path);
	_COPY_STRING_TALLOC(home_directory, home_directory);
	_COPY_STRING_TALLOC(home_drive, home_drive);
	_COPY_STRING_TALLOC(logon_server, logon_server);
	_COPY_STRING_TALLOC(domain_name, logon_domain);
#undef _COPY_STRING_TALLOC

	sam->logon_count = info->logon_count;
	sam->bad_password_count = info->bad_password_count;
	sam->groups.count = 0;
	sam->groups.rids = NULL;

	if (user_info_dc->num_sids > 2) {
		size_t i;
		sam->groups.rids = talloc_array(mem_ctx, struct samr_RidWithAttribute,
						user_info_dc->num_sids);

		if (sam->groups.rids == NULL)
			return NT_STATUS_NO_MEMORY;

		for (i=2; i<user_info_dc->num_sids; i++) {
			struct dom_sid *group_sid = &user_info_dc->sids[i];
			if (!dom_sid_in_domain(sam->domain_sid, group_sid)) {
				/* We handle this elsewhere */
				continue;
			}
			sam->groups.rids[sam->groups.count].rid =
				group_sid->sub_auths[group_sid->num_auths-1];

			sam->groups.rids[sam->groups.count].attributes =
				SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED;
			sam->groups.count += 1;
		}
	}
Esempio n. 6
0
/*
  lookup a SID for 1 name
*/
static NTSTATUS dcesrv_lsa_lookup_name(struct tevent_context *ev_ctx,
                                       struct loadparm_context *lp_ctx,
                                       struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
                                       const char *name, const char **authority_name,
                                       struct dom_sid **sid, enum lsa_SidType *rtype,
                                       uint32_t *rid)
{
    int ret, i;
    uint32_t atype;
    struct ldb_message **res;
    const char * const attrs[] = { "objectSid", "sAMAccountType", NULL};
    const char *p;
    const char *domain;
    const char *username;
    struct ldb_dn *domain_dn;
    struct dom_sid *domain_sid;
    NTSTATUS status;

    p = strchr_m(name, '\\');
    if (p != NULL) {
        domain = talloc_strndup(mem_ctx, name, p-name);
        if (!domain) {
            return NT_STATUS_NO_MEMORY;
        }
        username = p + 1;
    } else if (strchr_m(name, '@')) {
        status = crack_name_to_nt4_name(mem_ctx, ev_ctx, lp_ctx, DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL, name, &domain, &username);
        if (!NT_STATUS_IS_OK(status)) {
            DEBUG(3, ("Failed to crack name %s into an NT4 name: %s\n", name, nt_errstr(status)));
            return status;
        }
    } else {
        domain = NULL;
        username = name;
    }

    if (!domain) {
        /* Look up table of well known names */
        status = lookup_well_known_names(mem_ctx, NULL, username, authority_name, sid, rtype);
        if (NT_STATUS_IS_OK(status)) {
            dom_sid_split_rid(NULL, *sid, NULL, rid);
            return NT_STATUS_OK;
        }

        if (username == NULL) {
            *authority_name = NAME_BUILTIN;
            *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN);
            *rtype = SID_NAME_DOMAIN;
            *rid = 0xFFFFFFFF;
            return NT_STATUS_OK;
        }

        if (strcasecmp_m(username, NAME_NT_AUTHORITY) == 0) {
            *authority_name = NAME_NT_AUTHORITY;
            *sid =  dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
            *rtype = SID_NAME_DOMAIN;
            dom_sid_split_rid(NULL, *sid, NULL, rid);
            return NT_STATUS_OK;
        }
        if (strcasecmp_m(username, NAME_BUILTIN) == 0) {
            *authority_name = NAME_BUILTIN;
            *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN);
            *rtype = SID_NAME_DOMAIN;
            *rid = 0xFFFFFFFF;
            return NT_STATUS_OK;
        }
        if (strcasecmp_m(username, state->domain_dns) == 0) {
            *authority_name = state->domain_name;
            *sid =  state->domain_sid;
            *rtype = SID_NAME_DOMAIN;
            *rid = 0xFFFFFFFF;
            return NT_STATUS_OK;
        }
        if (strcasecmp_m(username, state->domain_name) == 0) {
            *authority_name = state->domain_name;
            *sid =  state->domain_sid;
            *rtype = SID_NAME_DOMAIN;
            *rid = 0xFFFFFFFF;
            return NT_STATUS_OK;
        }

        /* Perhaps this is a well known user? */
        name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_NT_AUTHORITY, username);
        if (!name) {
            return NT_STATUS_NO_MEMORY;
        }
        status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
        if (NT_STATUS_IS_OK(status)) {
            return status;
        }

        /* Perhaps this is a BUILTIN user? */
        name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_BUILTIN, username);
        if (!name) {
            return NT_STATUS_NO_MEMORY;
        }
        status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
        if (NT_STATUS_IS_OK(status)) {
            return status;
        }

        /* OK, I give up - perhaps we need to assume the user is in our domain? */
        name = talloc_asprintf(mem_ctx, "%s\\%s", state->domain_name, username);
        if (!name) {
            return NT_STATUS_NO_MEMORY;
        }
        status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
        if (NT_STATUS_IS_OK(status)) {
            return status;
        }

        return STATUS_SOME_UNMAPPED;
    } else if (strcasecmp_m(domain, NAME_NT_AUTHORITY) == 0) {
        if (!*username) {
            *authority_name = NAME_NT_AUTHORITY;
            *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
            *rtype = SID_NAME_DOMAIN;
            dom_sid_split_rid(NULL, *sid, NULL, rid);
            return NT_STATUS_OK;
        }

        /* Look up table of well known names */
        status = lookup_well_known_names(mem_ctx, domain, username, authority_name,
                                         sid, rtype);
        if (NT_STATUS_IS_OK(status)) {
            dom_sid_split_rid(NULL, *sid, NULL, rid);
        }
        return status;
    } else if (strcasecmp_m(domain, NAME_BUILTIN) == 0) {
        *authority_name = NAME_BUILTIN;
        domain_dn = state->builtin_dn;
    } else if (strcasecmp_m(domain, state->domain_dns) == 0) {
        *authority_name = state->domain_name;
        domain_dn = state->domain_dn;
    } else if (strcasecmp_m(domain, state->domain_name) == 0) {
        *authority_name = state->domain_name;
        domain_dn = state->domain_dn;
    } else {
        /* Not local, need to ask winbind in future */
        return STATUS_SOME_UNMAPPED;
    }

    ret = gendb_search_dn(state->sam_ldb, mem_ctx, domain_dn, &res, attrs);
    if (ret == 1) {
        domain_sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
        if (domain_sid == NULL) {
            return NT_STATUS_INVALID_SID;
        }
    } else {
        return NT_STATUS_INVALID_SID;
    }

    if (!*username) {
        *sid = domain_sid;
        *rtype = SID_NAME_DOMAIN;
        *rid = 0xFFFFFFFF;
        return NT_STATUS_OK;
    }

    ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs,
                       "(&(sAMAccountName=%s)(objectSid=*))",
                       ldb_binary_encode_string(mem_ctx, username));
    if (ret == -1) {
        return NT_STATUS_INVALID_SID;
    }

    for (i=0; i < ret; i++) {
        *sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
        if (*sid == NULL) {
            return NT_STATUS_INVALID_SID;
        }

        /* Check that this is in the domain */
        if (!dom_sid_in_domain(domain_sid, *sid)) {
            continue;
        }

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

        *rtype = ds_atype_map(atype);
        if (*rtype == SID_NAME_UNKNOWN) {
            return STATUS_SOME_UNMAPPED;
        }

        dom_sid_split_rid(NULL, *sid, NULL, rid);
        return NT_STATUS_OK;
    }

    /* need to check for an allocated sid */

    return NT_STATUS_INVALID_SID;
}
Esempio n. 7
0
/* Query display info for a realm. This is the basic user list fn */
static NTSTATUS query_user_list(struct winbindd_domain *domain,
			       TALLOC_CTX *mem_ctx,
			       uint32_t **prids)
{
	ADS_STRUCT *ads = NULL;
	const char *attrs[] = { "sAMAccountType", "objectSid", NULL };
	int count;
	uint32_t *rids = NULL;
	ADS_STATUS rc;
	LDAPMessage *res = NULL;
	LDAPMessage *msg = NULL;
	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;

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

	if ( !winbindd_can_contact_domain( domain ) ) {
		DEBUG(10,("query_user_list: 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;
	}

	rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs);
	if (!ADS_ERR_OK(rc)) {
		DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc)));
		status = ads_ntstatus(rc);
		goto done;
	} else if (!res) {
		DEBUG(1,("query_user_list ads_search returned NULL res\n"));
		goto done;
	}

	count = ads_count_replies(ads, res);
	if (count == 0) {
		DEBUG(1,("query_user_list: No users found\n"));
		goto done;
	}

	rids = talloc_zero_array(mem_ctx, uint32_t, count);
	if (rids == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	count = 0;

	for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
		struct dom_sid user_sid;
		uint32_t atype;
		bool ok;

		ok = ads_pull_uint32(ads, msg, "sAMAccountType", &atype);
		if (!ok) {
			DBG_INFO("Object lacks sAMAccountType attribute\n");
			continue;
		}
		if (ds_atype_map(atype) != SID_NAME_USER) {
			DBG_INFO("Not a user account? atype=0x%x\n", atype);
			continue;
		}

		if (!ads_pull_sid(ads, msg, "objectSid", &user_sid)) {
			char *dn = ads_get_dn(ads, talloc_tos(), msg);
			DBG_INFO("No sid for %s !?\n", dn);
			TALLOC_FREE(dn);
			continue;
		}

		if (!dom_sid_in_domain(&domain->sid, &user_sid)) {
			fstring sidstr, domstr;
			DBG_WARNING("Got sid %s in domain %s\n",
				    sid_to_fstring(sidstr, &user_sid),
				    sid_to_fstring(domstr, &domain->sid));
			continue;
		}

		sid_split_rid(&user_sid, &rids[count]);
		count += 1;
	}

	rids = talloc_realloc(mem_ctx, rids, uint32_t, count);
	if (prids != NULL) {
		*prids = rids;
	}

	status = NT_STATUS_OK;

	DBG_NOTICE("ads query_user_list gave %d entries\n", count);

done:
	return status;
}
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;
	}
}