From b1f4259cd5ecebfe7e4c4eb73aa32e1ed9b366b8 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 1 Mar 2007 03:16:38 +0000 Subject: [PATCH] r21616: Delay initialization of idmap and nss_info backends until necessary so they can honor the offline logon state. (This used to be commit 15b13dfe81e861b94077c94b80117a85a5ffb999) --- source3/nsswitch/idmap.c | 73 +++++++++++++++++++++++++++---- source3/nsswitch/idmap_cache.c | 61 +++++++++++++++++++++----- source3/nsswitch/nss_info.c | 46 ++++++++++++++++--- source3/nsswitch/winbindd.c | 10 ++--- source3/nsswitch/winbindd_async.c | 2 +- source3/nsswitch/winbindd_dual.c | 34 +++++++++++++- 6 files changed, 193 insertions(+), 33 deletions(-) diff --git a/source3/nsswitch/idmap.c b/source3/nsswitch/idmap.c index d69fd68e103..a58959afe4c 100644 --- a/source3/nsswitch/idmap.c +++ b/source3/nsswitch/idmap.c @@ -225,9 +225,36 @@ NTSTATUS idmap_close(void) static const char *idmap_default_domain[] = { "default domain", NULL }; +/**************************************************************************** + ****************************************************************************/ + +NTSTATUS idmap_init_cache(void) +{ + /* Always initialize the cache. We'll have to delay initialization + of backends if we are offline */ + + if ( idmap_ctx ) { + return NT_STATUS_OK; + } + + if ( (idmap_ctx = talloc_named_const(NULL, 0, "idmap_ctx")) == NULL ) { + return NT_STATUS_NO_MEMORY; + } + + if ( (idmap_cache = idmap_cache_init(idmap_ctx)) == NULL ) { + return NT_STATUS_UNSUCCESSFUL; + } + + return NT_STATUS_OK; +} + +/**************************************************************************** + ****************************************************************************/ + NTSTATUS idmap_init(void) { NTSTATUS ret; + static NTSTATUS backend_init_status = NT_STATUS_UNSUCCESSFUL; struct idmap_domain *dom; char *compat_backend = NULL; char *compat_params = NULL; @@ -238,16 +265,23 @@ NTSTATUS idmap_init(void) int compat = 0; int i; - if (idmap_ctx) { - return NT_STATUS_OK; - } + /* Always initialize the cache. We'll have to delay initialization + of backends if we are offline */ - if ( (idmap_ctx = talloc_named_const(NULL, 0, "idmap_ctx")) == NULL ) { - return NT_STATUS_NO_MEMORY; + ret = idmap_init_cache(); + if ( !NT_STATUS_IS_OK(ret) ) + return ret; + + if ( NT_STATUS_IS_OK(backend_init_status) ) { + return NT_STATUS_OK; } + + /* We can't reliably call intialization code here unless + we are online */ - if ( (idmap_cache = idmap_cache_init(idmap_ctx)) == NULL ) { - return NT_STATUS_UNSUCCESSFUL; + if ( get_global_winbindd_state_offline() ) { + backend_init_status = NT_STATUS_FILE_IS_OFFLINE; + return backend_init_status; } static_init_idmap; @@ -559,11 +593,17 @@ NTSTATUS idmap_init(void) /* cleanpu temporary strings */ TALLOC_FREE( compat_backend ); + backend_init_status = NT_STATUS_OK; + return NT_STATUS_OK; done: DEBUG(0, ("Aborting IDMAP Initialization ...\n")); idmap_close(); + + /* save the init status for later checks */ + backend_init_status = ret; + return ret; } @@ -1067,6 +1107,14 @@ NTSTATUS idmap_unixids_to_sids(struct id_map **ids) /* let's see if there is any id mapping to be retieved from the backends */ if (bi) { + /* Only do query if we are online */ + if ( lp_winbind_offline_logon() && + get_global_winbindd_state_offline() ) + { + ret = NT_STATUS_FILE_IS_OFFLINE; + goto done; + } + ret = idmap_backends_unixids_to_sids(bids); IDMAP_CHECK_RET(ret); @@ -1132,7 +1180,8 @@ NTSTATUS idmap_sids_to_unixids(struct id_map **ids) if ( ! NT_STATUS_IS_OK(ret)) { if ( ! bids) { - /* alloc space for ids to be resolved by backends (realloc ten by ten) */ + /* alloc space for ids to be resolved + by backends (realloc ten by ten) */ bids = talloc_array(ctx, struct id_map *, 10); if ( ! bids) { DEBUG(1, ("Out of memory!\n")); @@ -1164,6 +1213,14 @@ NTSTATUS idmap_sids_to_unixids(struct id_map **ids) /* let's see if there is any id mapping to be retieved from the backends */ if (bids) { + /* Only do query if we are online */ + if ( lp_winbind_offline_logon() && + get_global_winbindd_state_offline() ) + { + ret = NT_STATUS_FILE_IS_OFFLINE; + goto done; + } + ret = idmap_backends_sids_to_unixids(bids); IDMAP_CHECK_RET(ret); diff --git a/source3/nsswitch/idmap_cache.c b/source3/nsswitch/idmap_cache.c index 897dd9c4f5b..caf5fe72b3a 100644 --- a/source3/nsswitch/idmap_cache.c +++ b/source3/nsswitch/idmap_cache.c @@ -22,6 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/ #include "includes.h" +#include "winbindd.h" #define TIMEOUT_LEN 12 #define IDMAP_CACHE_DATA_FMT "%12u/%s" @@ -418,14 +419,34 @@ NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id) /* here ret == NT_STATUS_OK and id->status = ID_MAPPED */ if (t <= time(NULL)) { - /* We're expired, set an error code for upper layer */ - ret = NT_STATUS_SYNCHRONIZATION_REQUIRED; + /* If we've been told to be offline - stay in + that state... */ + if (lp_winbind_offline_logon() && + get_global_winbindd_state_offline()) + { + DEBUG(10,("idmap_cache_map_sid: winbindd is " + "globally offline.\n")); + } else { + /* We're expired, set an error code + for upper layer */ + ret = NT_STATUS_SYNCHRONIZATION_REQUIRED; + } } } else { if (t <= time(NULL)) { - /* We're expired, delete the entry and return not mapped */ - tdb_delete(cache->tdb, keybuf); - ret = NT_STATUS_NONE_MAPPED; + /* If we've been told to be offline - stay in + that state... */ + if (lp_winbind_offline_logon() && + get_global_winbindd_state_offline()) + { + DEBUG(10,("idmap_cache_map_sid: winbindd is " + "globally offline.\n")); + } else { + /* We're expired, delete the entry and return + not mapped */ + tdb_delete(cache->tdb, keybuf); + ret = NT_STATUS_NONE_MAPPED; + } } else { /* this is not mapped as it was a negative cache hit */ id->status = ID_UNMAPPED; @@ -508,14 +529,34 @@ NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id) /* here ret == NT_STATUS_OK and id->mapped = True */ if (t <= time(NULL)) { - /* We're expired, set an error code for upper layer */ - ret = NT_STATUS_SYNCHRONIZATION_REQUIRED; + /* If we've been told to be offline - stay in + that state... */ + if (lp_winbind_offline_logon() && + get_global_winbindd_state_offline()) + { + DEBUG(10,("idmap_cache_map_sid: winbindd is " + "globally offline.\n")); + } else { + /* We're expired, set an error code + for upper layer */ + ret = NT_STATUS_SYNCHRONIZATION_REQUIRED; + } } } else { if (t <= time(NULL)) { - /* We're expired, delete the entry and return not mapped */ - tdb_delete(cache->tdb, keybuf); - ret = NT_STATUS_NONE_MAPPED; + /* If we've been told to be offline - stay in + that state... */ + if (lp_winbind_offline_logon() && + get_global_winbindd_state_offline()) + { + DEBUG(10,("idmap_cache_map_sid: winbindd is " + "globally offline.\n")); + } else { + /* We're expired, delete the entry and + return not mapped */ + tdb_delete(cache->tdb, keybuf); + ret = NT_STATUS_NONE_MAPPED; + } } else { /* this is not mapped is it was a negative cache hit */ id->status = ID_UNMAPPED; diff --git a/source3/nsswitch/nss_info.c b/source3/nsswitch/nss_info.c index 0b0caeee022..d2516296629 100644 --- a/source3/nsswitch/nss_info.c +++ b/source3/nsswitch/nss_info.c @@ -131,11 +131,17 @@ static BOOL parse_nss_parm( const char *config, char **backend, char **domain ) NTSTATUS nss_init( const char **nss_list ) { NTSTATUS status; + static NTSTATUS nss_initialized = NT_STATUS_UNSUCCESSFUL; int i; char *backend, *domain; struct nss_function_entry *nss_backend; struct nss_domain_entry *nss_domain; + /* check for previous successful initializations */ + + if ( NT_STATUS_IS_OK(nss_initialized) ) + return NT_STATUS_OK; + /* The "template" backend should alqays be registered as it is a static module */ @@ -207,20 +213,25 @@ static BOOL parse_nss_parm( const char *config, char **backend, char **domain ) } + nss_initialized = NT_STATUS_OK; + return NT_STATUS_OK; } /******************************************************************** *******************************************************************/ - NTSTATUS nss_get_info( const char *domain, const DOM_SID *user_sid, - TALLOC_CTX *ctx, - ADS_STRUCT *ads, LDAPMessage *msg, - char **homedir, char **shell, char **gecos, - gid_t *p_gid) +static struct nss_domain_entry *find_nss_domain( const char *domain ) { + NTSTATUS status; struct nss_domain_entry *p; - struct nss_info_methods *m; + + status = nss_init( lp_winbind_nss_info() ); + if ( !NT_STATUS_IS_OK(status) ) { + DEBUG(4,("nss_get_info: Failed to init nss_info API (%s)!\n", + nt_errstr(status))); + return NULL; + } for ( p=nss_domain_list; p; p=p->next ) { if ( strequal( p->domain, domain ) ) @@ -231,12 +242,33 @@ static BOOL parse_nss_parm( const char *config, char **backend, char **domain ) if ( !p ) { if ( !nss_domain_list ) { - return NT_STATUS_NOT_FOUND; + return NULL; } p = nss_domain_list; } + return p; +} + +/******************************************************************** + *******************************************************************/ + + NTSTATUS nss_get_info( const char *domain, const DOM_SID *user_sid, + TALLOC_CTX *ctx, + ADS_STRUCT *ads, LDAPMessage *msg, + char **homedir, char **shell, char **gecos, + gid_t *p_gid) +{ + struct nss_domain_entry *p; + struct nss_info_methods *m; + + if ( (p = find_nss_domain( domain )) == NULL ) { + DEBUG(4,("nss_get_info: Failed to find nss domain pointer for %s\n", + domain )); + return NT_STATUS_NOT_FOUND; + } + m = p->backend->methods; return m->get_nss_info( p, user_sid, ctx, ads, msg, diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c index ef6d4700ceb..603cfeb85be 100644 --- a/source3/nsswitch/winbindd.c +++ b/source3/nsswitch/winbindd.c @@ -1011,14 +1011,10 @@ int main(int argc, char **argv, char **envp) /* Winbind daemon initialisation */ - if ( ! NT_STATUS_IS_OK(idmap_init()) ) { - DEBUG(1, ("Could not init idmap! - Sid/[UG]id mapping will not be available\n")); + if ( ! NT_STATUS_IS_OK(idmap_init_cache()) ) { + DEBUG(1, ("Could not init idmap cache!\n")); } -#ifdef WITH_ADS - nss_init( lp_winbind_nss_info() ); -#endif - /* Unblock all signals we are interested in as they may have been blocked by the parent process. */ @@ -1047,6 +1043,7 @@ int main(int argc, char **argv, char **envp) pidfile_create("winbindd"); +#if 0 /* not finished yet */ /* Ensure all cache and idmap caches are consistent before we startup. */ @@ -1060,6 +1057,7 @@ int main(int argc, char **argv, char **envp) } return execve(argv[0], argv, envp); } +#endif #if HAVE_SETPGID /* diff --git a/source3/nsswitch/winbindd_async.c b/source3/nsswitch/winbindd_async.c index cafaf1cb056..aa48f513e97 100644 --- a/source3/nsswitch/winbindd_async.c +++ b/source3/nsswitch/winbindd_async.c @@ -535,7 +535,7 @@ void winbindd_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, request.cmd = WINBINDD_DUAL_SID2GID; sid_to_string(request.data.dual_sid2id.sid, sid); - DEBUG(7,("idmap_sid2gid_async: Resolving %s to a gid\n", + DEBUG(7,("winbindd_sid2gid_async: Resolving %s to a gid\n", request.data.dual_sid2id.sid)); do_async(mem_ctx, idmap_child(), &request, winbindd_sid2gid_recv, diff --git a/source3/nsswitch/winbindd_dual.c b/source3/nsswitch/winbindd_dual.c index edb4fa504b1..6324de9a2d9 100644 --- a/source3/nsswitch/winbindd_dual.c +++ b/source3/nsswitch/winbindd_dual.c @@ -502,10 +502,26 @@ void winbind_msg_offline(int msg_type, struct process_id src, } DEBUG(5,("winbind_msg_offline: marking %s offline.\n", domain->name)); set_domain_offline(domain); + + /* Send an offline message to the idmap child when our + primary domain goes offline */ + + if ( domain->primary ) { + struct winbindd_child *idmap = idmap_child(); + + if ( idmap->pid != 0 ) { + message_send_pid(pid_to_procid(idmap->pid), + MSG_WINBIND_OFFLINE, + domain->name, + strlen(domain->name)+1, + False); + } + } } for (child = children; child != NULL; child = child->next) { - /* Don't send message to idmap child. */ + /* Don't send message to idmap child. We've already + done so above. */ if (!child->domain || (child == idmap_child())) { continue; } @@ -556,6 +572,22 @@ void winbind_msg_online(int msg_type, struct process_id src, winbindd_flush_negative_conn_cache(domain); set_domain_online_request(domain); + + /* Send an offline message to the idmap child when our + primary domain goes offline */ + + if ( domain->primary ) { + struct winbindd_child *idmap = idmap_child(); + + if ( idmap->pid != 0 ) { + message_send_pid(pid_to_procid(idmap->pid), + MSG_WINBIND_ONLINE, + domain->name, + strlen(domain->name)+1, + False); + } + + } } for (child = children; child != NULL; child = child->next) { -- 2.34.1