rpms/samba/devel samba3_idmap_offline.patch, NONE, 1.1 samba.spec, 1.109, 1.110

fedora-cvs-commits at redhat.com fedora-cvs-commits at redhat.com
Wed Apr 18 14:52:05 UTC 2007


Author: ssorce

Update of /cvs/dist/rpms/samba/devel
In directory cvs.devel.redhat.com:/tmp/cvs-serv31719

Modified Files:
	samba.spec 
Added Files:
	samba3_idmap_offline.patch 
Log Message:

offline patch (experimental)



samba3_idmap_offline.patch:
 include/idmap.h         |    4 
 include/smb.h           |    3 
 nsswitch/idmap.c        |  244 ++++++++++++++++++++++++++++--------------------
 nsswitch/idmap_ad.c     |   43 ++++++--
 nsswitch/idmap_cache.c  |  118 +++++++++--------------
 nsswitch/idmap_ldap.c   |   95 ++++++++++++++----
 nsswitch/idmap_nss.c    |    3 
 nsswitch/idmap_passdb.c |    3 
 nsswitch/idmap_tdb.c    |   43 ++++++++
 9 files changed, 351 insertions(+), 205 deletions(-)

--- NEW FILE samba3_idmap_offline.patch ---
Index: source/nsswitch/idmap_cache.c
===================================================================
--- source/nsswitch/idmap_cache.c	(revision 22320)
+++ source/nsswitch/idmap_cache.c	(working copy)
@@ -365,7 +365,7 @@
 
 /* search the cahce for the SID an return a mapping if found *
  *
- * 3 cases are possible
+ * 4 cases are possible
  *
  * 1 map found
  * 	in this case id->status = ID_MAPPED and NT_STATUS_OK is returned
@@ -373,21 +373,20 @@
  * 	in this case id->status = ID_UNKNOWN and NT_STATUS_NONE_MAPPED is returned
  * 3 negative cache found
  * 	in this case id->status = ID_UNMAPPED and NT_STATUS_OK is returned
- *
- * As a special case if the cache is expired NT_STATUS_SYNCHRONIZATION_REQUIRED
- * is returned instead of NT_STATUS_OK. In this case revalidation of the cache
- * is needed.
+ * 4 map found but timer expired
+ *      in this case id->status = ID_EXPIRED and NT_STATUS_SYNCHRONIZATION_REQUIRED
+ *      is returned. In this case revalidation of the cache is needed.
  */
 
 NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id)
 {
 	NTSTATUS ret;
 	TDB_DATA keybuf, databuf;
-	time_t t;
+	time_t t, now;
 	char *sidkey;
 	char *endptr;
 
-	/* make sure it is marked as not mapped by default */
+	/* make sure it is marked as unknown by default */
 	id->status = ID_UNKNOWN;
 	
 	ret = idmap_cache_build_sidkey(cache, &sidkey, id);
@@ -413,11 +412,13 @@
 		goto done;
 	}
 
+	now = time(NULL);
+
 	/* check it is not negative */
 	if (strcmp("IDMAP/NEGATIVE", endptr+1) != 0) {
-		
+
 		DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, "
-			   "timeout = %s", t > time(NULL) ? "valid" :
+			   "timeout = %s", t > now ? "valid" :
 			   "expired", sidkey, endptr+1, ctime(&t)));
 
 		/* this call if successful will also mark the entry as mapped */
@@ -431,35 +432,21 @@
 
 		/* here ret == NT_STATUS_OK and id->status = ID_MAPPED */
 
-		if (t <= time(NULL)) {
-			/* 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;
-			}			
+		if (t <= now) {
+	
+			/* we have it, but it is expired */
+			id->status = ID_EXPIRED;
+				
+			/* We're expired, set an error code
+			   for upper layer */
+			ret = NT_STATUS_SYNCHRONIZATION_REQUIRED;
 		}
 	} else {
-		if (t <= time(NULL)) {
-			/* 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;
-			}			
+		if (t <= now) {
+			/* We're expired, delete the NEGATIVE 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;
@@ -483,21 +470,20 @@
  * 	in this case id->status = ID_UNKNOWN and NT_STATUS_NONE_MAPPED is returned
  * 3 negative cache found
  * 	in this case id->status = ID_UNMAPPED and NT_STATUS_OK is returned
- *
- * As a special case if the cache is expired NT_STATUS_SYNCHRONIZATION_REQUIRED
- * is returned instead of NT_STATUS_OK. In this case revalidation of the cache
- * is needed.
+ * 4 map found but timer expired
+ *      in this case id->status = ID_EXPIRED and NT_STATUS_SYNCHRONIZATION_REQUIRED
+ *      is returned. In this case revalidation of the cache is needed.
  */
 
 NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id)
 {
 	NTSTATUS ret;
 	TDB_DATA keybuf, databuf;
-	time_t t;
+	time_t t, now;
 	char *idkey;
 	char *endptr;
 
-	/* make sure it is marked as not mapped by default */
+	/* make sure it is marked as unknown by default */
 	id->status = ID_UNKNOWN;
 	
 	ret = idmap_cache_build_idkey(cache, &idkey, id);
@@ -523,11 +509,13 @@
 		goto done;
 	}
 
+	now = time(NULL);
+
 	/* check it is not negative */
 	if (strcmp("IDMAP/NEGATIVE", endptr+1) != 0) {
 		
 		DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, "
-			   "timeout = %s", t > time(NULL) ? "valid" :
+			   "timeout = %s", t > now ? "valid" :
 			   "expired", idkey, endptr+1, ctime(&t)));
 
 		/* this call if successful will also mark the entry as mapped */
