summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/trustdom_cache.c124
-rw-r--r--source3/libsmb/trusts_util.c100
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;
}