From ee40cead097ed2c005f5f80b24c9f681e054849a Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 18 Apr 2007 21:10:37 +0000 Subject: [PATCH] r22343: Commit to 3_0 as well after adapting the patch. (tdb_delete_bystring instead of tdb_delete is used here) --- source/include/idmap.h | 4 +- source/include/smb.h | 3 +- source/nsswitch/idmap.c | 244 ++++++++++++++++++++++++----------------- source/nsswitch/idmap_ad.c | 43 ++++++-- source/nsswitch/idmap_cache.c | 120 ++++++++------------ source/nsswitch/idmap_ldap.c | 95 ++++++++++++---- source/nsswitch/idmap_nss.c | 3 +- source/nsswitch/idmap_passdb.c | 3 +- source/nsswitch/idmap_tdb.c | 43 +++++++- 9 files changed, 352 insertions(+), 206 deletions(-) diff --git a/source/include/idmap.h b/source/include/idmap.h index 80bd541a23f..472358a2305 100644 --- a/source/include/idmap.h +++ b/source/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/source/include/smb.h b/source/include/smb.h index a9c57f77f25..f85201ed303 100644 --- a/source/include/smb.h +++ b/source/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/source/nsswitch/idmap.c b/source/nsswitch/idmap.c index 885950830eb..82b8f3d592e 100644 --- a/source/nsswitch/idmap.c +++ b/source/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/source/nsswitch/idmap_ad.c b/source/nsswitch/idmap_ad.c index 87f73f99f09..9daa0024ea3 100644 --- a/source/nsswitch/idmap_ad.c +++ b/source/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/source/nsswitch/idmap_cache.c b/source/nsswitch/idmap_cache.c index 6e5febf2ba8..d43dc63f426 100644 --- a/source/nsswitch/idmap_cache.c +++ b/source/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/source/nsswitch/idmap_ldap.c b/source/nsswitch/idmap_ldap.c index d6261f407be..7575416af5e 100644 --- a/source/nsswitch/idmap_ldap.c +++ b/source/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/source/nsswitch/idmap_nss.c b/source/nsswitch/idmap_nss.c index 3cd8a8e8eae..e3e425f105f 100644 --- a/source/nsswitch/idmap_nss.c +++ b/source/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/source/nsswitch/idmap_passdb.c b/source/nsswitch/idmap_passdb.c index a5f8a084b3a..665ead5bb10 100644 --- a/source/nsswitch/idmap_passdb.c +++ b/source/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/source/nsswitch/idmap_tdb.c b/source/nsswitch/idmap_tdb.c index 73db1def0ce..4eb47c42b84 100644 --- a/source/nsswitch/idmap_tdb.c +++ b/source/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); -- 2.11.4.GIT