mirror of
https://github.com/samba-team/samba.git
synced 2025-01-12 09:18:10 +03:00
* set domain->last_status = NT_STATUS_SERVER_DISABLED on an ads_connect() failure
* Fix code to use winbind_rpc methods for trusted mixed mode or NT4 domains
( does no one ever test this? )
* add in LDAP code to get the sequence number for rpc based seqnum update.
( this is needed if the DC is upgraded and samba is not reconfigured
to use security = ads; it's not pretty but it works (from app_head) )
* fix bug that caused us to enumerate domain local groups in domains
other than our own
(This used to be commit 14f2cd139a
)
This commit is contained in:
parent
5f1ff72f7d
commit
81d8eefc0d
@ -589,13 +589,14 @@ BOOL user_in_list(const char *user,const char **list, gid_t *groups, size_t n_gr
|
||||
fstrcpy(domain, *list);
|
||||
domain[PTR_DIFF(p, *list)] = 0;
|
||||
|
||||
/* Check to see if name is a Windows group; Win2k native mode DCs
|
||||
will return domain local groups; while NT4 or mixed mode 2k DCs
|
||||
will not */
|
||||
/* Check to see if name is a Windows group; Win2k native mode DCs
|
||||
will return domain local groups; while NT4 or mixed mode 2k DCs
|
||||
will not */
|
||||
|
||||
if ( winbind_lookup_name(NULL, *list, &g_sid, &name_type)
|
||||
&& ( name_type==SID_NAME_DOM_GRP || name_type==SID_NAME_ALIAS ) )
|
||||
{
|
||||
if ( winbind_lookup_name(NULL, *list, &g_sid, &name_type)
|
||||
&& ( name_type==SID_NAME_DOM_GRP ||
|
||||
(strequal(lp_workgroup(), domain) && name_type==SID_NAME_ALIAS) ) )
|
||||
{
|
||||
|
||||
/* Check if user name is in the Windows group */
|
||||
ret = user_in_winbind_group_list(user, *list, &winbind_answered);
|
||||
|
@ -116,7 +116,11 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
|
||||
DEBUG(3,("ads: query_user_list\n"));
|
||||
|
||||
ads = ads_cached_connection(domain);
|
||||
if (!ads) goto done;
|
||||
|
||||
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)) {
|
||||
@ -213,7 +217,11 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
|
||||
DEBUG(3,("ads: enum_dom_groups\n"));
|
||||
|
||||
ads = ads_cached_connection(domain);
|
||||
if (!ads) goto done;
|
||||
|
||||
if (!ads) {
|
||||
domain->last_status = NT_STATUS_SERVER_DISABLED;
|
||||
goto done;
|
||||
}
|
||||
|
||||
rc = ads_search_retry(ads, &res, "(objectCategory=group)", attrs);
|
||||
if (!ADS_ERR_OK(rc)) {
|
||||
@ -236,7 +244,9 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
|
||||
i = 0;
|
||||
|
||||
group_flags = ATYPE_GLOBAL_GROUP;
|
||||
if ( domain->native_mode )
|
||||
|
||||
/* only grab domain local groups for our domain */
|
||||
if ( domain->native_mode && strequal(lp_realm(), domain->alt_name) )
|
||||
group_flags |= ATYPE_LOCAL_GROUP;
|
||||
|
||||
for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
|
||||
@ -286,7 +296,7 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
|
||||
{
|
||||
/*
|
||||
* This is a stub function only as we returned the domain
|
||||
* ocal groups in enum_dom_groups() if the domain->native field
|
||||
* local groups in enum_dom_groups() if the domain->native field
|
||||
* was true. This is a simple performance optimization when
|
||||
* using LDAP.
|
||||
*
|
||||
@ -311,8 +321,11 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
|
||||
DEBUG(3,("ads: name_to_sid\n"));
|
||||
|
||||
ads = ads_cached_connection(domain);
|
||||
if (!ads)
|
||||
|
||||
if (!ads) {
|
||||
domain->last_status = NT_STATUS_SERVER_DISABLED;
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
return ads_name_to_sid(ads, name, sid, type);
|
||||
}
|
||||
@ -326,9 +339,13 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
|
||||
{
|
||||
ADS_STRUCT *ads = NULL;
|
||||
DEBUG(3,("ads: sid_to_name\n"));
|
||||
|
||||
ads = ads_cached_connection(domain);
|
||||
if (!ads)
|
||||
|
||||
if (!ads) {
|
||||
domain->last_status = NT_STATUS_SERVER_DISABLED;
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
return ads_sid_to_name(ads, mem_ctx, sid, name, type);
|
||||
}
|
||||
@ -408,7 +425,11 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
|
||||
DEBUG(3,("ads: query_user\n"));
|
||||
|
||||
ads = ads_cached_connection(domain);
|
||||
if (!ads) goto done;
|
||||
|
||||
if (!ads) {
|
||||
domain->last_status = NT_STATUS_SERVER_DISABLED;
|
||||
goto done;
|
||||
}
|
||||
|
||||
sidstr = sid_binstring(sid);
|
||||
asprintf(&exp, "(objectSid=%s)", sidstr);
|
||||
@ -474,7 +495,11 @@ static NTSTATUS lookup_usergroups_alt(struct winbindd_domain *domain,
|
||||
DEBUG(3,("ads: lookup_usergroups_alt\n"));
|
||||
|
||||
ads = ads_cached_connection(domain);
|
||||
if (!ads) goto done;
|
||||
|
||||
if (!ads) {
|
||||
domain->last_status = NT_STATUS_SERVER_DISABLED;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* buggy server, no tokenGroups. Instead lookup what groups this user
|
||||
is a member of by DN search on member*/
|
||||
@ -562,7 +587,11 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
|
||||
*num_groups = 0;
|
||||
|
||||
ads = ads_cached_connection(domain);
|
||||
if (!ads) goto done;
|
||||
|
||||
if (!ads) {
|
||||
domain->last_status = NT_STATUS_SERVER_DISABLED;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!(sidstr = sid_binstring(sid))) {
|
||||
DEBUG(1,("lookup_usergroups(sid=%s) sid_binstring returned NULL\n", sid_to_string(sid_string, sid)));
|
||||
@ -669,7 +698,11 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
|
||||
*num_names = 0;
|
||||
|
||||
ads = ads_cached_connection(domain);
|
||||
if (!ads) goto done;
|
||||
|
||||
if (!ads) {
|
||||
domain->last_status = NT_STATUS_SERVER_DISABLED;
|
||||
goto done;
|
||||
}
|
||||
|
||||
sidstr = sid_binstring(group_sid);
|
||||
|
||||
@ -745,7 +778,11 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
|
||||
*seq = DOM_SEQUENCE_NONE;
|
||||
|
||||
ads = ads_cached_connection(domain);
|
||||
if (!ads) return NT_STATUS_UNSUCCESSFUL;
|
||||
|
||||
if (!ads) {
|
||||
domain->last_status = NT_STATUS_SERVER_DISABLED;
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
rc = ads_USN(ads, seq);
|
||||
if (!ADS_ERR_OK(rc)) {
|
||||
@ -773,7 +810,11 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
|
||||
*names = NULL;
|
||||
|
||||
ads = ads_cached_connection(domain);
|
||||
if (!ads) return NT_STATUS_UNSUCCESSFUL;
|
||||
|
||||
if (!ads) {
|
||||
domain->last_status = NT_STATUS_SERVER_DISABLED;
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
rc = ads_trusted_domains(ads, mem_ctx, num_domains, names, alt_names, dom_sids);
|
||||
|
||||
@ -789,7 +830,11 @@ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
|
||||
DEBUG(3,("ads: domain_sid\n"));
|
||||
|
||||
ads = ads_cached_connection(domain);
|
||||
if (!ads) return NT_STATUS_UNSUCCESSFUL;
|
||||
|
||||
if (!ads) {
|
||||
domain->last_status = NT_STATUS_SERVER_DISABLED;
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
rc = ads_domain_sid(ads, sid);
|
||||
|
||||
@ -815,7 +860,11 @@ static NTSTATUS alternate_name(struct winbindd_domain *domain)
|
||||
DEBUG(3,("ads: alternate_name\n"));
|
||||
|
||||
ads = ads_cached_connection(domain);
|
||||
if (!ads) return NT_STATUS_UNSUCCESSFUL;
|
||||
|
||||
if (!ads) {
|
||||
domain->last_status = NT_STATUS_SERVER_DISABLED;
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
if (!(ctx = talloc_init("alternate_name"))) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
|
@ -105,9 +105,19 @@ static struct winbind_cache *get_cache(struct winbindd_domain *domain)
|
||||
#ifdef HAVE_ADS
|
||||
case SEC_ADS: {
|
||||
extern struct winbindd_methods ads_methods;
|
||||
domain->backend = &ads_methods;
|
||||
break;
|
||||
}
|
||||
/* always obey the lp_security parameter for our domain */
|
||||
if ( strequal(lp_realm(), domain->alt_name) ) {
|
||||
domain->backend = &ads_methods;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( domain->native_mode ) {
|
||||
domain->backend = &ads_methods;
|
||||
break;
|
||||
}
|
||||
|
||||
/* fall through */
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
domain->backend = &msrpc_methods;
|
||||
@ -990,10 +1000,6 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
|
||||
do_query:
|
||||
*name = NULL;
|
||||
|
||||
if (wcache_server_down(domain)) {
|
||||
return NT_STATUS_SERVER_DISABLED;
|
||||
}
|
||||
|
||||
/* If the seq number check indicated that there is a problem
|
||||
* with this DC, then return that status... except for
|
||||
* access_denied. This is special because the dc may be in
|
||||
|
@ -75,7 +75,9 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
|
||||
|
||||
*num_gr_mem = 0;
|
||||
|
||||
if ((group_name_type!=SID_NAME_DOM_GRP) && (group_name_type!=SID_NAME_ALIAS)) {
|
||||
if ( !((group_name_type==SID_NAME_DOM_GRP) ||
|
||||
((group_name_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) )
|
||||
{
|
||||
DEBUG(1, ("SID %s in domain %s isn't a domain group (%d)\n",
|
||||
sid_to_string(sid_string, group_sid), domain->name,
|
||||
group_name_type));
|
||||
@ -228,7 +230,9 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
|
||||
if ((name_type != SID_NAME_ALIAS) && (name_type != SID_NAME_DOM_GRP)) {
|
||||
if ( !((name_type==SID_NAME_DOM_GRP) ||
|
||||
((name_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) )
|
||||
{
|
||||
DEBUG(1, ("name '%s' is not a local or domain group: %d\n",
|
||||
name_group, name_type));
|
||||
return WINBINDD_ERROR;
|
||||
@ -292,8 +296,9 @@ enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state)
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
|
||||
if (!((name_type == SID_NAME_ALIAS) ||
|
||||
(name_type == SID_NAME_DOM_GRP))) {
|
||||
if ( !((name_type==SID_NAME_DOM_GRP) ||
|
||||
((name_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) )
|
||||
{
|
||||
DEBUG(1, ("name '%s' is not a local or domain group: %d\n",
|
||||
group_name, name_type));
|
||||
return WINBINDD_ERROR;
|
||||
@ -451,10 +456,10 @@ static BOOL get_sam_group_entries(struct getent_state *ent)
|
||||
|
||||
ent->num_sam_entries = num_entries;
|
||||
|
||||
/* get the domain local groups if we are a member of a native win2k domain */
|
||||
/* get the domain local groups if we are a member of a native win2k domain
|
||||
and are not using LDAP to get the groups */
|
||||
|
||||
if ( domain->native_mode
|
||||
&& domain->methods->enum_local_groups
|
||||
if ( lp_security != SEC_ADS && domain->native_mode
|
||||
&& strequal(lp_workgroup(), domain->name) )
|
||||
{
|
||||
DEBUG(4,("get_sam_group_entries: Native Mode 2k domain; enumerating local groups as well\n"));
|
||||
@ -891,8 +896,9 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
|
||||
/* Check it is a domain group or an alias (domain local group)
|
||||
in a win2k native mode domain. */
|
||||
|
||||
if ( !(sid_type == SID_NAME_DOM_GRP || sid_type == SID_NAME_ALIAS) ) {
|
||||
|
||||
if ( !((sid_type==SID_NAME_DOM_GRP) ||
|
||||
((sid_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) )
|
||||
{
|
||||
DEBUG(10, ("winbindd_getgroups: sid type %d "
|
||||
"for %s is not a domain group\n",
|
||||
sid_type,
|
||||
|
@ -681,6 +681,168 @@ done:
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LDAP
|
||||
|
||||
#include <ldap.h>
|
||||
|
||||
static SIG_ATOMIC_T gotalarm;
|
||||
|
||||
/***************************************************************
|
||||
Signal function to tell us we timed out.
|
||||
****************************************************************/
|
||||
|
||||
static void gotalarm_sig(void)
|
||||
{
|
||||
gotalarm = 1;
|
||||
}
|
||||
|
||||
static LDAP *ldap_open_with_timeout(const char *server, int port, unsigned int to)
|
||||
{
|
||||
LDAP *ldp = NULL;
|
||||
|
||||
/* Setup timeout */
|
||||
gotalarm = 0;
|
||||
CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
|
||||
alarm(to);
|
||||
/* End setup timeout. */
|
||||
|
||||
ldp = ldap_open(server, port);
|
||||
|
||||
/* Teardown timeout. */
|
||||
CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);
|
||||
alarm(0);
|
||||
|
||||
return ldp;
|
||||
}
|
||||
|
||||
static int get_ldap_seq(const char *server, uint32 *seq)
|
||||
{
|
||||
int ret = -1;
|
||||
struct timeval to;
|
||||
char *attrs[] = {"highestCommittedUSN", NULL};
|
||||
LDAPMessage *res = NULL;
|
||||
char **values = NULL;
|
||||
LDAP *ldp = NULL;
|
||||
|
||||
*seq = DOM_SEQUENCE_NONE;
|
||||
|
||||
/*
|
||||
* 10 second timeout on open. This is needed as the search timeout
|
||||
* doesn't seem to apply to doing an open as well. JRA.
|
||||
*/
|
||||
|
||||
if ((ldp = ldap_open_with_timeout(server, LDAP_PORT, 10)) == NULL)
|
||||
return -1;
|
||||
|
||||
#if 0
|
||||
/* As per tridge comment this doesn't seem to be needed. JRA */
|
||||
if ((err = ldap_simple_bind_s(ldp, NULL, NULL)) != 0)
|
||||
goto done;
|
||||
#endif
|
||||
|
||||
/* Timeout if no response within 20 seconds. */
|
||||
to.tv_sec = 10;
|
||||
to.tv_usec = 0;
|
||||
|
||||
if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)", &attrs[0], 0, &to, &res))
|
||||
goto done;
|
||||
|
||||
if (ldap_count_entries(ldp, res) != 1)
|
||||
goto done;
|
||||
|
||||
values = ldap_get_values(ldp, res, "highestCommittedUSN");
|
||||
if (!values || !values[0])
|
||||
goto done;
|
||||
|
||||
*seq = atoi(values[0]);
|
||||
ret = 0;
|
||||
|
||||
done:
|
||||
|
||||
if (values)
|
||||
ldap_value_free(values);
|
||||
if (res)
|
||||
ldap_msgfree(res);
|
||||
if (ldp)
|
||||
ldap_unbind(ldp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Get the sequence number for a Windows AD native mode domain using
|
||||
LDAP queries
|
||||
**********************************************************************/
|
||||
|
||||
int get_ldap_sequence_number( const char* domain, uint32 *seq)
|
||||
{
|
||||
int ret = -1;
|
||||
int i;
|
||||
struct in_addr *ip_list = NULL;
|
||||
int count;
|
||||
BOOL list_ordered;
|
||||
|
||||
if ( !get_dc_list( domain, &ip_list, &count, &list_ordered ) ) {
|
||||
DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
|
||||
return False;
|
||||
}
|
||||
|
||||
if ( !list_ordered )
|
||||
{
|
||||
/*
|
||||
* Pick a nice close server. Look for DC on local net
|
||||
* (assuming we don't have a list of preferred DC's)
|
||||
*/
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (is_zero_ip(ip_list[i]))
|
||||
continue;
|
||||
|
||||
if ( !is_local_net(ip_list[i]) )
|
||||
continue;
|
||||
|
||||
if ( (ret = get_ldap_seq( inet_ntoa(ip_list[i]), seq)) == 0 )
|
||||
goto done;
|
||||
|
||||
zero_ip(&ip_list[i]);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Secondly try and contact a random PDC/BDC.
|
||||
*/
|
||||
|
||||
i = (sys_random() % count);
|
||||
|
||||
if ( !is_zero_ip(ip_list[i]) ) {
|
||||
if ( (ret = get_ldap_seq( inet_ntoa(ip_list[i]), seq)) == 0 )
|
||||
goto done;
|
||||
}
|
||||
zero_ip(&ip_list[i]); /* Tried and failed. */
|
||||
}
|
||||
|
||||
/* Finally return first DC that we can contact */
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (is_zero_ip(ip_list[i]))
|
||||
continue;
|
||||
|
||||
if ( (ret = get_ldap_seq( inet_ntoa(ip_list[i]), seq)) == 0 )
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
if ( ret == 0 ) {
|
||||
DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence number for Domain (%s) from DC (%s)\n",
|
||||
domain, inet_ntoa(ip_list[i])));
|
||||
}
|
||||
|
||||
SAFE_FREE(ip_list);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* HAVE_LDAP */
|
||||
|
||||
/* find the sequence number for a domain */
|
||||
static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
|
||||
{
|
||||
@ -704,6 +866,22 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
|
||||
|
||||
retry = 0;
|
||||
do {
|
||||
#ifdef HAVE_LDAP
|
||||
if ( domain->native_mode )
|
||||
{
|
||||
DEBUG(8,("using get_ldap_seq() to retrieve the sequence number\n"));
|
||||
|
||||
if ( get_ldap_sequence_number( domain->name, seq ) == 0 ) {
|
||||
result = NT_STATUS_OK;
|
||||
DEBUG(10,("domain_sequence_number: LDAP for domain %s is %u\n",
|
||||
domain->name, *seq));
|
||||
goto done;
|
||||
}
|
||||
|
||||
DEBUG(10,("domain_sequence_number: failed to get LDAP sequence number for domain %s\n",
|
||||
domain->name ));
|
||||
}
|
||||
#endif /* HAVE_LDAP */
|
||||
/* Get sam handle */
|
||||
if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd)))
|
||||
goto done;
|
||||
|
Loading…
Reference in New Issue
Block a user