@@ -539,39 +527,25 @@
 			goto done;
 		}
 
-		/* here ret == NT_STATUS_OK and id->mapped = True */
+		/* here ret == NT_STATUS_OK and id->mapped = ID_MAPPED */
 
-		if (t <= time(NULL)) {
-			/* 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;
-			}			
+		if (t <= now) {
+
+			/* we have it, but it is expired */
+			id->status = ID_EXPIRED;
+
+			/* We're expired, set an error code
+			   for upper layer */
+			ret = NT_STATUS_SYNCHRONIZATION_REQUIRED;
 		}
 	} else {
-		if (t <= time(NULL)) {
-			/* 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;
-			}			
+		if (t <= now) {
+			/* We're expired, delete the NEGATIVE 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 */
+			/* this is not mapped as it was a negative cache hit */
 			id->status = ID_UNMAPPED;
 			ret = NT_STATUS_OK;
 		}
Index: source/nsswitch/idmap_passdb.c
===================================================================
--- source/nsswitch/idmap_passdb.c	(revision 22320)
+++ source/nsswitch/idmap_passdb.c	(working copy)
@@ -29,8 +29,9 @@
  Initialise idmap database. 
 *****************************/
 
-static NTSTATUS idmap_pdb_init(struct idmap_domain *dom, const char *compat_params)
+static NTSTATUS idmap_pdb_init(struct idmap_domain *dom)
 {	
+	dom->initialized = True;
 	return NT_STATUS_OK;
 }
 
Index: source/nsswitch/idmap_ad.c
===================================================================
--- source/nsswitch/idmap_ad.c	(revision 22320)
+++ source/nsswitch/idmap_ad.c	(working copy)
@@ -160,7 +160,7 @@
 /************************************************************************
  ***********************************************************************/
 
-static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom, const char *params)
+static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom)
 {
 	struct idmap_ad_context *ctx;
 	char *config_option;
@@ -204,6 +204,7 @@
 	}
 
 	dom->private_data = ctx;
+	dom->initialized = True;
 
 	talloc_free(config_option);
 
@@ -269,6 +270,19 @@
 	char *u_filter = NULL;
 	char *g_filter = NULL;
 
+	/* Only do query if we are online */
+	if (idmap_is_offline())	{
+		return NT_STATUS_FILE_IS_OFFLINE;
+	}
+
+	/* Initilization my have been deferred because we were offline */
+	if ( ! dom->initialized) {
+		ret = idmap_ad_initialize(dom);
+		if ( ! NT_STATUS_IS_OK(ret)) {
+			return ret;
+		}
+	}
+
 	ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
 
 	if ( (memctx = talloc_new(ctx)) == NULL ) {
@@ -320,7 +334,7 @@
 			break;
 
 		default:
-			DEBUG(3, ("Unknown ID type\n"));
+			DEBUG(3, ("Error: mapping requested but Unknown ID type\n"));
 			ids[idx]->status = ID_UNKNOWN;
 			continue;
 		}
@@ -441,9 +455,9 @@
 
 	ret = NT_STATUS_OK;
 
-	/* mark all unknown ones as unmapped */
+	/* mark all unknown/expired ones as unmapped */
 	for (i = 0; ids[i]; i++) {
-		if (ids[i]->status == ID_UNKNOWN) 
+		if (ids[i]->status != ID_MAPPED) 
 			ids[i]->status = ID_UNMAPPED;
 	}
 
@@ -476,6 +490,19 @@
 	int i;
 	char *sidstr;
 
+	/* Only do query if we are online */
+	if (idmap_is_offline())	{
+		return NT_STATUS_FILE_IS_OFFLINE;
+	}
+
+	/* Initilization my have been deferred because we were offline */
+	if ( ! dom->initialized) {
+		ret = idmap_ad_initialize(dom);
+		if ( ! NT_STATUS_IS_OK(ret)) {
+			return ret;
+		}
+	}
+
 	ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);	
 
 	if ( (memctx = talloc_new(ctx)) == NULL ) {		
@@ -615,9 +642,9 @@
 
 	ret = NT_STATUS_OK;
 
-	/* mark all unknwon ones as unmapped */
+	/* mark all unknwoni/expired ones as unmapped */
 	for (i = 0; ids[i]; i++) {
-		if (ids[i]->status == ID_UNKNOWN) 
+		if (ids[i]->status != ID_MAPPED) 
 			ids[i]->status = ID_UNMAPPED;
 	}
 
@@ -669,7 +696,7 @@
 	ad_map_type =  WB_POSIX_MAP_SFU;	
 
 	if ( !ad_idmap_ads ) 
-		return idmap_ad_initialize( NULL, NULL );	
+		return idmap_ad_initialize(NULL);
 
 	return NT_STATUS_OK;
 }
@@ -690,7 +717,7 @@
 	ad_map_type =  WB_POSIX_MAP_RFC2307;
 
 	if ( !ad_idmap_ads ) 
-		return idmap_ad_initialize( NULL, NULL );	
+		return idmap_ad_initialize(NULL);	
 
 	return NT_STATUS_OK;
 }
