Skip to content

Commit

Permalink
access: rework struct credentials API
Browse files Browse the repository at this point in the history
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 link all struct credentials of a user into a list
via which the user will be able to keep the credentials up to
date.

Part of #2763
  • Loading branch information
Gerold103 committed Oct 29, 2019
1 parent c17c10a commit a8c3ebd
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 23 deletions.
3 changes: 1 addition & 2 deletions src/box/authentication.cc
Expand Up @@ -100,6 +100,5 @@ authenticate(const char *user_name, uint32_t len, const char *salt,
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);
}
9 changes: 4 additions & 5 deletions src/box/func.c
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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
Expand All @@ -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);
}
Expand Down
6 changes: 3 additions & 3 deletions src/box/lua/session.c
Expand Up @@ -185,22 +185,22 @@ 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 */
luaL_checktype(L, 2, LUA_TFUNCTION);
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);
Expand Down
10 changes: 5 additions & 5 deletions src/box/session.cc
Expand Up @@ -143,8 +143,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;
Expand Down Expand Up @@ -173,8 +172,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()
Expand Down Expand Up @@ -233,6 +231,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);
}

Expand All @@ -253,7 +252,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
Expand All @@ -279,6 +278,7 @@ session_free()
{
if (session_registry)
mh_i64ptr_delete(session_registry);
credentials_destroy(&admin_credentials);
}

int
Expand Down
8 changes: 0 additions & 8 deletions src/box/session.h
Expand Up @@ -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
Expand Down
22 changes: 22 additions & 0 deletions src/box/user.cc
Expand Up @@ -749,3 +749,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;
}
27 changes: 27 additions & 0 deletions src/box/user.h
Expand Up @@ -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" */

Expand Down

0 comments on commit a8c3ebd

Please sign in to comment.