--- samba-3.2.2/source/winbindd/idmap_ad.c 2008-08-19 08:20:10.000000000 +0200 +++ samba-3.2.2-patched/source/winbindd/idmap_ad.c 2008-09-05 15:16:11.000000000 +0200 @@ -25,6 +25,7 @@ */ #include "includes.h" +#include "winbindd.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_IDMAP @@ -54,6 +55,81 @@ /************************************************************************ ***********************************************************************/ +static ADS_STRUCT *ad_idmap_new_cached_connection(struct winbindd_domain *domain) +{ + ADS_STRUCT *ads; + ADS_STATUS status; + fstring dc_name; + struct sockaddr_storage dc_ip; + + DEBUG(10,("ads_cached_connection\n")); + + SMB_ASSERT(domain->private_data == NULL); + + /* we don't want this to affect the users ccache */ + 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); +} + +/************************************************************************ + ***********************************************************************/ + static ADS_STRUCT *ad_idmap_cached_connection_internal(void) { ADS_STRUCT *ads; @@ -63,7 +139,7 @@ struct sockaddr_storage dc_ip; if (ad_idmap_ads != NULL) { - + time_t expire; time_t now = time(NULL); @@ -72,8 +148,7 @@ 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 %d)\n", (uint32)expire-(uint32)now, (uint32) expire, (uint32) now)); if ( ads->config.realm && (expire > time(NULL))) { return ads; @@ -84,7 +159,7 @@ ads_destroy( &ads ); ads_kdestroy(WINBIND_CCACHE_NAME); ad_idmap_ads = NULL; - TALLOC_FREE( ad_schema ); + TALLOC_FREE( ad_schema ); } } @@ -106,9 +181,8 @@ ads->auth.realm = SMB_STRDUP(lp_realm()); /* 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")); @@ -126,7 +200,7 @@ /************************************************************************ ***********************************************************************/ -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(); @@ -160,6 +234,32 @@ /************************************************************************ ***********************************************************************/ +//DIFF: 3.0.32 <-> 3.2.2 : '[const] DOM_SID *sid' +static ADS_STRUCT *ad_idmap_cached_connection(DOM_SID *sid) +{ + struct winbindd_domain *d; + ADS_STRUCT *ads = NULL; + + d = find_domain_from_sid(sid); + + if (d == NULL) { + //DIFF: 3.0.32 <-> 3.2.2: + // sid_string_static -> sid_string_dbg + DEBUG(1,("Tried to find connection to unknown domain [%s]\n", sid_string_dbg(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; @@ -250,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 */ @@ -292,11 +392,11 @@ 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; - } + } attrs[2] = ad_schema->posix_uidnumber_attr; attrs[3] = ad_schema->posix_gidnumber_attr; @@ -470,6 +570,30 @@ /************************************************************************ ***********************************************************************/ +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) { NTSTATUS ret; @@ -511,11 +635,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; @@ -737,6 +857,7 @@ /************************************************************************ ***********************************************************************/ + static NTSTATUS nss_ad_get_info( struct nss_domain_entry *e, const DOM_SID *sid, TALLOC_CTX *ctx, @@ -757,7 +878,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; @@ -835,6 +956,8 @@ /* Always register the AD method first in order to get the idmap_domain interface called */ + DEBUG(1,("idmap_ad 3.2.2 : trial version for the multiple connection patch")); + if ( !NT_STATUS_IS_OK(status_idmap_ad) ) { status_idmap_ad = smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ad", &ad_methods);