[tarantool-patches] [PATCH v2 1/2] access: rework struct credentials API
Vladislav Shpilevoy
v.shpilevoy at tarantool.org
Sat Oct 5 01:25:59 MSK 2019
Struct credentials is a cache of user's universal privileges. It
is static and is never changed after creation. That is a problem.
If a user privileges are updated, it is not reflected in his
existing credentials caches.
This patch reworks credentials API so as now this struct is not
just a container for several numbers. It is an object with
standard methods like create(), destroy(). A credentials object
still is not updated together with its source user, but now at
least the API allows to fix that.
Next patch will add a trigger to struct credentials to catch user
privilege changes and update the cache.
Part of #2763
---
src/box/authentication.cc | 3 +--
src/box/func.c | 9 ++++-----
src/box/lua/session.c | 6 +++---
src/box/session.cc | 10 +++++-----
src/box/session.h | 8 --------
src/box/user.cc | 22 ++++++++++++++++++++++
src/box/user.h | 27 +++++++++++++++++++++++++++
7 files changed, 62 insertions(+), 23 deletions(-)
diff --git a/src/box/authentication.cc b/src/box/authentication.cc
index fdad7395a..a7a3587f7 100644
--- a/src/box/authentication.cc
+++ b/src/box/authentication.cc
@@ -100,6 +100,5 @@ ok:
if (! rlist_empty(&session_on_auth) &&
session_run_on_auth_triggers(&auth_res) != 0)
diag_raise();
- credentials_init(&session->credentials, user->auth_token,
- user->def->uid);
+ credentials_reset(&session->credentials, user);
}
diff --git a/src/box/func.c b/src/box/func.c
index e8cc99081..c94ca4974 100644
--- a/src/box/func.c
+++ b/src/box/func.c
@@ -418,7 +418,7 @@ func_new(struct func_def *def)
* Later on consistency of the cache is ensured by DDL
* checks (see user_has_data()).
*/
- func->owner_credentials.auth_token = BOX_USER_MAX; /* invalid value */
+ credentials_create_empty(&func->owner_credentials);
return func;
}
@@ -549,6 +549,7 @@ func_delete(struct func *func)
{
struct func_def *def = func->def;
func->vtab->destroy(func);
+ credentials_destroy(&func->owner_credentials);
free(def);
}
@@ -598,7 +599,7 @@ func_call(struct func *base, struct port *args, struct port *ret)
if (base->def->setuid) {
orig_credentials = effective_user();
/* Remember and change the current user id. */
- if (base->owner_credentials.auth_token >= BOX_USER_MAX) {
+ if (credentials_is_empty(&base->owner_credentials)) {
/*
* Fill the cache upon first access, since
* when func is created, no user may
@@ -608,9 +609,7 @@ func_call(struct func *base, struct port *args, struct port *ret)
struct user *owner = user_find(base->def->uid);
if (owner == NULL)
return -1;
- credentials_init(&base->owner_credentials,
- owner->auth_token,
- owner->def->uid);
+ credentials_reset(&base->owner_credentials, owner);
}
fiber_set_user(fiber(), &base->owner_credentials);
}
diff --git a/src/box/lua/session.c b/src/box/lua/session.c
index b9495e7a6..de5eb9adc 100644
--- a/src/box/lua/session.c
+++ b/src/box/lua/session.c
@@ -185,15 +185,14 @@ lbox_session_su(struct lua_State *L)
luaT_error(L);
if (top == 1) {
- credentials_init(&session->credentials, user->auth_token,
- user->def->uid);
+ credentials_reset(&session->credentials, user);
fiber_set_user(fiber(), &session->credentials);
return 0; /* su */
}
struct credentials su_credentials;
struct credentials *old_credentials = fiber()->storage.credentials;
- credentials_init(&su_credentials, user->auth_token, user->def->uid);
+ credentials_create(&su_credentials, user);
fiber()->storage.credentials = &su_credentials;
/* sudo */
@@ -201,6 +200,7 @@ lbox_session_su(struct lua_State *L)
int error = lua_pcall(L, top - 2, LUA_MULTRET, 0);
/* Restore the original credentials. */
fiber_set_user(fiber(), old_credentials);
+ credentials_destroy(&su_credentials);
if (error)
lua_error(L);
diff --git a/src/box/session.cc b/src/box/session.cc
index 59bf226dd..93d4eb948 100644
--- a/src/box/session.cc
+++ b/src/box/session.cc
@@ -142,8 +142,7 @@ session_create(enum session_type type)
session->sql_default_engine = SQL_STORAGE_ENGINE_MEMTX;
/* For on_connect triggers. */
- credentials_init(&session->credentials, guest_user->auth_token,
- guest_user->def->uid);
+ credentials_create(&session->credentials, guest_user);
struct mh_i64ptr_node_t node;
node.key = session->id;
node.val = session;
@@ -172,8 +171,7 @@ session_create_on_demand()
};
/* Add a trigger to destroy session on fiber stop */
trigger_add(&fiber()->on_stop, &s->fiber_on_stop);
- credentials_init(&s->credentials, admin_user->auth_token,
- admin_user->def->uid);
+ credentials_reset(&s->credentials, admin_user);
/*
* At bootstrap, admin user access is not loaded yet (is
* 0), force global access. @sa comment in session_init()
@@ -232,6 +230,7 @@ session_destroy(struct session *session)
session_storage_cleanup(session->id);
struct mh_i64ptr_node_t node = { session->id, NULL };
mh_i64ptr_remove(session_registry, &node, NULL);
+ credentials_destroy(&session->credentials);
mempool_free(&session_pool, session);
}
@@ -252,7 +251,7 @@ session_init()
if (session_registry == NULL)
panic("out of memory");
mempool_create(&session_pool, &cord()->slabc, sizeof(struct session));
- credentials_init(&admin_credentials, ADMIN, ADMIN);
+ credentials_create(&admin_credentials, admin_user);
/*
* For performance reasons, we do not always explicitly
* look at user id in access checks, while still need to
@@ -278,6 +277,7 @@ session_free()
{
if (session_registry)
mh_i64ptr_delete(session_registry);
+ credentials_destroy(&admin_credentials);
}
int
diff --git a/src/box/session.h b/src/box/session.h
index 85a2d940b..eff3d7a67 100644
--- a/src/box/session.h
+++ b/src/box/session.h
@@ -193,14 +193,6 @@ fiber_set_session(struct fiber *fiber, struct session *session)
fiber->storage.session = session;
}
-static inline void
-credentials_init(struct credentials *cr, uint8_t auth_token, uint32_t uid)
-{
- cr->auth_token = auth_token;
- cr->universal_access = universe.access[cr->auth_token].effective;
- cr->uid = uid;
-}
-
/*
* For use in local hot standby, which runs directly
* from ev watchers (without current fiber), but needs
diff --git a/src/box/user.cc b/src/box/user.cc
index c46ff67d1..f12d65d27 100644
--- a/src/box/user.cc
+++ b/src/box/user.cc
@@ -714,3 +714,25 @@ priv_grant(struct user *grantee, struct priv_def *priv)
}
/** }}} */
+
+void
+credentials_create(struct credentials *cr, struct user *user)
+{
+ cr->auth_token = user->auth_token;
+ cr->universal_access = universe.access[user->auth_token].effective;
+ cr->uid = user->def->uid;
+}
+
+void
+credentials_create_empty(struct credentials *cr)
+{
+ cr->auth_token = BOX_USER_MAX;
+ cr->universal_access = 0;
+ cr->uid = BOX_USER_MAX;
+}
+
+void
+credentials_destroy(struct credentials *cr)
+{
+ (void) cr;
+}
diff --git a/src/box/user.h b/src/box/user.h
index 527fb2e7c..5f320f739 100644
--- a/src/box/user.h
+++ b/src/box/user.h
@@ -106,6 +106,33 @@ user_find_by_name(const char *name, uint32_t len);
struct user *
user_find(uint32_t uid);
+/** Create a cache of user's privileges in @a cr. */
+void
+credentials_create(struct credentials *cr, struct user *user);
+
+/** Create a dummy credentials cache without a user. */
+void
+credentials_create_empty(struct credentials *cr);
+
+/** Check if @a cr has a source user. */
+static inline bool
+credentials_is_empty(const struct credentials *cr)
+{
+ return cr->auth_token == BOX_USER_MAX;
+}
+
+/** Free credentials resources, invalidate the object. */
+void
+credentials_destroy(struct credentials *cr);
+
+/** Change source user of the credentials cache. */
+static inline void
+credentials_reset(struct credentials *cr, struct user *new_user)
+{
+ credentials_destroy(cr);
+ credentials_create(cr, new_user);
+}
+
#if defined(__cplusplus)
} /* extern "C" */
--
2.21.0 (Apple Git-122)
More information about the Tarantool-patches
mailing list