diff options
| author | Shreyas Siravara <sshreyas@fb.com> | 2015-03-25 12:50:11 -0700 |
|---|---|---|
| committer | Jeff Darcy <jeff@pl.atyp.us> | 2017-08-29 15:11:10 +0000 |
| commit | 1f7b0cb7e81eb1c12b527138c0c64f8d4e093426 (patch) | |
| tree | 0ac8fccdba57c060dc8e3b846d7611ae6fce0255 | |
| parent | 9255f94bc29990e7d08ad5189ba9c3bda2ccba9a (diff) | |
Add negative caching to nfs auth cache
Summary:
This diff adds the ability to the nfs daemon to cache hosts it has deauthorized for mounts, not just the hosts
it has authorized. This allows a host that has been denied to be deauthorized for ttl # of seconds, or until the nfs
daemon has restarted.
Test Plan:
Use the prove tests to maintain the integrity of the auth code. Test manually to see
if the correct code path is being hit.
Reviewers: dph, rwareing
Reviewed By: rwareing
Differential Revision: https://phabricator.fb.com/D1947728
Change-Id: I9728e15913e0900ab34311b13b30eba0b91ce33f
Reviewed-on: https://review.gluster.org/18134
Smoke: Gluster Build System <jenkins@build.gluster.org>
Reviewed-by: Jeff Darcy <jeff@pl.atyp.us>
Tested-by: Jeff Darcy <jeff@pl.atyp.us>
CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
| -rw-r--r-- | xlators/debug/io-stats/src/io-stats.c | 2 | ||||
| -rw-r--r-- | xlators/nfs/server/src/auth-cache.c | 542 | ||||
| -rw-r--r-- | xlators/nfs/server/src/auth-cache.h | 31 | ||||
| -rw-r--r-- | xlators/nfs/server/src/exports.h | 9 | ||||
| -rw-r--r-- | xlators/nfs/server/src/mount3.c | 56 |
5 files changed, 289 insertions, 351 deletions
diff --git a/xlators/debug/io-stats/src/io-stats.c b/xlators/debug/io-stats/src/io-stats.c index 69f182c5194..b02819f1013 100644 --- a/xlators/debug/io-stats/src/io-stats.c +++ b/xlators/debug/io-stats/src/io-stats.c @@ -726,7 +726,7 @@ ios_stats_cleanup (xlator_t *this, inode_t *inode) fprintf (logfp, fmt); \ fprintf (logfp, "\n"); \ } \ - gf_log (this->name, GF_LOG_DEBUG, fmt); \ + gf_log (this->name, GF_LOG_TRACE, fmt); \ } while (0) int diff --git a/xlators/nfs/server/src/auth-cache.c b/xlators/nfs/server/src/auth-cache.c index 730e0a97d20..a607502c9de 100644 --- a/xlators/nfs/server/src/auth-cache.c +++ b/xlators/nfs/server/src/auth-cache.c @@ -17,47 +17,28 @@ #include "exports.h" #include "nfs-messages.h" -enum auth_cache_lookup_results { - ENTRY_FOUND = 0, - ENTRY_NOT_FOUND = -1, - ENTRY_EXPIRED = -2, -}; - -struct auth_cache_entry { - GF_REF_DECL; /* refcounting */ - data_t *data; /* data_unref() on refcount == 0 */ - - time_t timestamp; - struct export_item *item; -}; - /* Given a filehandle and an ip, creates a colon delimited hashkey. */ -static char* -make_hashkey(struct nfs3_fh *fh, const char *host) -{ - char *hashkey = NULL; - char exportid[256] = {0, }; - char gfid[256] = {0, }; - char mountid[256] = {0, }; - size_t nbytes = 0; - - gf_uuid_unparse (fh->exportid, exportid); - gf_uuid_unparse (fh->gfid, gfid); - gf_uuid_unparse (fh->mountid, mountid); - - nbytes = strlen (exportid) + strlen (host) - + strlen (mountid) + 3; - hashkey = GF_MALLOC (nbytes, gf_common_mt_char); - if (!hashkey) - return NULL; - - snprintf (hashkey, nbytes, "%s:%s:%s", exportid, - mountid, host); - - return hashkey; -} - +#define make_fh_hashkey(hashkey, fh, host) \ + do { \ + char exportid[256] = {0, }; \ + char mountid[256] = {0, }; \ + size_t nbytes = 0; \ + gf_uuid_unparse (fh->exportid, exportid); \ + gf_uuid_unparse (fh->mountid, mountid); \ + nbytes = strlen (exportid) + strlen (host) \ + + strlen (mountid) + 5; \ + hashkey = alloca (nbytes); \ + snprintf (hashkey, nbytes, "%s:%s:%s", exportid, \ + mountid, host); \ + } while (0); \ + +#define make_path_hashkey(hashkey, path, host) \ + do { \ + size_t nbytes = strlen (path) + strlen (host) + 2; \ + hashkey = alloca (nbytes); \ + snprintf (hashkey, nbytes, "%s:%s", path, host); \ + } while (0); /** * auth_cache_init -- Initialize an auth cache and set the ttl_sec * @@ -86,28 +67,11 @@ out: return cache; } -/* auth_cache_entry_free -- called by refcounting subsystem on refcount == 0 - * - * @to_free: auth_cache_entry that has refcount == 0 and needs to get free'd - */ -void -auth_cache_entry_free (void *to_free) -{ - struct auth_cache_entry *entry = to_free; - data_t *entry_data = NULL; - - GF_VALIDATE_OR_GOTO (GF_NFS, entry, out); - GF_VALIDATE_OR_GOTO (GF_NFS, entry->data, out); - - entry_data = entry->data; - /* set data_t->data to NULL, otherwise data_unref() tries to free it */ - entry_data->data = NULL; - data_unref (entry_data); - - GF_FREE (entry); -out: - return; -} +struct auth_cache_entry { + time_t timestamp; + struct export_item *item; + gf_boolean_t access_allowed; +}; /** * auth_cache_entry_init -- Initialize an auth cache entry @@ -124,303 +88,203 @@ auth_cache_entry_init () if (!entry) gf_msg (GF_NFS, GF_LOG_WARNING, ENOMEM, NFS_MSG_NO_MEMORY, "failed to allocate entry"); - else - GF_REF_INIT (entry, auth_cache_entry_free); return entry; } +// Internal lookup +enum _internal_cache_lookup_results { + ENTRY_NOT_FOUND = -1, + ENTRY_EXPIRED = -2, +}; + /** - * auth_cache_add -- Add an auth_cache_entry to the cache->dict + * auth_cache_purge -- Purge the dict in the cache and set + * the dict pointer to NULL. It will be allocated + * on the first insert into the dict. + * + * @cache: Cache to purge * - * @return: 0 on success, non-zero otherwise. */ -static int -auth_cache_add (struct auth_cache *cache, char *hashkey, - struct auth_cache_entry *entry) +void +auth_cache_purge (struct auth_cache *cache) { - int ret = -1; - data_t *entry_data = NULL; - - GF_VALIDATE_OR_GOTO (GF_NFS, cache, out); - GF_VALIDATE_OR_GOTO (GF_NFS, cache->cache_dict, out); - - ret = GF_REF_GET (entry); - if (ret == 0) { - /* entry does not have any references */ - ret = -1; - goto out; - } + dict_t *new_cache_dict = NULL; + dict_t *old_cache_dict = cache->cache_dict; - entry_data = bin_to_data (entry, sizeof (*entry)); - if (!entry_data) { - ret = -1; - GF_REF_PUT (entry); + if (!cache || !cache->cache_dict) goto out; - } - /* we'll take an extra ref on the data_t, it gets unref'd when the - * auth_cache_entry is released */ - entry->data = data_ref (entry_data); + (void)__sync_lock_test_and_set (&cache->cache_dict, new_cache_dict); - LOCK (&cache->lock); - { - ret = dict_set (cache->cache_dict, hashkey, entry_data); - } - UNLOCK (&cache->lock); - - if (ret) { - /* adding to dict failed */ - GF_REF_PUT (entry); - } + dict_destroy (old_cache_dict); out: - return ret; + return; } -/** - * _auth_cache_expired -- Check if the auth_cache_entry has expired - * - * The auth_cache->lock should have been taken when this function is called. - * - * @return: true when the auth_cache_entry is expired, false otherwise. - */ -static int -_auth_cache_expired (struct auth_cache *cache, struct auth_cache_entry *entry) -{ - return ((time (NULL) - entry->timestamp) > cache->ttl_sec); -} /** - * auth_cache_get -- Get the @hashkey entry from the cache->cache_dict - * - * @cache: The auth_cache that should contain the @entry. - * @haskkey: The key associated with the auth_cache_entry. - * @entry: The found auth_cache_entry, unmodified if not found/expired. - * - * The using the cache->dict requires locking, this function takes care of - * that. When the entry is found, but has expired, it will be removed from the - * cache_dict. - * - * @return: 0 when found, ENTRY_NOT_FOUND or ENTRY_EXPIRED otherwise. + * Lookup filehandle or path from the cache. */ -static enum auth_cache_lookup_results -auth_cache_get (struct auth_cache *cache, char *hashkey, - struct auth_cache_entry **entry) +int _cache_lookup (struct auth_cache *cache, char *key, + struct auth_cache_entry **entry) { - enum auth_cache_lookup_results ret = ENTRY_NOT_FOUND; - data_t *entry_data = NULL; - struct auth_cache_entry *lookup_res = NULL; + int ret = ENTRY_NOT_FOUND; + struct auth_cache_entry *lookup_res; + data_t *entry_data; - GF_VALIDATE_OR_GOTO (GF_NFS, cache, out); - GF_VALIDATE_OR_GOTO (GF_NFS, cache->cache_dict, out); - GF_VALIDATE_OR_GOTO (GF_NFS, hashkey, out); - - LOCK (&cache->lock); - { - entry_data = dict_get (cache->cache_dict, hashkey); - if (!entry_data) - goto unlock; - - lookup_res = (struct auth_cache_entry *)(entry_data->data); - if (GF_REF_GET (lookup_res) == 0) { - /* entry has been free'd */ - ret = ENTRY_EXPIRED; - goto unlock; - } + if (!cache->cache_dict) { + goto out; + } - if (_auth_cache_expired (cache, lookup_res)) { - ret = ENTRY_EXPIRED; + if (!entry) { + goto out; + } - /* free entry and remove from the cache */ - GF_FREE (lookup_res); - entry_data->data = NULL; - dict_del (cache->cache_dict, hashkey); + *entry = NULL; - goto unlock; - } + entry_data = dict_get (cache->cache_dict, key); + if (!entry_data) { + goto out; + } - *entry = lookup_res; - ret = ENTRY_FOUND; + lookup_res = (struct auth_cache_entry *)(entry_data->data); + if (time (NULL) - lookup_res->timestamp > cache->ttl_sec) { + GF_FREE (lookup_res); + entry_data->data = NULL; + dict_del (cache->cache_dict, key); // Remove from the cache + ret = ENTRY_EXPIRED; + goto out; } -unlock: - UNLOCK (&cache->lock); + + *entry = lookup_res; + + return 0; out: - return ret; + return -1; } /** - * auth_cache_lookup -- Lookup an item from the cache - * - * @cache: cache to lookup from - * @fh : FH to use in lookup - * @host_addr: Address to use in lookup - * @timestamp: The timestamp to set when lookup succeeds - * @can_write: Is the host authorized to write to the filehandle? - * - * If the current time - entry time of the cache entry > ttl_sec, - * we remove the element from the dict and return ENTRY_EXPIRED. - * - * @return: ENTRY_EXPIRED if entry expired - * ENTRY_NOT_FOUND if entry not found in dict - * 0 if found + * Lookup filehandle from the cache. */ -enum auth_cache_lookup_results -auth_cache_lookup (struct auth_cache *cache, struct nfs3_fh *fh, - const char *host_addr, time_t *timestamp, - gf_boolean_t *can_write) +int +_cache_lookup_fh (struct auth_cache *cache, struct nfs3_fh *fh, + const char *host_addr, struct auth_cache_entry **ec) { - char *hashkey = NULL; - struct auth_cache_entry *lookup_res = NULL; - enum auth_cache_lookup_results ret = ENTRY_NOT_FOUND; - - GF_VALIDATE_OR_GOTO (GF_NFS, cache, out); - GF_VALIDATE_OR_GOTO (GF_NFS, fh, out); - GF_VALIDATE_OR_GOTO (GF_NFS, host_addr, out); - GF_VALIDATE_OR_GOTO (GF_NFS, timestamp, out); - GF_VALIDATE_OR_GOTO (GF_NFS, can_write, out); - - hashkey = make_hashkey (fh, host_addr); - if (!hashkey) { - ret = -ENOMEM; - goto out; + char *hashkey; + int ret = ENTRY_NOT_FOUND; + if (fh && host_addr) { + make_fh_hashkey (hashkey, fh, host_addr); + ret =_cache_lookup (cache, hashkey, ec); } - - ret = auth_cache_get (cache, hashkey, &lookup_res); - switch (ret) { - case ENTRY_FOUND: - *timestamp = lookup_res->timestamp; - *can_write = lookup_res->item->opts->rw; - GF_REF_PUT (lookup_res); - break; - - case ENTRY_NOT_FOUND: - gf_msg_debug (GF_NFS, 0, "could not find entry for %s", - host_addr); - break; - - case ENTRY_EXPIRED: - gf_msg_debug (GF_NFS, 0, "entry for host %s has expired", - host_addr); - break; - } - -out: - GF_FREE (hashkey); - return ret; } -/* auth_cache_entry_purge -- free up the auth_cache_entry - * - * This gets called through dict_foreach() by auth_cache_purge(). Each - * auth_cache_entry has a refcount which needs to be decremented. Once the - * auth_cache_entry reaches refcount == 0, auth_cache_entry_free() will call - * data_unref() to free the associated data_t. - * - * @d: dict that gets purged by auth_cache_purge() - * @k: hashkey of the current entry - * @v: data_t of the current entry +/** + * Lookup path from the cache. */ int -auth_cache_entry_purge (dict_t *d, char *k, data_t *v, void *_unused) +_cache_lookup_path (struct auth_cache *cache, const char *path, + const char *host_addr, struct auth_cache_entry **ec) { - struct auth_cache_entry *entry = (struct auth_cache_entry *) v->data; - - if (entry) - GF_REF_PUT (entry); - - return 0; + char *hashkey; + int ret = ENTRY_NOT_FOUND; + if (path && host_addr) { + make_path_hashkey (hashkey, path, host_addr); + ret = _cache_lookup (cache, hashkey, ec); + } + return ret; } /** - * auth_cache_purge -- Purge the dict in the cache and create a new empty one. - * - * @cache: Cache to purge - * + * cache_item -- Caches either a filehandle or path. + * See descriptions of functions that invoke this one. */ -void -auth_cache_purge (struct auth_cache *cache) +int +cache_item (struct auth_cache *cache, const char *path, struct nfs3_fh *fh, + const char *host_addr, struct export_item *export_item, + auth_cache_status_t status) { - dict_t *new_cache_dict = dict_new (); - dict_t *old_cache_dict = NULL; + int ret = -EINVAL; + data_t *entry_data = NULL; + struct auth_cache_entry *entry = NULL; + char *hashkey = NULL; - if (!cache || !new_cache_dict) + GF_VALIDATE_OR_GOTO (GF_NFS, host_addr, out); + GF_VALIDATE_OR_GOTO (GF_NFS, cache, out); + + // We can cache either a file-handle or a path, not both, + // and at least one of them must be defined! + if ((fh && path) || (!fh && !path)) { goto out; + } - LOCK (&cache->lock); - { - old_cache_dict = cache->cache_dict; - cache->cache_dict = new_cache_dict; + // If a dict has not been allocated already, allocate it. + if (!cache->cache_dict) { + cache->cache_dict = dict_new (); + if (!cache->cache_dict) { + ret = -ENOMEM; + goto out; + } } - UNLOCK (&cache->lock); - /* walk all entries and refcount-- with GF_REF_PUT() */ - dict_foreach (old_cache_dict, auth_cache_entry_purge, NULL); - dict_unref (old_cache_dict); -out: - return; -} -/** - * is_nfs_fh_cached_and_writeable -- Checks if an NFS FH is cached for the given - * host - * @cache: The fh cache - * @host_addr: Address to use in lookup - * @fh: The fh to use in lookup - * - * - * @return: TRUE if cached, FALSE otherwise - * - */ -gf_boolean_t -is_nfs_fh_cached (struct auth_cache *cache, struct nfs3_fh *fh, - const char *host_addr) -{ - int ret = 0; - time_t timestamp = 0; - gf_boolean_t cached = _gf_false; - gf_boolean_t can_write = _gf_false; + // Find an entry with the filehandle or path, depending + // on which one is defined. Validation for these parameters + // is above. + if (fh) { + ret = _cache_lookup_fh (cache, fh, host_addr, &entry); + make_fh_hashkey (hashkey, fh, host_addr) + } - if (!fh) - goto out; + if (path) { + ret = _cache_lookup_path (cache, path, host_addr, &entry); + make_path_hashkey (hashkey, path, host_addr) + } + + // If no entry was found, we need to create one. + if (!entry) { + entry = auth_cache_entry_init (); + GF_CHECK_ALLOC (entry, ret, out); + } - ret = auth_cache_lookup (cache, fh, host_addr, ×tamp, &can_write); - cached = (ret == ENTRY_FOUND); + // Populate the entry + entry->timestamp = time (NULL); + entry->item = export_item; + // Access is only allowed if the status is set to + // AUTH_CACHE_HOST_AUTH_OK + entry->access_allowed = (status == AUTH_CACHE_HOST_AUTH_OK); + // Put the entry into the cache + entry_data = bin_to_data (entry, sizeof (*entry)); + dict_set (cache->cache_dict, hashkey, entry_data); + gf_log (GF_NFS, GF_LOG_TRACE, "Caching %s for host(%s) as %s", + path ? path : "fh", host_addr, entry->access_allowed ? + "ALLOWED" : "NOT ALLOWED"); out: - return cached; + return ret; } - /** - * is_nfs_fh_cached_and_writeable -- Checks if an NFS FH is cached for the given - * host and writable - * @cache: The fh cache - * @host_addr: Address to use in lookup - * @fh: The fh to use in lookup - * + * cache_nfs_path -- Places the path in the underlying dict as we are + * using as our cache. The value is an entry struct + * containing the export item that was authorized or + * deauthorized for the operation and the path authorized + * or deauthorized. * - * @return: TRUE if cached & writable, FALSE otherwise + * @cache: The cache to place fh's in + * @path : The path to cache + * @host_addr: The address of the host + * @export_item: The export item that was authorized/deauthorized * */ -gf_boolean_t -is_nfs_fh_cached_and_writeable (struct auth_cache *cache, struct nfs3_fh *fh, - const char *host_addr) +int +cache_nfs_path (struct auth_cache *cache, const char *path, + const char *host_addr, struct export_item *export_item, + auth_cache_status_t status) { - int ret = 0; - time_t timestamp = 0; - gf_boolean_t cached = _gf_false; - gf_boolean_t writable = _gf_false; - - if (!fh) - goto out; - - ret = auth_cache_lookup (cache, fh, host_addr, ×tamp, &writable); - cached = ((ret == ENTRY_FOUND) && writable); - -out: - return cached; + return cache_item (cache, path, NULL, host_addr, export_item, status); } /** @@ -438,52 +302,68 @@ out: */ int cache_nfs_fh (struct auth_cache *cache, struct nfs3_fh *fh, - const char *host_addr, struct export_item *export_item) + const char *host_addr, struct export_item *export_item, + auth_cache_status_t status) { - int ret = -EINVAL; - char *hashkey = NULL; - data_t *entry_data = NULL; - time_t timestamp = 0; - gf_boolean_t can_write = _gf_false; - struct auth_cache_entry *entry = NULL; + return cache_item (cache, NULL, fh, host_addr, export_item, status); +} - GF_VALIDATE_OR_GOTO (GF_NFS, host_addr, out); - GF_VALIDATE_OR_GOTO (GF_NFS, cache, out); - GF_VALIDATE_OR_GOTO (GF_NFS, fh, out); +auth_cache_status_t +auth_cache_allows (struct auth_cache *cache, struct nfs3_fh *fh, + const char *path, const char *host_addr, + gf_boolean_t check_rw_access) +{ + int ret = 0; + int status = AUTH_CACHE_HOST_EACCES; + gf_boolean_t cache_allows = FALSE; + struct auth_cache_entry *ace = NULL; - /* If we could already find it in the cache, just return */ - ret = auth_cache_lookup (cache, fh, host_addr, ×tamp, &can_write); - if (ret == 0) { - gf_msg_trace (GF_NFS, 0, "found cached auth/fh for host " - "%s", host_addr); + if ((fh && path) || (!fh && !path)) { + status = AUTH_CACHE_HOST_ENOENT; goto out; } - hashkey = make_hashkey (fh, host_addr); - if (!hashkey) { - ret = -ENOMEM; - goto out; + if (fh) { + ret = _cache_lookup_fh (cache, fh, host_addr, &ace); } - entry = auth_cache_entry_init (); - if (!entry) { - ret = -ENOMEM; - goto out; + if (path) { + ret = _cache_lookup_path (cache, path, host_addr, &ace); } - entry->timestamp = time (NULL); - entry->item = export_item; - - ret = auth_cache_add (cache, hashkey, entry); - GF_REF_PUT (entry); - if (ret) - goto out; + cache_allows = (ret == 0) && ace->access_allowed; + if (check_rw_access) { + cache_allows = cache_allows && ace->item->opts->rw; + } - gf_msg_trace (GF_NFS, 0, "Caching file-handle (%s)", host_addr); - ret = 0; + if (!ace) { + status = AUTH_CACHE_HOST_ENOENT; + } + if (cache_allows) { + status = AUTH_CACHE_HOST_AUTH_OK; + } out: - GF_FREE (hashkey); + return status; +} - return ret; +auth_cache_status_t +auth_cache_allows_fh (struct auth_cache *cache, struct nfs3_fh *fh, + const char *host_addr) +{ + return auth_cache_allows (cache, fh, NULL, host_addr, FALSE); +} + +auth_cache_status_t +auth_cache_allows_write_to_fh (struct auth_cache *cache, struct nfs3_fh *fh, + const char *host_addr) +{ + return auth_cache_allows (cache, fh, NULL, host_addr, TRUE); +} + +auth_cache_status_t +auth_cache_allows_path (struct auth_cache *cache, const char *path, + const char *host_addr) +{ + return auth_cache_allows (cache, NULL, path, host_addr, FALSE); } diff --git a/xlators/nfs/server/src/auth-cache.h b/xlators/nfs/server/src/auth-cache.h index a3ea5a43ded..de7db6b5545 100644 --- a/xlators/nfs/server/src/auth-cache.h +++ b/xlators/nfs/server/src/auth-cache.h @@ -27,6 +27,11 @@ struct auth_cache { time_t ttl_sec; /* TTL of the auth cache in seconds */ }; +typedef enum { + AUTH_CACHE_HOST_ENOENT = -1, /* Host not found in cache */ + AUTH_CACHE_HOST_EACCES = -2, /* Host explicitly de-authed */ + AUTH_CACHE_HOST_AUTH_OK = 0, /* Host is fully authed */ +} auth_cache_status_t; /* Initializes the cache */ struct auth_cache * @@ -35,17 +40,29 @@ auth_cache_init (time_t ttl_sec); /* Inserts FH into cache */ int cache_nfs_fh (struct auth_cache *cache, struct nfs3_fh *fh, - const char *host_addr, struct export_item *export_item); + const char *host_addr, struct export_item *export_item, + auth_cache_status_t status); + +/* Inserts path into cache */ +int +cache_nfs_path (struct auth_cache *cache, const char *path, + const char *host_addr, struct export_item *export_item, + auth_cache_status_t status); /* Checks if the filehandle cached & writable */ -gf_boolean_t -is_nfs_fh_cached_and_writeable (struct auth_cache *cache, struct nfs3_fh *fh, - const char *host_addr); +auth_cache_status_t +auth_cache_allows_write_to_fh (struct auth_cache *cache, struct nfs3_fh *fh, + const char *host_addr); /* Checks if the filehandle is cached */ -gf_boolean_t -is_nfs_fh_cached (struct auth_cache *cache, struct nfs3_fh *fh, - const char *host_addr); +auth_cache_status_t +auth_cache_allows_fh (struct auth_cache *cache, struct nfs3_fh *fh, + const char *host_addr); + +/* Checks if the path is cached */ +auth_cache_status_t +auth_cache_allows_path (struct auth_cache *cache, const char *path, + const char *host_addr); /* Purge the cache */ void diff --git a/xlators/nfs/server/src/exports.h b/xlators/nfs/server/src/exports.h index 0079b9a3deb..a4e15d3f7ef 100644 --- a/xlators/nfs/server/src/exports.h +++ b/xlators/nfs/server/src/exports.h @@ -51,23 +51,28 @@ struct export_options { char *anon_uid; /* anonuid option */ char *sec_type; /* X, for sec=X */ }; +typedef struct export_options export_options_t; + struct export_item { - char *name; /* Name of the export item */ - struct export_options *opts; /* NFS Options */ + char *name; /* Name of the export item */ + export_options_t *opts; /* NFS Options */ }; +typedef struct export_item export_item_t; struct export_dir { char *dir_name; /* Directory */ dict_t *netgroups; /* Dict of netgroups */ dict_t *hosts; /* Dict of hosts */ }; +typedef struct export_dir export_dir_t; struct exports_file { char *filename; /* Filename */ dict_t *exports_dict; /* Dict of export_dir_t */ dict_t *exports_map; /* Map of SuperFastHash(<export>) -> expdir */ }; +typedef struct exports_file exports_file_t; void exp_file_deinit (struct exports_file *expfile); diff --git a/xlators/nfs/server/src/mount3.c b/xlators/nfs/server/src/mount3.c index 2dbbc0fbc3b..0a3d79af6f0 100644 --- a/xlators/nfs/server/src/mount3.c +++ b/xlators/nfs/server/src/mount3.c @@ -1933,9 +1933,23 @@ mnt3_check_cached_fh (struct mount3_state *ms, struct nfs3_fh *fh, const char *host_addr, gf_boolean_t is_write_op) { if (!is_write_op) - return is_nfs_fh_cached (ms->authcache, fh, host_addr); + return auth_cache_allows_fh (ms->authcache, fh, host_addr); - return is_nfs_fh_cached_and_writeable (ms->authcache, fh, host_addr); + return auth_cache_allows_write_to_fh (ms->authcache, fh, host_addr); +} + +/** + * mnt3_check_cached_path -- Check if path is cached. + * + * Calls auxiliary functions based on whether we are checking + * a write operation. + * + */ +int +mnt3_check_cached_path (struct mount3_state *ms, const char *path, + const char *host_addr, gf_boolean_t is_write_op) +{ + return auth_cache_allows_path (ms->authcache, path, host_addr); } /** @@ -1969,7 +1983,7 @@ _mnt3_authenticate_req (struct mount3_state *ms, rpcsvc_request_t *req, char *pathdup = NULL; size_t dlen = 0; char *auth_host = NULL; - gf_boolean_t fh_cached = _gf_false; + auth_cache_status_t auth_cache_status = AUTH_CACHE_HOST_ENOENT; struct export_item *expitem = NULL; GF_VALIDATE_OR_GOTO (GF_MNT, ms, out); @@ -1990,12 +2004,24 @@ _mnt3_authenticate_req (struct mount3_state *ms, rpcsvc_request_t *req, } /* Check if the filehandle is cached */ - fh_cached = mnt3_check_cached_fh (ms, fh, host_addr_ip, is_write_op); - if (fh_cached) { - gf_msg_trace (GF_MNT, 0, "Found cached FH for %s", - host_addr_ip); + auth_cache_status = fh ? mnt3_check_cached_fh (ms, fh, host_addr_ip, + is_write_op) : + mnt3_check_cached_path (ms, path, host_addr_ip, + is_write_op); + + if (auth_cache_status == AUTH_CACHE_HOST_AUTH_OK) { + gf_log (GF_MNT, GF_LOG_TRACE, "Found authorized cached " + "FH for [%s]!", host_addr_ip); auth_status_code = 0; goto free_and_out; + } else if (auth_cache_status == AUTH_CACHE_HOST_EACCES) { + gf_log (GF_MNT, GF_LOG_TRACE, "Found de-authorized cached " + "FH for [%s]!", host_addr_ip); + auth_status_code = -EACCES; + goto free_and_out; + } else { + gf_log (GF_MNT, GF_LOG_TRACE, "Cached FH not found for [%s]!", + host_addr_ip); } /* Check if the IP is authorized */ @@ -2026,10 +2052,20 @@ _mnt3_authenticate_req (struct mount3_state *ms, rpcsvc_request_t *req, * host if they are null. */ if (!authorized_export || !authorized_host) { - /* Cache the file handle if it was authorized */ - if (fh && auth_status_code == 0) - cache_nfs_fh (ms->authcache, fh, host_addr_ip, expitem); + if (auth_status_code == 0) { + auth_cache_status = AUTH_CACHE_HOST_AUTH_OK; + } else { + auth_cache_status = AUTH_CACHE_HOST_EACCES; + } + if (fh) { + cache_nfs_fh (ms->authcache, fh, host_addr_ip, + expitem, auth_cache_status); + } + if (path) { + cache_nfs_path (ms->authcache, path, host_addr_ip, + expitem, auth_cache_status); + } goto free_and_out; } |
