summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2007-03-01 03:16:38 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:18:18 -0500
commitb1f4259cd5ecebfe7e4c4eb73aa32e1ed9b366b8 (patch)
tree8c49ed786823f88b9a0bce54eb848d316159f34f
parent6fb6adba274f6473e4247a5e30d1e496873077a9 (diff)
downloadsamba-b1f4259cd5ecebfe7e4c4eb73aa32e1ed9b366b8.tar.gz
samba-b1f4259cd5ecebfe7e4c4eb73aa32e1ed9b366b8.tar.bz2
samba-b1f4259cd5ecebfe7e4c4eb73aa32e1ed9b366b8.zip
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)
-rw-r--r--source3/nsswitch/idmap.c73
-rw-r--r--source3/nsswitch/idmap_cache.c61
-rw-r--r--source3/nsswitch/nss_info.c46
-rw-r--r--source3/nsswitch/winbindd.c10
-rw-r--r--source3/nsswitch/winbindd_async.c2
-rw-r--r--source3/nsswitch/winbindd_dual.c34
6 files changed, 193 insertions, 33 deletions
diff --git a/source3/nsswitch/idmap.c b/source3/nsswitch/idmap.c
index d69fd68e10..a58959afe4 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 897dd9c4f5..caf5fe72b3 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 0b0caeee02..d251629662 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 ef6d4700ce..603cfeb85b 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 cafaf1cb05..aa48f513e9 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 edb4fa504b..6324de9a2d 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) {