Index: source/nsswitch/idmap_nss.c
===================================================================
--- source/nsswitch/idmap_nss.c	(revision 22320)
+++ source/nsswitch/idmap_nss.c	(working copy)
@@ -30,8 +30,9 @@
  Initialise idmap database. 
 *****************************/
 
-static NTSTATUS idmap_nss_int_init(struct idmap_domain *dom, const char *compat_params)
+static NTSTATUS idmap_nss_int_init(struct idmap_domain *dom)
 {	
+	dom->initialized = True;
 	return NT_STATUS_OK;
 }
 
Index: source/nsswitch/idmap_tdb.c
===================================================================
--- source/nsswitch/idmap_tdb.c	(revision 22320)
+++ source/nsswitch/idmap_tdb.c	(working copy)
@@ -611,7 +611,7 @@
  Initialise idmap database. 
 *****************************/
 
-static NTSTATUS idmap_tdb_db_init(struct idmap_domain *dom, const char *compat_params)
+static NTSTATUS idmap_tdb_db_init(struct idmap_domain *dom)
 {
 	NTSTATUS ret;
 	struct idmap_tdb_context *ctx;
@@ -645,6 +645,7 @@
 	}
 
 	dom->private_data = ctx;
+	dom->initialized = True;
 
 	talloc_free(config_option);
 	return NT_STATUS_OK;
@@ -799,6 +800,14 @@
 	NTSTATUS ret;
 	int i;
 
