diff options
Diffstat (limited to 'source3/libsmb')
-rw-r--r-- | source3/libsmb/trustdom_cache.c | 124 | ||||
-rw-r--r-- | source3/libsmb/trusts_util.c | 100 |
2 files changed, 202 insertions, 22 deletions
diff --git a/source3/libsmb/trustdom_cache.c b/source3/libsmb/trustdom_cache.c index 61b024da43..8378125088 100644 --- a/source3/libsmb/trustdom_cache.c +++ b/source3/libsmb/trustdom_cache.c @@ -26,6 +26,7 @@ #define DBGC_CLASS DBGC_ALL /* there's no proper class yet */ #define TDOMKEY_FMT "TDOM/%s" +#define TDOMTSKEY "TDOMCACHE/TIMESTAMP" /** @@ -186,6 +187,71 @@ BOOL trustdom_cache_fetch(const char* name, DOM_SID* sid) } +/******************************************************************* + fetch the timestamp from the last update +*******************************************************************/ + +uint32 trustdom_cache_fetch_timestamp( void ) +{ + char *value; + time_t timeout; + uint32 timestamp; + + /* init the cache */ + if (!gencache_init()) + return False; + + if (!gencache_get(TDOMTSKEY, &value, &timeout)) { + DEBUG(5, ("no timestamp for trusted domain cache located.\n")); + return 0; + } + + timestamp = atoi(value); + + return timestamp; +} + +/******************************************************************* + store the timestamp from the last update +*******************************************************************/ + +BOOL trustdom_cache_store_timestamp( uint32 t, time_t timeout ) +{ + fstring value; + + /* init the cache */ + if (!gencache_init()) + return False; + + snprintf(value, sizeof(value), "%d", t ); + + if (!gencache_set(TDOMTSKEY, value, timeout)) { + DEBUG(5, ("failed to set timestamp for trustdom_cache\n")); + return False; + } + + return True; +} + + +/******************************************************************* + lock the timestamp entry in the trustdom_cache +*******************************************************************/ + +BOOL trustdom_cache_lock_timestamp( void ) +{ + return gencache_lock_entry( TDOMTSKEY ) != -1; +} + +/******************************************************************* + unlock the timestamp entry in the trustdom_cache +*******************************************************************/ + +void trustdom_cache_unlock_timestamp( void ) +{ + gencache_unlock_entry( TDOMTSKEY ); +} + /** * Delete single trustdom entry. Look at the * gencache_iterate definition. @@ -216,3 +282,61 @@ void trustdom_cache_flush(void) DEBUG(5, ("Trusted domains cache flushed\n")); } +/******************************************************************** + update the trustdom_cache if needed +********************************************************************/ +#define TRUSTDOM_UPDATE_INTERVAL 600 + +void update_trustdom_cache( void ) +{ + char **domain_names; + DOM_SID *dom_sids; + uint32 num_domains; + uint32 last_check; + int time_diff; + TALLOC_CTX *mem_ctx = NULL; + time_t now = time(NULL); + int i; + + /* get the timestamp. We have to initialise it if the last timestamp == 0 */ + + if ( (last_check = trustdom_cache_fetch_timestamp()) == 0 ) + trustdom_cache_store_timestamp(0, now+TRUSTDOM_UPDATE_INTERVAL); + + time_diff = now - last_check; + + if ( (time_diff > 0) && (time_diff < TRUSTDOM_UPDATE_INTERVAL) ) { + DEBUG(10,("update_trustdom_cache: not time to update trustdom_cache yet\n")); + return; + } + + /* lock the timestamp */ + if ( !trustdom_cache_lock_timestamp() ) + return; + + if ( !(mem_ctx = talloc_init("update_trustdom_cache")) ) { + DEBUG(0,("update_trustdom_cache: talloc_init() failed!\n")); + goto done; + } + + /* get the domains and store them */ + + if ( enumerate_domain_trusts(mem_ctx, lp_workgroup(), &domain_names, + &num_domains, &dom_sids) ) + { + for ( i=0; i<num_domains; i++ ) { + trustdom_cache_store( domain_names[i], NULL, &dom_sids[i], + now+TRUSTDOM_UPDATE_INTERVAL); + } + + trustdom_cache_store_timestamp( now, now+TRUSTDOM_UPDATE_INTERVAL ); + } + +done: + /* unlock and we're done */ + trustdom_cache_unlock_timestamp(); + + talloc_destroy( mem_ctx ); + + return; +} diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c index 569b0521be..464a3324c1 100644 --- a/source3/libsmb/trusts_util.c +++ b/source3/libsmb/trusts_util.c @@ -123,6 +123,71 @@ NTSTATUS trust_pw_find_change_and_store_it(struct cli_state *cli, } +/********************************************************************* + Enumerate the list of trusted domains from a DC +*********************************************************************/ + +BOOL enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain, + char ***domain_names, uint32 *num_domains, + DOM_SID **sids ) +{ + POLICY_HND pol; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + fstring dc_name; + struct in_addr dc_ip; + uint32 enum_ctx = 0; + struct cli_state *cli = NULL; + BOOL retry; + + *domain_names = NULL; + *num_domains = 0; + *sids = NULL; + + /* lookup a DC first */ + + if ( !get_dc_name(domain, dc_name, &dc_ip) ) { + DEBUG(3,("enumerate_domain_trusts: can't locate a DC for domain %s\n", + domain)); + return False; + } + + /* setup the anonymous connection */ + + result = cli_full_connection( &cli, global_myname(), dc_name, &dc_ip, 0, "IPC$", "IPC", + "", "", "", 0, &retry); + if ( !NT_STATUS_IS_OK(result) ) + goto done; + + /* open the LSARPC_PIPE */ + + if ( !cli_nt_session_open( cli, PI_LSARPC ) ) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* get a handle */ + + result = cli_lsa_open_policy(cli, mem_ctx, True, + POLICY_VIEW_LOCAL_INFORMATION, &pol); + if ( !NT_STATUS_IS_OK(result) ) + goto done; + + /* Lookup list of trusted domains */ + + result = cli_lsa_enum_trust_dom(cli, mem_ctx, &pol, &enum_ctx, + num_domains, domain_names, sids); + if ( !NT_STATUS_IS_OK(result) ) + goto done; + +done: + /* cleanup */ + + cli_nt_session_close( cli ); + cli_shutdown( cli ); + + return NT_STATUS_IS_OK(result); +} + /** * Verify whether or not given domain is trusted. @@ -139,37 +204,28 @@ BOOL is_trusted_domain(const char* dom_name) time_t lct; BOOL ret; + /* if we are a DC, then check for a direct trust relationships */ + if (lp_server_role() == ROLE_DOMAIN_BDC || lp_server_role() == ROLE_DOMAIN_PDC) { - /* - * Query the secrets db as an ultimate source of information - * about trusted domain names. This is PDC or BDC case. - */ ret = secrets_fetch_trusted_domain_password(dom_name, &pass, &trustdom_sid, &lct); SAFE_FREE(pass); if (ret) - return ret; + return True; } + + /* if winbindd is not up then we need to update the trustdom_cache ourselves */ - /* - * Query the trustdom_cache updated periodically. The only - * way for domain member server. - * - * Sure...it's all fun and games until someone gets hurt... - * This call cannot work without winbindd running since it - * is the only process updating the cache currently. - * - * FIXME!!! make this always true for now until I figure - * out what to do --jerry - */ - - if (True || trustdom_cache_fetch(dom_name, &trustdom_sid)) { + if ( !winbind_ping() ) + update_trustdom_cache(); + + /* now the trustdom cache should be available a DC could still + * have a transitive trust so fall back to the cache of trusted + * domains (like a domain member would use */ + + if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) { return True; } - /* - * if nothing's been found, then give up here, although - * the last resort might be to query the PDC. - */ return False; } |