diff options
Diffstat (limited to 'source3/nsswitch/winbindd_ads.c')
-rw-r--r-- | source3/nsswitch/winbindd_ads.c | 183 |
1 files changed, 50 insertions, 133 deletions
diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c index b61348adfe..22bad667c3 100644 --- a/source3/nsswitch/winbindd_ads.c +++ b/source3/nsswitch/winbindd_ads.c @@ -24,9 +24,6 @@ #ifdef HAVE_ADS -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - /* the realm of our primary LDAP server */ static char *primary_realm; @@ -61,7 +58,7 @@ ADS_STATUS ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path, int scope if (*res) ads_msgfree(ads, *res); *res = NULL; - DEBUG(3,("Reopening ads connection to %s after error %s\n", + DEBUG(1,("Reopening ads connection to %s after error %s\n", ads->ldap_server, ads_errstr(status))); if (ads->ld) { ldap_unbind(ads->ld); @@ -122,8 +119,6 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain) if (resolve_name(domain->name, &server_ip, 0x1b)) { sname = inet_ntoa(server_ip); - } else if (resolve_name(domain->name, &server_ip, 0x1c)) { - sname = inet_ntoa(server_ip); } else { if (strcasecmp(domain->name, lp_workgroup()) != 0) { DEBUG(1,("can't find domain controller for %s\n", domain->name)); @@ -132,7 +127,7 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain) sname = NULL; } - ads = ads_init(primary_realm, domain->name, NULL, NULL, NULL); + ads = ads_init(primary_realm, sname, NULL, NULL); if (!ads) { DEBUG(1,("ads_init for domain %s failed\n", domain->name)); return NULL; @@ -143,7 +138,7 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain) ads->password = secrets_fetch_machine_password(); status = ads_connect(ads); - if (!ADS_ERR_OK(status) || !ads->realm) { + if (!ADS_ERR_OK(status)) { extern struct winbindd_methods msrpc_methods; DEBUG(1,("ads_connect for domain %s failed: %s\n", domain->name, ads_errstr(status))); @@ -191,24 +186,6 @@ static enum SID_NAME_USE ads_atype_map(uint32 atype) return SID_NAME_UNKNOWN; } -/* - in order to support usernames longer than 21 characters we need to - use both the sAMAccountName and the userPrincipalName attributes - It seems that not all users have the userPrincipalName attribute set -*/ -static char *pull_username(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, void *msg) -{ - char *ret, *p; - - ret = ads_pull_string(ads, mem_ctx, msg, "userPrincipalName"); - if (ret && (p = strchr(ret, '@'))) { - *p = 0; - return ret; - } - return ads_pull_string(ads, mem_ctx, msg, "sAMAccountName"); -} - - /* 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, @@ -216,9 +193,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, WINBIND_USERINFO **info) { ADS_STRUCT *ads = NULL; - const char *attrs[] = {"userPrincipalName", - "sAMAccountName", - "name", "objectSid", "primaryGroupID", + const char *attrs[] = {"sAMAccountName", "name", "objectSid", "primaryGroupID", "sAMAccountType", NULL}; int i, count; ADS_STATUS rc; @@ -265,7 +240,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, continue; } - name = pull_username(ads, mem_ctx, msg); + name = ads_pull_string(ads, mem_ctx, msg, "sAMAccountName"); gecos = ads_pull_string(ads, mem_ctx, msg, "name"); if (!ads_pull_sid(ads, msg, "objectSid", &sid)) { DEBUG(1,("No sid for %s !?\n", name)); @@ -276,7 +251,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, continue; } - if (!sid_peek_check_rid(&domain->sid, &sid, &rid)) { + if (!sid_peek_rid(&sid, &rid)) { DEBUG(1,("No rid for %s !?\n", name)); continue; } @@ -306,8 +281,7 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, struct acct_info **info) { ADS_STRUCT *ads = NULL; - const char *attrs[] = {"userPrincipalName", "sAMAccountName", - "name", "objectSid", + const char *attrs[] = {"sAMAccountName", "name", "objectSid", "sAMAccountType", NULL}; int i, count; ADS_STATUS rc; @@ -324,13 +298,13 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, rc = ads_search_retry(ads, &res, "(objectCategory=group)", attrs); if (!ADS_ERR_OK(rc)) { - DEBUG(1,("enum_dom_groups ads_search: %s\n", ads_errstr(rc))); + DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc))); goto done; } count = ads_count_replies(ads, res); if (count == 0) { - DEBUG(1,("enum_dom_groups: No groups found\n")); + DEBUG(1,("query_user_list: No users found\n")); goto done; } @@ -352,14 +326,14 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, &account_type) || !(account_type & ATYPE_GROUP)) continue; - name = pull_username(ads, mem_ctx, msg); + name = ads_pull_string(ads, mem_ctx, msg, "sAMAccountName"); gecos = ads_pull_string(ads, mem_ctx, msg, "name"); if (!ads_pull_sid(ads, msg, "objectSid", &sid)) { DEBUG(1,("No sid for %s !?\n", name)); continue; } - if (!sid_peek_check_rid(&domain->sid, &sid, &rid)) { + if (!sid_peek_rid(&sid, &rid)) { DEBUG(1,("No rid for %s !?\n", name)); continue; } @@ -403,9 +377,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, ads = ads_cached_connection(domain); if (!ads) goto done; - /* accept either the win2000 or the pre-win2000 username */ - asprintf(&exp, "(|(sAMAccountName=%s)(userPrincipalName=%s@%s))", - name, name, ads->realm); + asprintf(&exp, "(sAMAccountName=%s)", name); rc = ads_search_retry(ads, &res, exp, attrs); free(exp); if (!ADS_ERR_OK(rc)) { @@ -449,9 +421,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain, enum SID_NAME_USE *type) { ADS_STRUCT *ads = NULL; - const char *attrs[] = {"userPrincipalName", - "sAMAccountName", - "sAMAccountType", NULL}; + const char *attrs[] = {"sAMAccountName", "sAMAccountType", NULL}; ADS_STATUS rc; void *msg = NULL; char *exp; @@ -478,7 +448,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain, goto done; } - *name = pull_username(ads, mem_ctx, msg); + *name = ads_pull_string(ads, mem_ctx, msg, "sAMAccountName"); *type = ads_atype_map(atype); status = NT_STATUS_OK; @@ -492,50 +462,6 @@ done: } -/* convert a DN to a name, rid and name type - this might become a major speed bottleneck if groups have - lots of users, in which case we could cache the results -*/ -static BOOL dn_lookup(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, - const char *dn, - char **name, uint32 *name_type, uint32 *rid) -{ - char *exp; - void *res = NULL; - const char *attrs[] = {"userPrincipalName", "sAMAccountName", - "objectSid", "sAMAccountType", NULL}; - ADS_STATUS rc; - uint32 atype; - DOM_SID sid; - - asprintf(&exp, "(distinguishedName=%s)", dn); - rc = ads_search_retry(ads, &res, exp, attrs); - free(exp); - if (!ADS_ERR_OK(rc)) { - goto failed; - } - - (*name) = pull_username(ads, mem_ctx, res); - - if (!ads_pull_uint32(ads, res, "sAMAccountType", &atype)) { - goto failed; - } - (*name_type) = ads_atype_map(atype); - - if (!ads_pull_sid(ads, res, "objectSid", &sid) || - !sid_peek_rid(&sid, rid)) { - goto failed; - } - - if (res) ads_msgfree(ads, res); - return True; - -failed: - if (res) ads_msgfree(ads, res); - return False; -} - - /* convert a sid to a distnguished name */ static NTSTATUS sid_to_distinguished_name(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, @@ -585,9 +511,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain, WINBIND_USERINFO *info) { ADS_STRUCT *ads = NULL; - const char *attrs[] = {"userPrincipalName", - "sAMAccountName", - "name", "objectSid", + const char *attrs[] = {"sAMAccountName", "name", "objectSid", "primaryGroupID", NULL}; ADS_STATUS rc; int count; @@ -620,7 +544,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain, goto done; } - info->acct_name = pull_username(ads, mem_ctx, msg); + info->acct_name = ads_pull_string(ads, mem_ctx, msg, "sAMAccountName"); info->full_name = ads_pull_string(ads, mem_ctx, msg, "name"); if (!ads_pull_sid(ads, msg, "objectSid", &sid)) { DEBUG(1,("No sid for %d !?\n", user_rid)); @@ -631,7 +555,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain, goto done; } - if (!sid_peek_check_rid(&domain->sid,&sid, &info->user_rid)) { + if (!sid_peek_rid(&sid, &info->user_rid)) { DEBUG(1,("No rid for %d !?\n", user_rid)); goto done; } @@ -709,7 +633,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, for (i=1;i<count;i++) { uint32 rid; - if (!sid_peek_check_rid(&domain->sid, &sids[i-1], &rid)) continue; + if (!sid_peek_rid(&sids[i-1], &rid)) continue; (*user_gids)[*num_groups] = rid; (*num_groups)++; } @@ -722,9 +646,7 @@ done: return status; } -/* - find the members of a group, given a group rid and domain - */ + static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, uint32 group_rid, uint32 *num_names, @@ -732,16 +654,13 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, uint32 **name_types) { DOM_SID group_sid; + const char *attrs[] = {"sAMAccountName", "objectSid", "sAMAccountType", NULL}; ADS_STATUS rc; int count; - void *res=NULL; + void *res=NULL, *msg=NULL; ADS_STRUCT *ads = NULL; - char *exp; + char *exp, *dn = NULL; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - char *sidstr; - const char *attrs[] = {"member", NULL}; - char **members; - int i, num_members; *num_names = 0; @@ -749,14 +668,17 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, if (!ads) goto done; sid_from_rid(domain, group_rid, &group_sid); - sidstr = sid_binstring(&group_sid); + status = sid_to_distinguished_name(domain, mem_ctx, &group_sid, &dn); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3,("Failed to find distinguishedName for %s\n", sid_string_static(&group_sid))); + return status; + } - /* search for all members of the group */ - asprintf(&exp, "(objectSid=%s)",sidstr); + /* search for all users who have that group sid as primary group or as member */ + asprintf(&exp, "(&(objectCategory=user)(|(primaryGroupID=%d)(memberOf=%s)))", + group_rid, dn); rc = ads_search_retry(ads, &res, exp, attrs); free(exp); - free(sidstr); - if (!ADS_ERR_OK(rc)) { DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc))); goto done; @@ -768,33 +690,29 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, goto done; } - members = ads_pull_strings(ads, mem_ctx, res, "member"); - if (!members) { - /* no members? ok ... */ - status = NT_STATUS_OK; - goto done; - } - - /* now we need to turn a list of members into rids, names and name types - the problem is that the members are in the form of distinguised names - */ - for (i=0;members[i];i++) /* noop */ ; - num_members = i; + (*rid_mem) = talloc_zero(mem_ctx, sizeof(uint32) * count); + (*name_types) = talloc_zero(mem_ctx, sizeof(uint32) * count); + (*names) = talloc_zero(mem_ctx, sizeof(char *) * count); - (*rid_mem) = talloc_zero(mem_ctx, sizeof(uint32) * num_members); - (*name_types) = talloc_zero(mem_ctx, sizeof(uint32) * num_members); - (*names) = talloc_zero(mem_ctx, sizeof(char *) * num_members); - - for (i=0;i<num_members;i++) { - uint32 name_type, rid; - char *name; + for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) { + uint32 atype, rid; + DOM_SID sid; - if (dn_lookup(ads, mem_ctx, members[i], &name, &name_type, &rid)) { - (*names)[*num_names] = name; - (*name_types)[*num_names] = name_type; - (*rid_mem)[*num_names] = rid; - (*num_names)++; + (*names)[*num_names] = ads_pull_string(ads, mem_ctx, msg, "sAMAccountName"); + if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype)) { + continue; + } + (*name_types)[*num_names] = ads_atype_map(atype); + if (!ads_pull_sid(ads, msg, "objectSid", &sid)) { + DEBUG(1,("No sid for %s !?\n", (*names)[*num_names])); + continue; } + if (!sid_peek_rid(&sid, &rid)) { + DEBUG(1,("No rid for %s !?\n", (*names)[*num_names])); + continue; + } + (*rid_mem)[*num_names] = rid; + (*num_names)++; } status = NT_STATUS_OK; @@ -805,7 +723,6 @@ done: return status; } - /* find the sequence number for a domain */ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) { |