diff options
author | Gerald Carter <jerry@samba.org> | 2003-07-01 03:49:41 +0000 |
---|---|---|
committer | Gerald Carter <jerry@samba.org> | 2003-07-01 03:49:41 +0000 |
commit | 7bc4b65b91f98271089335cc301146d5f0c76c3a (patch) | |
tree | e42c9b9b8b429680da20395f81c3e61f3edf7e98 | |
parent | dbbd8dd15582f95fb9c160c6c42ce9f0971ac4b7 (diff) | |
download | samba-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.in | 27 | ||||
-rw-r--r-- | source/auth/auth_util.c | 3 | ||||
-rw-r--r-- | source/lib/gencache.c | 21 | ||||
-rw-r--r-- | source/libsmb/trustdom_cache.c | 124 | ||||
-rw-r--r-- | source/libsmb/trusts_util.c | 100 | ||||
-rw-r--r-- | source/nsswitch/wb_client.c | 14 |
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; +} + |