#include "includes.h"
#include "winbindd.h"
+#include "winbindd_ads.h"
+#include "libsmb/namequery.h"
#include "rpc_client/rpc_client.h"
#include "../librpc/gen_ndr/ndr_netlogon_c.h"
#include "../libds/common/flags.h"
/* we don't want this to affect the users ccache */
setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1);
- ads = ads_init(target_realm, target_dom_name, ldap_server);
+ ads = ads_init(target_realm,
+ target_dom_name,
+ ldap_server,
+ ADS_SASL_SEAL);
if (!ads) {
DEBUG(1,("ads_init for domain %s failed\n", target_dom_name));
return ADS_ERROR(LDAP_NO_MEMORY);
ads->auth.renewable = renewable;
ads->auth.password = password;
+ ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
+
ads->auth.realm = SMB_STRDUP(auth_realm);
if (!strupper_m(ads->auth.realm)) {
ads_destroy(&ads);
struct winbindd_domain *wb_dom;
ADS_STATUS status;
+ if (IS_AD_DC) {
+ /*
+ * Make sure we never try to use LDAP against
+ * a trusted domain as AD DC.
+ */
+ return ADS_ERROR_NT(NT_STATUS_REQUEST_NOT_ACCEPTED);
+ }
+
ads_cached_connection_reuse(adsp);
if (*adsp != NULL) {
return ADS_SUCCESS;
ADS_STATUS status;
char *password, *realm;
+ if (IS_AD_DC) {
+ /*
+ * Make sure we never try to use LDAP against
+ * a trusted domain as AD DC.
+ */
+ return NULL;
+ }
+
DEBUG(10,("ads_cached_connection\n"));
ads_cached_connection_reuse((ADS_STRUCT **)&domain->private_data);
/* 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 *num_entries,
- struct wbint_userinfo **pinfo)
+ uint32_t **prids)
{
ADS_STRUCT *ads = NULL;
- const char *attrs[] = { "*", NULL };
- int i, count;
+ 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;
- *num_entries = 0;
-
DEBUG(3,("ads: query_user_list\n"));
if ( !winbindd_can_contact_domain( domain ) ) {
goto done;
}
- (*pinfo) = talloc_zero_array(mem_ctx, struct wbint_userinfo, count);
- if (!*pinfo) {
+ 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 wbint_userinfo *info = &((*pinfo)[count]);
- uint32_t group;
+ struct dom_sid user_sid;
uint32_t atype;
bool ok;
continue;
}
- info->acct_name = ads_pull_username(ads, mem_ctx, msg);
- info->full_name = ads_pull_string(ads, mem_ctx, msg, "displayName");
- if (info->full_name == NULL) {
- info->full_name = ads_pull_string(ads, mem_ctx, msg, "name");
- }
- info->homedir = NULL;
- info->shell = NULL;
- info->primary_gid = (gid_t)-1;
-
- if (!ads_pull_sid(ads, msg, "objectSid",
- &info->user_sid)) {
- DEBUG(1, ("No sid for %s !?\n", info->acct_name));
+ 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 (!ads_pull_uint32(ads, msg, "primaryGroupID", &group)) {
- DEBUG(1, ("No primary group for %s !?\n",
- info->acct_name));
+ if (!dom_sid_in_domain(&domain->sid, &user_sid)) {
+ struct dom_sid_buf sidstr, domstr;
+ DBG_WARNING("Got sid %s in domain %s\n",
+ dom_sid_str_buf(&user_sid, &sidstr),
+ dom_sid_str_buf(&domain->sid, &domstr));
continue;
}
- sid_compose(&info->group_sid, &domain->sid, group);
+ sid_split_rid(&user_sid, &rids[count]);
count += 1;
}
- (*num_entries) = count;
- ads_msgfree(ads, res);
-
- for (i=0; i<count; i++) {
- struct wbint_userinfo *info = &((*pinfo)[i]);
- const char *gecos = NULL;
- gid_t primary_gid = (gid_t)-1;
-
- status = nss_get_info_cached(domain, &info->user_sid, mem_ctx,
- &info->homedir, &info->shell,
- &gecos, &primary_gid);
- if (!NT_STATUS_IS_OK(status)) {
- /*
- * Deliberately ignore this error, there might be more
- * users to fill
- */
- continue;
- }
-
- if (gecos != NULL) {
- info->full_name = gecos;
- }
- info->primary_gid = primary_gid;
+ rids = talloc_realloc(mem_ctx, rids, uint32_t, count);
+ if (prids != NULL) {
+ *prids = rids;
}
status = NT_STATUS_OK;
- DEBUG(3,("ads query_user_list gave %d entries\n", (*num_entries)));
+ DBG_NOTICE("ads query_user_list gave %d entries\n", count);
done:
+ ads_msgfree(ads, res);
return status;
}
struct dom_sid sid;
uint32_t rid;
- name = ads_pull_username(ads, mem_ctx, msg);
- gecos = ads_pull_string(ads, mem_ctx, msg, "name");
+ name = ads_pull_username(ads, (*info), msg);
+ gecos = ads_pull_string(ads, (*info), msg, "name");
if (!ads_pull_sid(ads, msg, "objectSid", &sid)) {
DEBUG(1,("No sid for %s !?\n", name));
continue;
continue;
}
- fstrcpy((*info)[i].acct_name, name);
- fstrcpy((*info)[i].acct_desc, gecos);
+ (*info)[i].acct_name = name;
+ (*info)[i].acct_desc = gecos;
(*info)[i].rid = rid;
i++;
}
const char *domain_name,
const char *name,
uint32_t flags,
+ const char **pdom_name,
struct dom_sid *sid,
enum lsa_SidType *type)
{
return msrpc_methods.name_to_sid(domain, mem_ctx, domain_name, name,
- flags, sid, type);
+ flags, pdom_name, sid, type);
}
/* convert a domain SID to a user or group name - use rpc methods */
domain_name, names, types);
}
-/* If you are looking for "dn_lookup": Yes, it used to be here!
- * It has gone now since it was a major speed bottleneck in
- * lookup_groupmem (its only use). It has been replaced by
- * an rpc lookup sids call... R.I.P. */
-
-/* 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_t group_rid;
- NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
- struct netr_SamInfo3 *user = NULL;
- gid_t gid = -1;
- int ret;
- char *full_name;
-
- DEBUG(3,("ads: query_user\n"));
-
- info->homedir = NULL;
- info->shell = NULL;
-
- /* try netsamlogon cache first */
-
- if ( (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);
-
- if (info->full_name == NULL) {
- /* this might fail so we don't check the return code */
- wcache_query_user_fullname(domain,
- mem_ctx,
- sid,
- &info->full_name);
- }
-
- 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)) {
- DEBUG(1,("query_user(sid=%s) ads_search: %s\n",
- sid_string_dbg(sid), ads_errstr(rc)));
- return ads_ntstatus(rc);
- } else if (!msg) {
- DEBUG(1,("query_user(sid=%s) ads_search returned NULL res\n",
- sid_string_dbg(sid)));
- return NT_STATUS_INTERNAL_ERROR;
- }
-
- 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.
- */
- full_name = ads_pull_string(ads, mem_ctx, msg, "displayName");
- if (full_name == NULL) {
- full_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 = full_name;
- } else {
- TALLOC_FREE(full_name);
- }
-
- status = NT_STATUS_OK;
-
- DEBUG(3,("ads query_user gave %s\n", info->acct_name));
- return NT_STATUS_OK;
-}
-
/* Lookup groups a user is a member of - alternate method, for when
tokenGroups are not available. */
static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain,
const char *attrs[] = {"memberOf", NULL};
uint32_t num_groups = 0;
struct dom_sid *group_sids = NULL;
- int i;
+ size_t i;
char **strings = NULL;
size_t num_strings = 0, num_sids = 0;
uint32_t primary_group_rid;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
uint32_t num_groups = 0;
+ struct dom_sid_buf buf;
DEBUG(3,("ads: lookup_usergroups\n"));
*p_num_groups = 0;
if (!ADS_ERR_OK(rc)) {
status = ads_ntstatus(rc);
DEBUG(1, ("lookup_usergroups(sid=%s) ads_search tokenGroups: "
- "%s\n", sid_string_dbg(sid), ads_errstr(rc)));
+ "%s\n",
+ dom_sid_str_buf(sid, &buf),
+ ads_errstr(rc)));
goto done;
}
status = NT_STATUS_UNSUCCESSFUL;
DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: "
"invalid number of results (count=%d)\n",
- sid_string_dbg(sid), count));
+ dom_sid_str_buf(sid, &buf),
+ count));
goto done;
}
if (!msg) {
DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: NULL msg\n",
- sid_string_dbg(sid)));
+ dom_sid_str_buf(sid, &buf)));
status = NT_STATUS_UNSUCCESSFUL;
goto done;
}
if (!ads_pull_uint32(ads, msg, "primaryGroupID", &primary_group_rid)) {
DEBUG(1,("%s: No primary group for sid=%s !?\n",
- domain->name, sid_string_dbg(sid)));
+ domain->name,
+ dom_sid_str_buf(sid, &buf)));
goto done;
}
status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
DEBUG(3,("ads lookup_usergroups (tokenGroups) succeeded for sid=%s\n",
- sid_string_dbg(sid)));
+ dom_sid_str_buf(sid, &buf)));
done:
TALLOC_FREE(user_dn);
ads_msgfree(ads, msg);
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
char *sidbinstr;
char **members = NULL;
- int i;
+ size_t i;
size_t num_members = 0;
ads_control args;
struct dom_sid *sid_mem_nocache = NULL;
uint32_t num_nocache = 0;
TALLOC_CTX *tmp_ctx = NULL;
uint32_t rid;
+ struct dom_sid_buf buf;
DEBUG(10,("ads: lookup_groupmem %s sid=%s\n", domain->name,
- sid_string_dbg(group_sid)));
+ dom_sid_str_buf(group_sid, &buf)));
*num_names = 0;
if (lookup_cached_sid(mem_ctx, &sid, &domain_name, &name,
&name_type)) {
DEBUG(10,("ads: lookup_groupmem: got sid %s from "
- "cache\n", sid_string_dbg(&sid)));
+ "cache\n",
+ dom_sid_str_buf(&sid, &buf)));
sid_copy(&(*sid_mem)[*num_names], &sid);
(*names)[*num_names] = fill_domain_username_talloc(
*names,
}
else {
DEBUG(10, ("ads: lookup_groupmem: sid %s not found in "
- "cache\n", sid_string_dbg(&sid)));
+ "cache\n",
+ dom_sid_str_buf(&sid, &buf)));
sid_copy(&(sid_mem_nocache)[num_nocache], &sid);
num_nocache++;
}
status = NT_STATUS_OK;
DEBUG(3,("ads lookup_groupmem for sid=%s succeeded\n",
- sid_string_dbg(group_sid)));
+ dom_sid_str_buf(group_sid, &buf)));
done:
return NT_STATUS_OK;
}
+ if (IS_AD_DC) {
+ DEBUG(10,("sequence: Avoid LDAP connection for domain %s\n",
+ domain->name));
+ *seq = time(NULL);
+ return NT_STATUS_OK;
+ }
+
*seq = DOM_SEQUENCE_NONE;
ads = ads_cached_connection(domain);
{
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
WERROR werr;
- int i;
+ uint32_t i;
uint32_t flags;
struct rpc_pipe_client *cli;
int ret_count;
*/
if ((trust->trust_attributes
- == LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) &&
+ & LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) &&
!domain->primary )
{
DEBUG(10,("trusted_domains: Skipping external trusted "
}
TALLOC_FREE(parent);
+ /*
+ * We need to pass the modified properties
+ * to the caller.
+ */
+ trust->trust_flags = d.domain_flags;
+ trust->trust_type = d.domain_type;
+ trust->trust_attributes = d.domain_trust_attribs;
+
wcache_tdc_add_domain( &d );
ret_count++;
}
name_to_sid,
sid_to_name,
rids_to_names,
- query_user,
lookup_usergroups,
lookup_useraliases,
lookup_groupmem,