summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/idmap.h4
-rw-r--r--source3/include/smb.h3
-rw-r--r--source3/nsswitch/idmap.c244
-rw-r--r--source3/nsswitch/idmap_ad.c43
-rw-r--r--source3/nsswitch/idmap_cache.c120
-rw-r--r--source3/nsswitch/idmap_ldap.c95
-rw-r--r--source3/nsswitch/idmap_nss.c3
-rw-r--r--source3/nsswitch/idmap_passdb.c3
-rw-r--r--source3/nsswitch/idmap_tdb.c43
9 files changed, 352 insertions, 206 deletions
diff --git a/source3/include/idmap.h b/source3/include/idmap.h
index 80bd541a23..472358a230 100644
--- a/source3/include/idmap.h
+++ b/source3/include/idmap.h
@@ -42,13 +42,15 @@ struct idmap_domain {
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);
diff --git a/source3/include/smb.h b/source3/include/smb.h
index a9c57f77f2..f85201ed30 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -278,7 +278,8 @@ typedef struct dom_sid {
enum id_mapping {
ID_UNKNOWN,
ID_MAPPED,
- ID_UNMAPPED
+ ID_UNMAPPED,
+ ID_EXPIRED
};
enum id_type {
diff --git a/source3/nsswitch/idmap.c b/source3/nsswitch/idmap.c
index 885950830e..82b8f3d592 100644
--- a/source3/nsswitch/idmap.c
+++ b/source3/nsswitch/idmap.c
@@ -43,6 +43,12 @@ struct idmap_alloc_backend {
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 pdb_dom_num = -1;
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 @@ void set_idmap_in_own_child(void)
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 @@ static int close_domain_destructor(struct idmap_domain *dom)
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_cache(void)
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,24 +296,12 @@ NTSTATUS idmap_init(void)
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;
@@ -432,13 +433,18 @@ NTSTATUS idmap_init(void)
/* 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 @@ NTSTATUS idmap_init(void)
/* 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 @@ NTSTATUS idmap_init(void)
/* 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,37 +615,50 @@ NTSTATUS idmap_init(void)
}
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 );
-
- backend_init_status = NT_STATUS_OK;
+
+ idmap_init_status = NT_STATUS_OK;
return ret;
@@ -633,12 +666,35 @@ 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 idmap_allocate_uid(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->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 @@ static NTSTATUS idmap_new_mapping(TALLOC_CTX *ctx, struct id_map *map)
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 @@ static NTSTATUS idmap_backends_unixids_to_sids(struct id_map **ids)
_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 @@ static NTSTATUS idmap_backends_unixids_to_sids(struct id_map **ids)
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 @@ static NTSTATUS idmap_backends_unixids_to_sids(struct id_map **ids)
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 @@ static NTSTATUS idmap_backends_sids_to_unixids(struct id_map **ids)
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 @@ static NTSTATUS idmap_backends_sids_to_unixids(struct id_map **ids)
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 @@ static NTSTATUS idmap_backends_sids_to_unixids(struct id_map **ids)
/* 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 @@ static NTSTATUS idmap_backends_sids_to_unixids(struct id_map **ids)
/* 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 @@ 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);
@@ -1179,11 +1218,17 @@ NTSTATUS idmap_unixids_to_sids(struct id_map **ids)
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 @@ 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);
@@ -1285,12 +1323,18 @@ NTSTATUS idmap_sids_to_unixids(struct id_map **ids)
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 @@ void idmap_dump_maps(char *logfile)
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);
}
diff --git a/source3/nsswitch/idmap_ad.c b/source3/nsswitch/idmap_ad.c
index 87f73f99f0..9daa0024ea 100644
--- a/source3/nsswitch/idmap_ad.c
+++ b/source3/nsswitch/idmap_ad.c
@@ -160,7 +160,7 @@ static ADS_STRUCT *ad_idmap_cached_connection(void)
/************************************************************************
***********************************************************************/
-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 @@ static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom, const char *params
}
dom->private_data = ctx;
+ dom->initialized = True;
talloc_free(config_option);
@@ -269,6 +270,19 @@ static NTSTATUS idmap_ad_unixids_to_sids(struct idmap_domain *dom, struct id_map
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 @@ again:
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 @@ again:
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 @@ static NTSTATUS idmap_ad_sids_to_unixids(struct idmap_domain *dom, struct id_map
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 @@ again:
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 @@ static NTSTATUS nss_sfu_init( struct nss_domain_entry *e )
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 @@ static NTSTATUS nss_rfc2307_init( struct nss_domain_entry *e )
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;
}
diff --git a/source3/nsswitch/idmap_cache.c b/source3/nsswitch/idmap_cache.c
index 6e5febf2ba..d43dc63f42 100644
--- a/source3/nsswitch/idmap_cache.c
+++ b/source3/nsswitch/idmap_cache.c
@@ -348,7 +348,7 @@ BOOL idmap_cache_is_negative(const char *val)
/* 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
@@ -356,17 +356,16 @@ BOOL idmap_cache_is_negative(const char *val)
* 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 databuf;
- time_t t;
+ time_t t, now;
char *sidkey;
char *endptr;
@@ -393,11 +392,13 @@ NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id)
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 */
@@ -411,35 +412,21 @@ 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)) {
- /* 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_bystring(cache->tdb, sidkey);
- ret = NT_STATUS_NONE_MAPPED;
- }
+ if (t <= now) {
+ /* We're expired, delete the NEGATIVE entry and return
+ not mapped */
+ tdb_delete_bystring(cache->tdb, sidkey);
+ ret = NT_STATUS_NONE_MAPPED;
} else {
/* this is not mapped as it was a negative cache hit */
id->status = ID_UNMAPPED;
@@ -455,7 +442,7 @@ done:
/* search the cahce for the ID 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
@@ -463,21 +450,20 @@ done:
* 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 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);
@@ -500,11 +486,13 @@ NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id)
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 */
@@ -516,39 +504,25 @@ NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id)
goto done;
}
- /* here ret == NT_STATUS_OK and id->mapped = True */
-
- 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;
- }
+ /* here ret == NT_STATUS_OK and id->mapped = ID_MAPPED */
+
+ 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_bystring(cache->tdb, idkey);
- ret = NT_STATUS_NONE_MAPPED;
- }
+ if (t <= now) {
+ /* We're expired, delete the NEGATIVE entry and return
+ not mapped */
+ tdb_delete_bystring(cache->tdb, idkey);
+ 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;
}
diff --git a/source3/nsswitch/idmap_ldap.c b/source3/nsswitch/idmap_ldap.c
index d6261f407b..7575416af5 100644
--- a/source3/nsswitch/idmap_ldap.c
+++ b/source3/nsswitch/idmap_ldap.c
@@ -152,6 +152,7 @@ static NTSTATUS verify_idpool(void)
&result);
if (rc != LDAP_SUCCESS) {
+ DEBUG(1, ("Unable to verify the idpool, cannot continue initialization!\n"));
return NT_STATUS_UNSUCCESSFUL;
}
@@ -210,6 +211,11 @@ static NTSTATUS idmap_ldap_alloc_init(const char *params)
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 );
@@ -346,6 +352,11 @@ static NTSTATUS idmap_ldap_allocate_id(struct unixid *xid)
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;
}
@@ -492,6 +503,11 @@ static NTSTATUS idmap_ldap_get_hwm(struct unixid *xid)
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;
}
@@ -582,6 +598,11 @@ static NTSTATUS idmap_ldap_set_hwm(struct unixid *xid)
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;
}
@@ -702,14 +723,19 @@ static int idmap_ldap_close_destructor(struct idmap_ldap_context *ctx)
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"));
@@ -734,9 +760,9 @@ static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom, const char *params)
}
}
- 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);
@@ -840,6 +866,19 @@ static NTSTATUS idmap_ldap_unixids_to_sids(struct idmap_domain *dom, struct id_m
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);
@@ -994,10 +1033,10 @@ again:
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:
@@ -1044,6 +1083,19 @@ static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom, struct id_m
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);
@@ -1195,9 +1247,10 @@ again:
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:
@@ -1224,6 +1277,19 @@ static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom, const struct id
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) {
@@ -1304,15 +1370,6 @@ done:
}
/**********************************
- 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
**********************************/
@@ -1336,8 +1393,6 @@ static struct idmap_methods idmap_ldap_methods = {
.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
};
diff --git a/source3/nsswitch/idmap_nss.c b/source3/nsswitch/idmap_nss.c
index 3cd8a8e8ea..e3e425f105 100644
--- a/source3/nsswitch/idmap_nss.c
+++ b/source3/nsswitch/idmap_nss.c
@@ -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;
}
diff --git a/source3/nsswitch/idmap_passdb.c b/source3/nsswitch/idmap_passdb.c
index a5f8a084b3..665ead5bb1 100644
--- a/source3/nsswitch/idmap_passdb.c
+++ b/source3/nsswitch/idmap_passdb.c
@@ -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;
}
diff --git a/source3/nsswitch/idmap_tdb.c b/source3/nsswitch/idmap_tdb.c
index 73db1def0c..4eb47c42b8 100644
--- a/source3/nsswitch/idmap_tdb.c
+++ b/source3/nsswitch/idmap_tdb.c
@@ -586,7 +586,7 @@ struct idmap_tdb_context {
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;
@@ -620,6 +620,7 @@ static NTSTATUS idmap_tdb_db_init(struct idmap_domain *dom, const char *compat_p
}
dom->private_data = ctx;
+ dom->initialized = True;
talloc_free(config_option);
return NT_STATUS_OK;
@@ -772,6 +773,14 @@ static NTSTATUS idmap_tdb_unixids_to_sids(struct idmap_domain *dom, struct id_ma
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++) {
@@ -810,6 +819,14 @@ static NTSTATUS idmap_tdb_sids_to_unixids(struct idmap_domain *dom, struct id_ma
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++) {
@@ -849,6 +866,14 @@ static NTSTATUS idmap_tdb_set_mapping(struct idmap_domain *dom, const struct id_
TDB_DATA ksid, kid, data;
char *ksidstr, *kidstr;
+ /* 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;
}
@@ -954,6 +979,14 @@ static NTSTATUS idmap_tdb_remove_mapping(struct idmap_domain *dom, const struct
TDB_DATA ksid, kid, data;
char *ksidstr, *kidstr;
+ /* 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;
}
@@ -1133,6 +1166,14 @@ static NTSTATUS idmap_tdb_dump_data(struct idmap_domain *dom, struct id_map **ma
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);