* fix the trustdom_cache to work when winbindd is not running.
authorGerald Carter <jerry@samba.org>
Tue, 1 Jul 2003 03:49:41 +0000 (03:49 +0000)
committerGerald Carter <jerry@samba.org>
Tue, 1 Jul 2003 03:49:41 +0000 (03:49 +0000)
  smbd will update the trustdom_cache periodically after locking
  the timestamp key
(This used to be commit 7bc4b65b91f98271089335cc301146d5f0c76c3a)

source3/Makefile.in
source3/auth/auth_util.c
source3/lib/gencache.c
source3/libsmb/trustdom_cache.c
source3/libsmb/trusts_util.c
source3/nsswitch/wb_client.c

index ab3693146e2cd8cac110c21fe20b6427db86e8c9..7f85619bc2e22b4fc1868cedfb6e9aa9beb365d6 100644 (file)
@@ -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)
index 30510c1bfa685535e2258da28e04a7de7626e85c..5185f876c6e2c5740cc601c1c1cb282838b855e2 100644 (file)
@@ -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();
        
index 40b4d1390dcd8deb6b685efe6bf345f24fb16e9d..58e44e3f0bb8d313c27ca719748fc20426c835b4 100644 (file)
@@ -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;
+}
+
+
index 61b024da43980906c0648096ffa5195379d8c2dc..83781250880ceaf15fe2ce64dc458eccd8da5539 100644 (file)
@@ -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;
+}
index 569b0521be1f70c5f90234fec8ad2c5bf2421585..464a3324c167d69aba5c8bfb57da1f0e362d6b30 100644 (file)
@@ -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;
 }
 
index b1765a8bd7d2852c410056aab947af94fa35646a..196e44020c5216b62411cdfb51eb5a36f8fced97 100644 (file)
@@ -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;
+}
+