--- samba-3.0.32/source/nsswitch/idmap_ad.c 2008-08-25 23:09:21.000000000 +0200 +++ samba-3.0.32-patched/source/nsswitch/idmap_ad.c 2008-09-05 15:16:46.000000000 +0200 @@ -26,6 +26,7 @@ */ #include "includes.h" +#include "winbindd.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_IDMAP @@ -48,10 +49,89 @@ NTSTATUS init_module(void); -static ADS_STRUCT *ad_idmap_ads = NULL; +static ADS_STRUCT *ad_idmap_ads = NULL; static struct posix_schema *ad_schema = NULL; static enum wb_posix_mapping ad_map_type = WB_POSIX_MAP_UNKNOWN; + +/************************************************************************ + ***********************************************************************/ + +static ADS_STRUCT *ad_idmap_new_cached_connection(struct winbindd_domain *domain) +{ + ADS_STRUCT *ads; + ADS_STATUS status; + fstring dc_name; + struct in_addr dc_ip; + + DEBUG(10,("ads_cached_connection\n")); + + SMB_ASSERT(domain->private_data == NULL); + + setenv("KRB5CCNAME", "MEMORY:winbind_ccache", 1); + + ads = ads_init(domain->alt_name, domain->name, NULL); + if (!ads) { + DEBUG(1,("ads_init for domain %s failed\n", domain->name)); + return NULL; + } + + /* the machine acct password might have change - fetch it every time */ + SAFE_FREE(ads->auth.password); + + ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); + + SAFE_FREE(ads->auth.realm); + ads->auth.realm = SMB_STRDUP(lp_realm()); + + status = ads_connect(ads); + if (!ADS_ERR_OK(status)) { + DEBUG(1,("ads_connect for domain %s failed: %s\n", + domain->name, ads_errstr(status))); + ads_destroy(&ads); + + return NULL; + } + + ads->is_mine = False; + + domain->private_data = (void *)ads; + return ads; +} + +/************************************************************************ + ***********************************************************************/ + +static ADS_STRUCT *ad_idmap_live_connection(struct winbindd_domain *d) +{ + ADS_STRUCT *ads = (ADS_STRUCT *) d->private_data; + + if (ads) { + + time_t expire; + time_t now = time(NULL); + + /* check for a valid structure */ + expire = MIN(ads->auth.tgt_expire, ads->auth.tgs_expire); + + DEBUG(7, ("Current tickets expire in %d seconds (at %d, time is now %d)\n", + (uint32)expire-(uint32)now, (uint32) expire, (uint32) now)); + + if ( ads->config.realm && (expire > now)) { + return ads; + } + + /* we own this ADS_STRUCT so make sure it goes away */ + ads->is_mine = True; + ads_destroy( &ads ); + ads_kdestroy("MEMORY:winbind_ccache"); + ads = NULL; + d->private_data = NULL; + } + + return ad_idmap_new_cached_connection(d); +} + /************************************************************************ ***********************************************************************/ @@ -61,7 +141,7 @@ ADS_STATUS status; BOOL local = False; fstring dc_name; - struct in_addr dc_ip; + struct in_addr dc_ip; if (ad_idmap_ads != NULL) { @@ -73,10 +153,9 @@ expire = MIN(ads->auth.tgt_expire, ads->auth.tgs_expire); /* check for a valid structure */ - DEBUG(7, ("Current tickets expire in %d seconds (at %d, time is now %d)\n", - (uint32)expire-(uint32)now, (uint32) expire, (uint32) now)); + DEBUG(7, ("Current tickets expire in %d seconds (at %d, time is now %s)\n", (uint32)expire-(uint32)now, (uint32) expire, (uint32) now)); - if ( ads->config.realm && (expire > time(NULL))) { + if ( ads->config.realm && (expire < time(NULL))) { return ads; } else { /* we own this ADS_STRUCT so make sure it goes away */ @@ -85,7 +164,7 @@ ads_destroy( &ads ); ads_kdestroy(WINBIND_CCACHE_NAME); ad_idmap_ads = NULL; - TALLOC_FREE( ad_schema ); + TALLOC_FREE( ad_schema ); } } @@ -109,7 +188,7 @@ /* setup server affinity */ get_dc_name( NULL, ads->auth.realm, dc_name, &dc_ip ); - + status = ads_connect(ads); if (!ADS_ERR_OK(status)) { DEBUG(1, ("ad_idmap_init: failed to connect to AD\n")); @@ -127,18 +206,18 @@ /************************************************************************ ***********************************************************************/ -static ADS_STRUCT *ad_idmap_cached_connection(void) +static ADS_STRUCT *ad_idmap_cached_connection_orig(void) { ADS_STRUCT *ads = ad_idmap_cached_connection_internal(); if ( !ads ) - return NULL; + return NULL; - /* if we have a valid ADS_STRUCT and the schema model is + /*if we have a valid ADS_STRUCT and the schema model is defined, then we can return here. */ if ( ad_schema ) - return ads; + return ads; /* Otherwise, set the schema model */ @@ -160,6 +239,29 @@ /************************************************************************ ***********************************************************************/ +static ADS_STRUCT *ad_idmap_cached_connection(const DOM_SID *sid) +{ + struct winbindd_domain *d; + ADS_STRUCT *ads = NULL; + + d = find_domain_from_sid(sid); + + if (d == NULL) { + DEBUG(1,("Tried to find connection to unknown domain [%s]\n", sid_string_static(sid))); + return NULL; + } + + if (!d->active_directory) { + DEBUG(1,("ad_idmap_cached_connection found non-AD domain %s\n", d->name)); + return NULL; + } + + return ad_idmap_live_connection(d); +} + +/************************************************************************ + ***********************************************************************/ + static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom) { struct idmap_ad_context *ctx; @@ -201,7 +303,7 @@ else DEBUG(0,("idmap_ad_initialize: Unknown schema_mode (%s)\n", schema_mode)); - } + } dom->private_data = ctx; dom->initialized = True; @@ -248,13 +350,13 @@ /************************************************************************ ***********************************************************************/ -static NTSTATUS idmap_ad_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids) +static NTSTATUS idmap_ad_unixids_to_sids_in_domain(ADS_STRUCT *ads, struct idmap_domain *dom,struct id_map **ids) { NTSTATUS ret; TALLOC_CTX *memctx; struct idmap_ad_context *ctx; ADS_STATUS rc; - ADS_STRUCT *ads; +// added 'ADS_STRUCT *ads' to method-header, removed it here const char *attrs[] = { "sAMAccountType", "objectSid", NULL, /* uidnumber */ @@ -290,7 +392,7 @@ return NT_STATUS_NO_MEMORY; } - if ( (ads = ad_idmap_cached_connection()) == NULL ) { + if ( (ads = ad_idmap_cached_connection_orig()) == NULL ) { DEBUG(1, ("ADS uninitialized\n")); ret = NT_STATUS_UNSUCCESSFUL; goto done; @@ -467,7 +569,29 @@ } /************************************************************************ - ***********************************************************************/ +***********************************************************************/ + +static NTSTATUS idmap_ad_unixids_to_sids(struct idmap_domain *domain, struct id_map **iids) +{ + struct winbindd_domain *d; + ADS_STRUCT *ads = NULL; + NTSTATUS status; + + for (d = domain_list(); d; d = d->next) { + ads = ad_idmap_live_connection(d); + if (!ads) { + DEBUG(1,("ad_idmap_get_sid_from_id: could not check %s\n", d->name)); + continue; + } + status = idmap_ad_unixids_to_sids_in_domain(ads,domain,iids); + if (NT_STATUS_IS_OK(status)) + return status; + } + return NT_STATUS_UNSUCCESSFUL; +} + +/************************************************************************ +***********************************************************************/ static NTSTATUS idmap_ad_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids) { @@ -510,11 +634,7 @@ return NT_STATUS_NO_MEMORY; } - if ( (ads = ad_idmap_cached_connection()) == NULL ) { - DEBUG(1, ("ADS uninitialized\n")); - ret = NT_STATUS_UNSUCCESSFUL; - goto done; - } + ads = ad_idmap_cached_connection(ids[idx]->sid); attrs[2] = ad_schema->posix_uidnumber_attr; attrs[3] = ad_schema->posix_gidnumber_attr; @@ -553,7 +673,7 @@ DEBUG(10, ("No IDs found\n")); } - entry = res; + entry = res; for (i = 0; (i < count) && entry; i++) { DOM_SID sid; enum id_type type; @@ -739,7 +859,7 @@ /* We are assuming that the internal ADS_STRUCT is for the same forest as the incoming *ads pointer */ - ads_internal = ad_idmap_cached_connection(); + ads_internal = ad_idmap_cached_connection_orig(); if ( !ads_internal || !ad_schema ) return NT_STATUS_OBJECT_NAME_NOT_FOUND; @@ -809,6 +929,8 @@ /* Always register the AD method first in order to get the idmap_domain interface called */ + DEBUG(1,("idmap_ad 3.0.32: - trial version for the multiple connection patch\n ")); + if ( !NT_STATUS_IS_OK(status_idmap_ad) ) { status_idmap_ad = smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ad", &ad_methods);