summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2003-07-01 03:49:41 +0000
committerGerald Carter <jerry@samba.org>2003-07-01 03:49:41 +0000
commit7bc4b65b91f98271089335cc301146d5f0c76c3a (patch)
treee42c9b9b8b429680da20395f81c3e61f3edf7e98
parentdbbd8dd15582f95fb9c160c6c42ce9f0971ac4b7 (diff)
downloadsamba-7bc4b65b91f98271089335cc301146d5f0c76c3a.tar.gz
samba-7bc4b65b91f98271089335cc301146d5f0c76c3a.tar.xz
samba-7bc4b65b91f98271089335cc301146d5f0c76c3a.zip
* fix the trustdom_cache to work when winbindd is not running.
smbd will update the trustdom_cache periodically after locking the timestamp key
-rw-r--r--source/Makefile.in27
-rw-r--r--source/auth/auth_util.c3
-rw-r--r--source/lib/gencache.c21
-rw-r--r--source/libsmb/trustdom_cache.c124
-rw-r--r--source/libsmb/trusts_util.c100
-rw-r--r--source/nsswitch/wb_client.c14
6 files changed, 250 insertions, 39 deletions
diff --git a/source/Makefile.in b/source/Makefile.in
index ab3693146e2..7f85619bc2e 100644
--- a/source/Makefile.in
+++ b/source/Makefile.in
@@ -222,7 +222,6 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \
libsmb/smberr.o libsmb/credentials.o libsmb/pwd_cache.o \
libsmb/clioplock.o libsmb/errormap.o libsmb/clirap2.o \
libsmb/passchange.o libsmb/doserr.o \
- libsmb/trustdom_cache.o \
$(RPC_PARSE_OBJ1) $(LIBSAMBA_OBJ) $(LIBNMB_OBJ)
LIBMSRPC_OBJ = rpc_client/cli_lsarpc.o rpc_client/cli_samr.o \
@@ -232,8 +231,6 @@ LIBMSRPC_OBJ = rpc_client/cli_lsarpc.o rpc_client/cli_samr.o \
rpc_client/cli_spoolss.o rpc_client/cli_spoolss_notify.o \
rpc_client/cli_ds.o rpc_client/cli_echo.o
-LIBMSRPC_SERVER_OBJ = libsmb/trusts_util.o
-
REGOBJS_OBJ = registry/reg_objects.o
REGISTRY_OBJ = registry/reg_frontend.o registry/reg_cachehook.o registry/reg_printing.o \
registry/reg_db.o
@@ -311,6 +308,8 @@ PLAINTEXT_AUTH_OBJ = auth/pampass.o auth/pass_check.o
SLCACHE_OBJ = libsmb/samlogon_cache.o
+DCUTIL_OBJ = libsmb/namequery_dc.o libsmb/trustdom_cache.o libsmb/trusts_util.o
+
AUTH_BUILTIN_OBJ = auth/auth_builtin.o
AUTH_DOMAIN_OBJ = auth/auth_domain.o
AUTH_SAM_OBJ = auth/auth_sam.o
@@ -320,8 +319,8 @@ AUTH_UNIX_OBJ = auth/auth_unix.o
AUTH_WINBIND_OBJ = auth/auth_winbind.o
AUTH_OBJ = auth/auth.o @AUTH_STATIC@ auth/auth_util.o auth/auth_compat.o \
- auth/auth_ntlmssp.o libsmb/namequery_dc.o \
- $(PLAINTEXT_AUTH_OBJ) $(SLCACHE_OBJ)
+ auth/auth_ntlmssp.o \
+ $(PLAINTEXT_AUTH_OBJ) $(SLCACHE_OBJ) $(DCUTIL_OBJ)
MANGLE_OBJ = smbd/mangle.o smbd/mangle_hash.o smbd/mangle_map.o smbd/mangle_hash2.o
@@ -350,7 +349,7 @@ SMBD_OBJ_BASE = $(PARAM_OBJ) $(SMBD_OBJ_SRV) $(MSDFS_OBJ) $(LIBSMB_OBJ) \
$(LOCKING_OBJ) $(PASSDB_OBJ) $(PRINTING_OBJ) $(PROFILE_OBJ) \
$(LIB_OBJ) $(PRINTBACKEND_OBJ) $(OPLOCK_OBJ) \
$(NOTIFY_OBJ) $(GROUPDB_OBJ) $(AUTH_OBJ) \
- $(LIBMSRPC_OBJ) $(LIBMSRPC_SERVER_OBJ) \
+ $(LIBMSRPC_OBJ) \
$(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(LIBADS_SERVER_OBJ) \
$(LIB_SMBD_OBJ) $(REGISTRY_OBJ) $(POPT_LIB_OBJ) $(IDMAP_OBJ) \
$(UBIQX_OBJ) $(BUILDOPT_OBJ) $(SMBLDAP_OBJ)
@@ -436,7 +435,7 @@ RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \
$(RPC_PARSE_OBJ) $(PASSDB_OBJ) $(LIBMSRPC_OBJ) \
$(READLINE_OBJ) $(GROUPDB_OBJ) $(KRBCLIENT_OBJ) \
$(LIBADS_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) \
- $(IDMAP_OBJ) $(SMBLDAP_OBJ)
+ $(IDMAP_OBJ) $(SMBLDAP_OBJ) $(DCUTIL_OBJ)
PAM_WINBIND_OBJ = nsswitch/pam_winbind.po nsswitch/wb_common.po lib/snprintf.po
@@ -482,9 +481,9 @@ NET_OBJ1 = utils/net.o utils/net_ads.o utils/net_ads_cldap.o utils/net_help.o \
NET_OBJ = $(NET_OBJ1) $(PARAM_OBJ) $(SECRETS_OBJ) $(LIBSMB_OBJ) \
$(RPC_PARSE_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
$(KRBCLIENT_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \
- $(LIBMSRPC_OBJ) $(LIBMSRPC_SERVER_OBJ) \
+ $(LIBMSRPC_OBJ) \
$(LIBADS_OBJ) $(LIBADS_SERVER_OBJ) $(POPT_LIB_OBJ) \
- $(IDMAP_OBJ) $(SMBLDAP_OBJ)
+ $(IDMAP_OBJ) $(SMBLDAP_OBJ) $(DCUTIL_OBJ)
CUPS_OBJ = client/smbspool.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) \
$(LIB_OBJ) $(KRBCLIENT_OBJ)
@@ -527,7 +526,7 @@ LOCKTEST2_OBJ = torture/locktest2.o $(PARAM_OBJ) $(LOCKING_OBJ) $(LIBSMB_OBJ) \
SMBCACLS_OBJ = utils/smbcacls.o $(PARAM_OBJ) $(LOCKING_OBJ) $(LIBSMB_OBJ) \
$(KRBCLIENT_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) $(RPC_PARSE_OBJ) \
$(PASSDB_GET_SET_OBJ) $(LIBMSRPC_OBJ) $(SECRETS_OBJ) \
- $(POPT_LIB_OBJ)
+ $(POPT_LIB_OBJ) $(DCUTIL_OBJ) $(LIBADS_OBJ)
SMBCQUOTAS_OBJ = utils/smbcquotas.o $(LOCKING_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
$(PARAM_OBJ) \
@@ -554,7 +553,7 @@ SMBFILTER_OBJ = utils/smbfilter.o $(PARAM_OBJ) $(LIBSMB_OBJ) \
PROTO_OBJ = $(SMBD_OBJ_MAIN) \
$(SMBD_OBJ_SRV) $(NMBD_OBJ1) $(SWAT_OBJ1) $(LIB_OBJ) $(LIBSMB_OBJ) \
$(SMBW_OBJ1) $(SMBWRAPPER_OBJ1) $(SMBTORTURE_OBJ1) $(RPCCLIENT_OBJ1) \
- $(LIBMSRPC_OBJ) $(LIBMSRPC_SERVER_OBJ) $(RPC_CLIENT_OBJ) \
+ $(LIBMSRPC_OBJ) $(RPC_CLIENT_OBJ) \
$(RPC_PIPE_OBJ) $(RPC_PARSE_OBJ) $(KRBCLIENT_OBJ) \
$(AUTH_OBJ) $(PARAM_OBJ) $(LOCKING_OBJ) $(SECRETS_OBJ) \
$(PRINTING_OBJ) $(PRINTBACKEND_OBJ) $(OPLOCK_OBJ) $(NOTIFY_OBJ) \
@@ -595,15 +594,15 @@ WINBINDD_OBJ1 = \
nsswitch/winbindd_rpc.o \
nsswitch/winbindd_ads.o \
nsswitch/winbindd_dual.o \
- nsswitch/winbindd_passdb.o \
- libsmb/namequery_dc.o
+ nsswitch/winbindd_passdb.o
WINBINDD_OBJ = \
$(WINBINDD_OBJ1) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
$(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \
$(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) \
$(PROFILE_OBJ) $(SLCACHE_OBJ) $(IDMAP_OBJ) $(SMBLDAP_OBJ) \
- $(SECRETS_OBJ) $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ)
+ $(SECRETS_OBJ) $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ) \
+ $(DCUTIL_OBJ)
WBINFO_OBJ = nsswitch/wbinfo.o $(LIBSAMBA_OBJ) $(PARAM_OBJ) $(LIB_OBJ) \
$(UBIQX_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ)
diff --git a/source/auth/auth_util.c b/source/auth/auth_util.c
index 30510c1bfa6..5185f876c6e 100644
--- a/source/auth/auth_util.c
+++ b/source/auth/auth_util.c
@@ -216,9 +216,6 @@ NTSTATUS make_user_info_map(auth_usersupplied_info **user_info,
/* do what win2k does. Always map unknown domains to our own
and let the "passdb backend" handle unknown users */
- /* FIXME!!!! grr...this is a broken check currently since is_trusted_domain()
- is useless without winbindd --jerry */
-
if ( !is_trusted_domain(domain) )
domain = get_global_sam_name();
diff --git a/source/lib/gencache.c b/source/lib/gencache.c
index 40b4d1390dc..58e44e3f0bb 100644
--- a/source/lib/gencache.c
+++ b/source/lib/gencache.c
@@ -347,3 +347,24 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time
tdb_search_list_free(first_node);
}
+
+/********************************************************************
+ lock a key
+********************************************************************/
+
+int gencache_lock_entry( const char *key )
+{
+ return tdb_lock_bystring(cache, key, 0);
+}
+
+/********************************************************************
+ unlock a key
+********************************************************************/
+
+void gencache_unlock_entry( const char *key )
+{
+ tdb_unlock_bystring(cache, key);
+ return;
+}
+
+
diff --git a/source/libsmb/trustdom_cache.c b/source/libsmb/trustdom_cache.c
index 61b024da439..83781250880 100644
--- a/source/libsmb/trustdom_cache.c
+++ b/source/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/source/libsmb/trusts_util.c b/source/libsmb/trusts_util.c
index 569b0521be1..464a3324c16 100644
--- a/source/libsmb/trusts_util.c
+++ b/source/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;
}
diff --git a/source/nsswitch/wb_client.c b/source/nsswitch/wb_client.c
index b1765a8bd7d..196e44020c5 100644
--- a/source/nsswitch/wb_client.c
+++ b/source/nsswitch/wb_client.c
@@ -283,3 +283,17 @@ int winbind_getgroups(const char *user, gid_t **list)
return wb_getgroups(user, list);
}
+
+/**********************************************************************
+ simple wrapper function to see if winbindd is alive
+**********************************************************************/
+
+BOOL winbind_ping( void )
+{
+ NSS_STATUS result;
+
+ result = winbindd_request(WINBINDD_PING, NULL, NULL);
+
+ return result == NSS_STATUS_SUCCESS;
+}
+