+	/* make sure we initialized */
+	if ( ! dom->initialized) {
+		ret = idmap_tdb_db_init(dom);
+		if ( ! NT_STATUS_IS_OK(ret)) {
+			return ret;
+		}
+	}
+
 	ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
 
 	for (i = 0; ids[i]; i++) {
@@ -837,6 +846,14 @@
 	NTSTATUS ret;
 	int i;
 
+	/* make sure we initialized */
+	if ( ! dom->initialized) {
+		ret = idmap_tdb_db_init(dom);
+		if ( ! NT_STATUS_IS_OK(ret)) {
+			return ret;
+		}
+	}
+
 	ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
 
 	for (i = 0; ids[i]; i++) {
@@ -875,6 +892,14 @@
 	NTSTATUS ret;
 	TDB_DATA ksid, kid, data;
 
+	/* make sure we initialized */
+	if ( ! dom->initialized) {
+		ret = idmap_tdb_db_init(dom);
+		if ( ! NT_STATUS_IS_OK(ret)) {
+			return ret;
+		}
+	}
+
 	if (!map || !map->sid) {
 		return NT_STATUS_INVALID_PARAMETER;
 	}
@@ -978,6 +1003,14 @@
 	NTSTATUS ret;
 	TDB_DATA ksid, kid, data;
 
+	/* make sure we initialized */
+	if ( ! dom->initialized) {
+		ret = idmap_tdb_db_init(dom);
+		if ( ! NT_STATUS_IS_OK(ret)) {
+			return ret;
+		}
+	}
+
 	if (!map || !map->sid) {
 		return NT_STATUS_INVALID_PARAMETER;
 	}
@@ -1155,6 +1188,14 @@
 	struct dump_data *data;
 	NTSTATUS ret = NT_STATUS_OK;
 
+	/* make sure we initialized */
+	if ( ! dom->initialized) {
+		ret = idmap_tdb_db_init(dom);
+		if ( ! NT_STATUS_IS_OK(ret)) {
+			return ret;
+		}
+	}
+
 	ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
 
 	data = talloc_zero(ctx, struct dump_data);
Index: source/nsswitch/idmap.c
===================================================================
--- source/nsswitch/idmap.c	(revision 22320)
+++ source/nsswitch/idmap.c	(working copy)
@@ -43,6 +43,12 @@
 
 struct idmap_cache_ctx;
 
+struct idmap_alloc_context {
+	const char *params;
+	struct idmap_alloc_methods *methods;
+	BOOL initialized;
+};
+
 static TALLOC_CTX *idmap_ctx = NULL;
 static struct idmap_cache_ctx *idmap_cache;
 
@@ -53,9 +59,10 @@
 static int def_dom_num = -1;
 
 static struct idmap_alloc_backend *alloc_backends = NULL;
-static struct idmap_alloc_methods *alloc_methods = NULL;
+static struct idmap_alloc_context *idmap_alloc_ctx = NULL;
 
 #define IDMAP_CHECK_RET(ret) do { if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(2, ("ERROR: NTSTATUS = 0x%08x\n", NT_STATUS_V(ret))); goto done; } } while(0)
+#define IDMAP_REPORT_RET(ret) do { if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(2, ("ERROR: NTSTATUS = 0x%08x\n", NT_STATUS_V(ret))); } } while(0)
 #define IDMAP_CHECK_ALLOC(mem) do { if (!mem) { DEBUG(0, ("Out of memory!\n")); ret = NT_STATUS_NO_MEMORY; goto done; } } while(0)
 
 static struct idmap_methods *get_methods(struct idmap_backend *be, const char *name)
@@ -102,6 +109,12 @@
 	idmap_in_own_child = True;
 }
 
+BOOL idmap_is_offline(void)
+{
+	return ( lp_winbind_offline_logon() &&
+	     get_global_winbindd_state_offline() );
+}
+
 /**********************************************************************
  Allow a module to register itself as a method.
 **********************************************************************/
@@ -221,9 +234,9 @@
 NTSTATUS idmap_close(void)
 {
 	/* close the alloc backend first before freeing idmap_ctx */
-	if (alloc_methods) {
-		alloc_methods->close_fn();
-		alloc_methods = NULL;
+	if (idmap_alloc_ctx) {
+		idmap_alloc_ctx->methods->close_fn();
+		idmap_alloc_ctx->methods = NULL;
 	}
 	alloc_backends = NULL;
 
@@ -272,7 +285,7 @@
 NTSTATUS idmap_init(void)
 {	
 	NTSTATUS ret;
-	static NTSTATUS backend_init_status = NT_STATUS_UNSUCCESSFUL;	
+	static NTSTATUS idmap_init_status = NT_STATUS_UNSUCCESSFUL;
 	struct idmap_domain *dom;
 	char *compat_backend = NULL;
 	char *compat_params = NULL;
@@ -283,25 +296,13 @@
 	int compat = 0;
 	int i;
 
-	/* Always initialize the cache.  We'll have to delay initialization
-	   of backends if we are offline */
-
 	ret = idmap_init_cache();
 	if ( !NT_STATUS_IS_OK(ret) )
 		return ret;
 
-	if ( NT_STATUS_IS_OK(backend_init_status) ) {
+	if (NT_STATUS_IS_OK(idmap_init_status))
 		return NT_STATUS_OK;
-	}
-	
-	/* We can't reliably call intialization code here unless 
-	   we are online */
 
-	if ( get_global_winbindd_state_offline() ) {
-		backend_init_status = NT_STATUS_FILE_IS_OFFLINE;
-		return backend_init_status;		
-	}
-
 	static_init_idmap;
 
 	dom_list = lp_idmap_domains();
@@ -432,13 +433,18 @@
 		/* now that we have methods, set the destructor for this domain */
 		talloc_set_destructor(dom, close_domain_destructor);
 
+		if (compat_params) {
+			dom->params = talloc_strdup(dom, compat_params);
+			IDMAP_CHECK_ALLOC(dom->params);
+		} else {
+			dom->params = NULL;
+		}
+
 		/* Finally instance a backend copy for this domain */
-		ret = dom->methods->init(dom, compat_params);
+		ret = dom->methods->init(dom);
 		if ( ! NT_STATUS_IS_OK(ret)) {
-			DEBUG(0, ("ERROR: Initialization failed for backend %s (domain %s)\n",
+			DEBUG(0, ("ERROR: Initialization failed for backend %s (domain %s), deferred!\n",
 						parm_backend, dom->name));
-			ret = NT_STATUS_UNSUCCESSFUL;
-			goto done;
 		}
 		idmap_domains = talloc_realloc(idmap_ctx, idmap_domains, struct idmap_domain *, i+1);
 		if ( ! idmap_domains) {
@@ -489,8 +495,15 @@
 		/* now that we have methods, set the destructor for this domain */
 		talloc_set_destructor(dom, close_domain_destructor);
 
+		if (compat_params) {
+			dom->params = talloc_strdup(dom, compat_params);
+			IDMAP_CHECK_ALLOC(dom->params);
+		} else {
+			dom->params = NULL;
+		}
+
 		/* Finally instance a backend copy for this domain */
-		ret = dom->methods->init(dom, compat_params);
+		ret = dom->methods->init(dom);
 		if ( ! NT_STATUS_IS_OK(ret)) {
 			DEBUG(0, ("ERROR: Initialization failed for idmap_nss ?!\n"));
 			ret = NT_STATUS_UNSUCCESSFUL;
@@ -533,8 +546,15 @@
 	/* now that we have methods, set the destructor for this domain */
 	talloc_set_destructor(dom, close_domain_destructor);
 
+	if (compat_params) {
+		dom->params = talloc_strdup(dom, compat_params);
+		IDMAP_CHECK_ALLOC(dom->params);
+	} else {
+		dom->params = NULL;
+	}
+
 	/* Finally instance a backend copy for this domain */
-	ret = dom->methods->init(dom, compat_params);
+	ret = dom->methods->init(dom);
 	if ( ! NT_STATUS_IS_OK(ret)) {
 		DEBUG(0, ("ERROR: Initialization failed for idmap_passdb ?!\n"));
 		ret = NT_STATUS_UNSUCCESSFUL;
@@ -595,50 +615,86 @@
 	}
 
 	if ( alloc_backend ) {
+		
+		idmap_alloc_ctx = talloc_zero(idmap_ctx, struct idmap_alloc_context);
+		IDMAP_CHECK_ALLOC(idmap_alloc_ctx);
 
-		alloc_methods = get_alloc_methods(alloc_backends, alloc_backend);
-		if ( ! alloc_methods) {
+		idmap_alloc_ctx->methods = get_alloc_methods(alloc_backends, alloc_backend);
+		if ( ! idmap_alloc_ctx->methods) {
 			ret = smb_probe_module("idmap", alloc_backend);
 			if (NT_STATUS_IS_OK(ret)) {
-				alloc_methods = get_alloc_methods(alloc_backends, alloc_backend);
+				idmap_alloc_ctx->methods = get_alloc_methods(alloc_backends, alloc_backend);
 			}
 		}
-		if ( alloc_methods) {
-			ret = alloc_methods->init(compat_params);
+		if (idmap_alloc_ctx->methods) {
+
+			if (compat_params) {
+				idmap_alloc_ctx->params = talloc_strdup(idmap_alloc_ctx, compat_params);
+				IDMAP_CHECK_ALLOC(idmap_alloc_ctx->params);
+			} else {
+				idmap_alloc_ctx->params = NULL;
+			}
+
+			ret = idmap_alloc_ctx->methods->init(idmap_alloc_ctx->params);
 			if ( ! NT_STATUS_IS_OK(ret)) {
-				DEBUG(0, ("idmap_init: Initialization failed for alloc "
-					  "backend %s\n", alloc_backend));
-				ret = NT_STATUS_UNSUCCESSFUL;
-				goto done;
-		}
+				DEBUG(0, ("ERROR: Initialization failed for alloc "
+					  "backend %s, deferred!\n", alloc_backend));
+			} else {
+				idmap_alloc_ctx->initialized = True;
+			}
 		} else {
 			DEBUG(2, ("idmap_init: Unable to get methods for alloc backend %s\n", 
 				  alloc_backend));
 			/* certain compat backends are just readonly */
-			if ( compat )
+			if ( compat ) {
+				TALLOC_FREE(idmap_alloc_ctx);
 				ret = NT_STATUS_OK;
-			else
+			} else {
 				ret = NT_STATUS_UNSUCCESSFUL;
+			}
 		}
 	}
 	
 	/* cleanpu temporary strings */
 	TALLOC_FREE( compat_backend );
+
+	idmap_init_status = NT_STATUS_OK;
 	
-	backend_init_status = NT_STATUS_OK;
-	
 	return ret;
 
 done:
 	DEBUG(0, ("Aborting IDMAP Initialization ...\n"));
 	idmap_close();
 
-	/* save the init status for later checks */
-	backend_init_status = ret;
-	
 	return ret;
 }
 
+static NTSTATUS idmap_alloc_init(void)
+{
+	NTSTATUS ret;
+
+	if (! NT_STATUS_IS_OK(ret = idmap_init())) {
+		return ret;
+	}
+
+	if ( ! idmap_alloc_ctx) {
+		return NT_STATUS_NOT_SUPPORTED;
+	}
+
+	if ( ! idmap_alloc_ctx->initialized) {
+		ret = idmap_alloc_ctx->methods->init(idmap_alloc_ctx->params);
+		if ( ! NT_STATUS_IS_OK(ret)) {
+			DEBUG(0, ("ERROR: Initialization failed for alloc "
+				  "backend, deferred!\n"));
+			return ret;
+		} else {
+			idmap_alloc_ctx->initialized = True;
+		}
+	}
+
+	return NT_STATUS_OK;
+}
+
 /**************************************************************************
  idmap allocator interface functions
 **************************************************************************/
@@ -647,60 +703,48 @@
 {
 	NTSTATUS ret;
 
-	if (! NT_STATUS_IS_OK(ret = idmap_init())) {
+	if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) {
 		return ret;
 	}
 
-	if ( !alloc_methods )
-		return NT_STATUS_NOT_SUPPORTED;	
-
 	id->type = ID_TYPE_UID;
-	return alloc_methods->allocate_id(id);
+	return idmap_alloc_ctx->methods->allocate_id(id);
 }
 
 NTSTATUS idmap_allocate_gid(struct unixid *id)
 {
 	NTSTATUS ret;
 
-	if (! NT_STATUS_IS_OK(ret = idmap_init())) {
+	if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) {
 		return ret;
 	}
 
-	if ( !alloc_methods )
-		return NT_STATUS_NOT_SUPPORTED;	
-
 	id->type = ID_TYPE_GID;
-	return alloc_methods->allocate_id(id);
+	return idmap_alloc_ctx->methods->allocate_id(id);
 }
 
 NTSTATUS idmap_set_uid_hwm(struct unixid *id)
 {
 	NTSTATUS ret;
 
-	if (! NT_STATUS_IS_OK(ret = idmap_init())) {
+	if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) {
 		return ret;
 	}
 
-	if ( !alloc_methods )
-		return NT_STATUS_NOT_SUPPORTED;	
-
 	id->type = ID_TYPE_UID;
-	return alloc_methods->set_id_hwm(id);
+	return idmap_alloc_ctx->methods->set_id_hwm(id);
 }
 
 NTSTATUS idmap_set_gid_hwm(struct unixid *id)
 {
 	NTSTATUS ret;
 
-	if (! NT_STATUS_IS_OK(ret = idmap_init())) {
+	if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) {
 		return ret;
 	}
 
-	if ( !alloc_methods )
-		return NT_STATUS_NOT_SUPPORTED;	
-
 	id->type = ID_TYPE_GID;
-	return alloc_methods->set_id_hwm(id);
+	return idmap_alloc_ctx->methods->set_id_hwm(id);
 }
 
 /******************************************************************************
@@ -815,6 +859,11 @@
 	enum lsa_SidType sid_type;
 	BOOL wbret;
 
+	/* If we are offline we cannot lookup SIDs, deny mapping */
+	if (idmap_is_offline())	{
+		return NT_STATUS_FILE_IS_OFFLINE;
+	}
+
 	ret = idmap_can_map(map, &dom);
 	if ( ! NT_STATUS_IS_OK(ret)) {
 		return NT_STATUS_NONE_MAPPED;
@@ -937,11 +986,6 @@
 
 	_ids = ids;
 
-	/* make sure all maps are marked as in UNKNOWN status */
-	for (i = 0; _ids[i]; i++) {
-		_ids[i]->status = ID_UNKNOWN;
-	}
-
 	unmapped = NULL;
 	for (n = num_domains-1; n >= 0; n--) { /* cycle backwards */
 
@@ -950,12 +994,12 @@
 		DEBUG(10, ("Query sids from domain %s\n", dom->name));
 		
 		ret = dom->methods->unixids_to_sids(dom, _ids);
-		IDMAP_CHECK_RET(ret);
+		IDMAP_REPORT_RET(ret);
 
 		unmapped = NULL;
 
 		for (i = 0, u = 0; _ids[i]; i++) {
-			if (_ids[i]->status == ID_UNKNOWN || _ids[i]->status == ID_UNMAPPED) {
+			if (_ids[i]->status != ID_MAPPED) {
 				unmapped = talloc_realloc(ctx, unmapped, struct id_map *, u + 2);
 				IDMAP_CHECK_ALLOC(unmapped);
 				unmapped[u] = _ids[i];
@@ -975,7 +1019,9 @@
 
 	if (unmapped) {
 		/* there are still unmapped ids, map them to the unix users/groups domains */
+		/* except for expired entries, these will be returned as valid (offline mode) */
 		for (i = 0; unmapped[i]; i++) {
+			if (unmapped[i]->status == ID_EXPIRED) continue;
 			switch (unmapped[i]->xid.type) {
 			case ID_TYPE_UID:
 				uid_to_unix_users_sid((uid_t)unmapped[i]->xid.id, unmapped[i]->sid);
@@ -1025,11 +1071,8 @@
 	for (i = 0; ids[i]; i++) {
 		uint32 idx;		
 
-		/* make sure they are unknown to start off */
-		ids[i]->status = ID_UNKNOWN;
-
 		if ( (dom = find_idmap_domain_from_sid( ids[i]->sid )) == NULL ) {
-			/* no vailable idmap_domain.  Move on */
+			/* no available idmap_domain.  Move on */
 			continue;
 		}
 
@@ -1057,7 +1100,7 @@
 			dom = idmap_domains[i];
 			DEBUG(10, ("Query ids from domain %s\n", dom->name));
 			ret = dom->methods->sids_to_unixids(dom, dom_ids[i]);
-			IDMAP_CHECK_RET(ret);
+			IDMAP_REPORT_RET(ret);
 		}
 	}
 
@@ -1065,6 +1108,8 @@
 	/* let's see if we have any unmapped SID left and act accordingly */
 
 	for (i = 0; ids[i]; i++) {
+		/* NOTE: this will NOT touch ID_EXPIRED entries that the backend
+		 * was not able to confirm/deny (offline mode) */
 		if (ids[i]->status == ID_UNKNOWN || ids[i]->status == ID_UNMAPPED) {
 			/* ok this is an unmapped one, see if we can map it */
 			ret = idmap_new_mapping(ctx, ids[i]);
@@ -1075,7 +1120,8 @@
 				/* could not map it */
 				ids[i]->status = ID_UNMAPPED;
 			} else {
-				/* Something very bad happened down there */
+				/* Something very bad happened down there
+				 * OR we are offline */
 				ids[i]->status = ID_UNKNOWN;
 			}
 		}
@@ -1164,13 +1210,6 @@
 
 	/* 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);
@@ -1179,11 +1218,17 @@
 		for (i = 0; i < bi; i++) {
 			if (bids[i]->status == ID_MAPPED) {
 				ret = idmap_cache_set(idmap_cache, bids[i]);
+			} else if (bids[i]->status == ID_EXPIRED) {
+				/* the cache returned an expired entry and the backend was
+				 * was not able to clear the situation (offline).
+				 * This handles a previous NT_STATUS_SYNCHRONIZATION_REQUIRED
+				 * for disconnected mode, */
+				bids[i]->status = ID_MAPPED;
 			} else if (bids[i]->status == ID_UNKNOWN) {
-				/* return an expired entry in the cache or an unknown */
-				/* this handles a previous NT_STATUS_SYNCHRONIZATION_REQUIRED
-				 * for disconnected mode */
-				idmap_cache_map_id(idmap_cache, ids[i]);
+				/* something bad here. We were not able to handle this for some
+				 * reason, mark it as unmapped and hope next time things will
+				 * settle down. */
+				bids[i]->status = ID_UNMAPPED;
 			} else { /* unmapped */
 				ret = idmap_cache_set_negative_id(idmap_cache, bids[i]);
 			}
@@ -1270,13 +1315,6 @@
 
 	/* 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);
@@ -1285,12 +1323,18 @@
 		for (i = 0; bids[i]; i++) {
 			if (bids[i]->status == ID_MAPPED) {
 				ret = idmap_cache_set(idmap_cache, bids[i]);
+			} else if (bids[i]->status == ID_EXPIRED) {
+				/* the cache returned an expired entry and the backend was
+				 * was not able to clear the situation (offline).
+				 * This handles a previous NT_STATUS_SYNCHRONIZATION_REQUIRED
+				 * for disconnected mode, */
+				bids[i]->status = ID_MAPPED;
 			} else if (bids[i]->status == ID_UNKNOWN) {
-				/* return an expired entry in the cache or an unknown */
-				/* this handles a previous NT_STATUS_SYNCHRONIZATION_REQUIRED
-				 * for disconnected mode */
-				idmap_cache_map_id(idmap_cache, ids[i]);
-			} else {
+				/* something bad here. We were not able to handle this for some
+				 * reason, mark it as unmapped and hope next time things will
+				 * settle down. */
+				bids[i]->status = ID_UNMAPPED;
+			} else { /* unmapped */
 				ret = idmap_cache_set_negative_sid(idmap_cache, bids[i]);
 			}
 			IDMAP_CHECK_RET(ret);
@@ -1362,15 +1406,15 @@
 		return;
 	}
 
-	if ( alloc_methods ) {		
+	if (NT_STATUS_IS_OK(ret = idmap_alloc_init())) {		
 		allid.type = ID_TYPE_UID;
 		allid.id = 0;
-		alloc_methods->get_id_hwm(&allid);
+		idmap_alloc_ctx->methods->get_id_hwm(&allid);
 		fprintf(dump, "USER HWM %lu\n", (unsigned long)allid.id);
 		
 		allid.type = ID_TYPE_GID;
 		allid.id = 0;
-		alloc_methods->get_id_hwm(&allid);
+		idmap_alloc_ctx->methods->get_id_hwm(&allid);
 		fprintf(dump, "GROUP HWM %lu\n", (unsigned long)allid.id);
 	}
 	
Index: source/nsswitch/idmap_ldap.c
===================================================================
--- source/nsswitch/idmap_ldap.c	(revision 22320)
+++ source/nsswitch/idmap_ldap.c	(working copy)
@@ -151,6 +151,7 @@
 				&result);
 
 	if (rc != LDAP_SUCCESS) {
+		DEBUG(1, ("Unable to verify the idpool, cannot continue initialization!\n"));
 		return NT_STATUS_UNSUCCESSFUL;
 	}
 
@@ -209,6 +210,11 @@
 	gid_t low_gid = 0;
 	gid_t high_gid = 0;
 
+	/* Only do init if we are online */
+	if (idmap_is_offline())	{
+		return NT_STATUS_FILE_IS_OFFLINE;
+	}
+
 	idmap_alloc_ldap = talloc_zero(NULL, struct idmap_ldap_alloc_context);
         CHECK_ALLOC_DONE( idmap_alloc_ldap );
 	
@@ -344,6 +350,11 @@
 	const char **attr_list;
 	const char *type;
 
+	/* Only do query if we are online */
+	if (idmap_is_offline())	{
+		return NT_STATUS_FILE_IS_OFFLINE;
+	}
+
 	if ( ! idmap_alloc_ldap) {
 		return NT_STATUS_UNSUCCESSFUL;
 	}
@@ -490,6 +501,11 @@
 	const char **attr_list;
 	const char *type;
 
+	/* Only do query if we are online */
+	if (idmap_is_offline())	{
+		return NT_STATUS_FILE_IS_OFFLINE;
+	}
+
 	if ( ! idmap_alloc_ldap) {
 		return NT_STATUS_UNSUCCESSFUL;
 	}
@@ -580,6 +596,11 @@
 	const char **attr_list;
 	const char *type;
 
+	/* Only do query if we are online */
+	if (idmap_is_offline())	{
+		return NT_STATUS_FILE_IS_OFFLINE;
+	}
+
 	if ( ! idmap_alloc_ldap) {
 		return NT_STATUS_UNSUCCESSFUL;
 	}
@@ -700,14 +721,19 @@
  Initialise idmap database. 
 ********************************/
 
-static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom, const char *params)
+static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom)
 {
 	NTSTATUS ret;
 	struct idmap_ldap_context *ctx = NULL;
 	char *config_option = NULL;
 	const char *range = NULL;
 	const char *tmp = NULL;
-	
+
+	/* Only do init if we are online */
+	if (idmap_is_offline())	{
+		return NT_STATUS_FILE_IS_OFFLINE;
+	}
+
 	ctx = talloc_zero(dom, struct idmap_ldap_context);
 	if ( ! ctx) {
 		DEBUG(0, ("Out of memory!\n"));
@@ -732,9 +758,9 @@
 		}
 	}
 
-	if (params && *params) {
+	if (dom->params && *(dom->params)) {
 		/* assume location is the only parameter */
-		ctx->url = talloc_strdup(ctx, params);
+		ctx->url = talloc_strdup(ctx, dom->params);
 	} else {
 		tmp = lp_parm_const_string(-1, config_option, "ldap_url", NULL);
 
@@ -837,6 +863,19 @@
 	int rc;
 	int i;
 
+	/* Only do query if we are online */
+	if (idmap_is_offline())	{
+		return NT_STATUS_FILE_IS_OFFLINE;
+	}
+
+	/* Initilization my have been deferred because we were offline */
+	if ( ! dom->initialized) {
+		ret = idmap_ldap_db_init(dom);
+		if ( ! NT_STATUS_IS_OK(ret)) {
+			return ret;
+		}
+	}
+
 	ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);	
 
 	memctx = talloc_new(ctx);
@@ -991,10 +1030,10 @@
 
 	ret = NT_STATUS_OK;
 
-
-	/* mark all unknwon ones as unmapped */
+	/* mark all unknwon/expired ones as unmapped */
 	for (i = 0; ids[i]; i++) {
-		if (ids[i]->status == ID_UNKNOWN) ids[i]->status = ID_UNMAPPED;
+		if (ids[i]->status != ID_MAPPED)
+			ids[i]->status = ID_UNMAPPED;
 	}
 
 done:
@@ -1040,6 +1079,19 @@
 	int rc;
 	int i;
 
+	/* Only do query if we are online */
+	if (idmap_is_offline())	{
+		return NT_STATUS_FILE_IS_OFFLINE;
+	}
+
+	/* Initilization my have been deferred because we were offline */
+	if ( ! dom->initialized) {
+		ret = idmap_ldap_db_init(dom);
+		if ( ! NT_STATUS_IS_OK(ret)) {
+			return ret;
+		}
+	}
+
 	ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);	
 
 	memctx = talloc_new(ctx);
@@ -1192,9 +1244,10 @@
 
 	ret = NT_STATUS_OK;
 
-	/* mark all unknwon ones as unmapped */
+	/* mark all unknwon/expired ones as unmapped */
 	for (i = 0; ids[i]; i++) {
-		if (ids[i]->status == ID_UNKNOWN) ids[i]->status = ID_UNMAPPED;
+		if (ids[i]->status != ID_MAPPED)
+			ids[i]->status = ID_UNMAPPED;
 	}
 
 done:
@@ -1221,6 +1274,19 @@
 	char *dn;
 	int rc = -1;
 
+	/* Only do query if we are online */
+	if (idmap_is_offline())	{
+		return NT_STATUS_FILE_IS_OFFLINE;
+	}
+
+	/* Initilization my have been deferred because we were offline */
+	if ( ! dom->initialized) {
+		ret = idmap_ldap_db_init(dom);
+		if ( ! NT_STATUS_IS_OK(ret)) {
+			return ret;
+		}
+	}
+
 	ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);	
 
 	switch(map->xid.type) {
@@ -1301,15 +1367,6 @@
 }
 
 /**********************************
- remove a mapping. 
-**********************************/
-
-static NTSTATUS idmap_ldap_remove_mapping(struct idmap_domain *dom, const struct id_map *map)
-{
-	return NT_STATUS_UNSUCCESSFUL;
-}
-
-/**********************************
  Close the idmap ldap instance 
 **********************************/
 
@@ -1333,8 +1390,6 @@
 	.unixids_to_sids = idmap_ldap_unixids_to_sids,
 	.sids_to_unixids = idmap_ldap_sids_to_unixids,
 	.set_mapping = idmap_ldap_set_mapping,
-	.remove_mapping = idmap_ldap_remove_mapping,
-	/* .dump_data = TODO */
 	.close_fn = idmap_ldap_close
 };
 
Index: source/include/idmap.h
===================================================================
--- source/include/idmap.h	(revision 22320)
+++ source/include/idmap.h	(working copy)
@@ -42,13 +42,15 @@
 	BOOL readonly;
 	void *private_data;
 	struct idmap_methods *methods;
+	BOOL initialized;
+	const char *params;
 };
 
 /* Filled out by IDMAP backends */
 struct idmap_methods {
 
 	/* Called when backend is first loaded */
-	NTSTATUS (*init)(struct idmap_domain *dom, const char *compat_params);
+	NTSTATUS (*init)(struct idmap_domain *dom);
 
 	NTSTATUS (*unixids_to_sids)(struct idmap_domain *dom, struct id_map **ids);
 	NTSTATUS (*sids_to_unixids)(struct idmap_domain *dom, struct id_map **ids);
Index: source/include/smb.h
===================================================================
--- source/include/smb.h	(revision 22320)
+++ source/include/smb.h	(working copy)
@@ -288,7 +288,8 @@
 enum id_mapping {
 	ID_UNKNOWN,
 	ID_MAPPED,
-	ID_UNMAPPED
+	ID_UNMAPPED,
+	ID_EXPIRED
 };
 
 enum id_type {


Index: samba.spec
===================================================================
RCS file: /cvs/dist/rpms/samba/devel/samba.spec,v
retrieving revision 1.109
retrieving revision 1.110
diff -u -r1.109 -r1.110
--- samba.spec	16 Apr 2007 15:52:28 -0000	1.109
+++ samba.spec	18 Apr 2007 14:52:03 -0000	1.110
@@ -4,7 +4,7 @@
 Name: samba
 Epoch: 0
 Version: 3.0.25
-Release: 0.7.rc1%{?dist}
+Release: 0.7.rc1%{?dist}.2
 License: GPL
 Group: System Environment/Daemons
 URL: http://www.samba.org/
@@ -50,6 +50,7 @@
 Patch200: samba-3.0.25rc1-inotifiy.patch
 Patch201: samba-3-0-25rc1-bugday-apr10.patch
 Patch202: samba3_idmap_loop.patch
+Patch203: samba3_idmap_offline.patch
 
 
 Requires(pre): samba-common = %{epoch}:%{version}-%{release}
@@ -174,6 +175,7 @@
 %patch200 -p0 -b .inotify
 %patch201 -p0 -b .bugday
 %patch202 -p0 -b .idmap_loop
+%patch203 -p0 -b .idmap_offline
 
 # crap
 rm -f examples/VFS/.cvsignore




More information about the fedora-cvs-commits mailing list