From ecb0e698dfb835d9ecde8cfc76a3189f53ae1a81 Mon Sep 17 00:00:00 2001 From: Sulverus <sulverus@gmail.com> Date: Mon, 22 Jun 2015 20:26:54 +0300 Subject: [PATCH] gh-844: Authentication trigger feature in iproto - add a test case for authentication trigger - pass user name to the trigger - invoke trigger before the current user has been changed - after review fixes --- src/box/authentication.cc | 3 + src/box/lua/session.cc | 19 ++++++ src/box/session.cc | 8 +++ src/box/session.h | 5 ++ src/lua/session.cc | 9 +++ src/session.cc | 1 + test-run | 2 +- test/box/auth.result | 133 ++++++++++++++++++++++++++++++++++++++ test/box/auth.test.lua | 54 ++++++++++++++++ 9 files changed, 233 insertions(+), 1 deletion(-) create mode 100644 test/box/auth.result create mode 100644 test/box/auth.test.lua diff --git a/src/box/authentication.cc b/src/box/authentication.cc index dfdf8aaf7b..5d5c9b1045 100644 --- a/src/box/authentication.cc +++ b/src/box/authentication.cc @@ -69,6 +69,9 @@ authenticate(const char *user_name, uint32_t len, if (scramble_check(scramble, session->salt, user->hash2)) tnt_raise(ClientError, ER_PASSWORD_MISMATCH, user->name); + /* check and run auth triggers on success */ + if (! rlist_empty(&session_on_auth)) + session_run_on_auth_triggers(user->name); ok: credentials_init(&session->credentials, user); } diff --git a/src/box/lua/session.cc b/src/box/lua/session.cc index 082c53a9a1..1021b22c61 100644 --- a/src/box/lua/session.cc +++ b/src/box/lua/session.cc @@ -211,6 +211,17 @@ lbox_session_run_trigger(struct trigger *trigger, void * /* event */) lbox_call(L, 0, 0); } +static void +lbox_session_run_auth_trigger(struct trigger *trigger, void *event) +{ + lua_State *L = lua_newthread(tarantool_L); + LuarefGuard coro_guard(tarantool_L); + lua_rawgeti(L, LUA_REGISTRYINDEX, (intptr_t) trigger->data); + /* now only the user name comes in as an on_auth argument */ + lua_pushstring(L, (const char *)event); + lbox_call(L, 1, 0); +} + static int lbox_session_on_connect(struct lua_State *L) { @@ -225,6 +236,13 @@ lbox_session_on_disconnect(struct lua_State *L) lbox_session_run_trigger); } +static int +lbox_session_on_auth(struct lua_State *L) +{ + return lbox_trigger_reset(L, 2, &session_on_auth, + lbox_session_run_auth_trigger); +} + void session_storage_cleanup(int sid) { @@ -270,6 +288,7 @@ box_lua_session_init(struct lua_State *L) {"peer", lbox_session_peer}, {"on_connect", lbox_session_on_connect}, {"on_disconnect", lbox_session_on_disconnect}, + {"on_auth", lbox_session_on_auth}, {NULL, NULL} }; luaL_register_module(L, sessionlib_name, sessionlib); diff --git a/src/box/session.cc b/src/box/session.cc index 607f0d7597..8f18cca194 100644 --- a/src/box/session.cc +++ b/src/box/session.cc @@ -42,6 +42,7 @@ struct mempool session_pool; RLIST_HEAD(session_on_connect); RLIST_HEAD(session_on_disconnect); +RLIST_HEAD(session_on_auth); static inline uint32_t sid_max() @@ -137,6 +138,7 @@ session_run_on_disconnect_triggers(struct session *session) void session_run_on_connect_triggers(struct session *session) { + /* Run on_connect with admin credentals */ struct fiber *fiber = fiber(); fiber_set_session(fiber, session); fiber_set_user(fiber, &admin_credentials); @@ -144,6 +146,12 @@ session_run_on_connect_triggers(struct session *session) /* Set session user to guest, until it is authenticated. */ } +void +session_run_on_auth_triggers(const char *user_name) +{ + trigger_run(&session_on_auth, (void *)user_name); +} + void session_destroy(struct session *session) { diff --git a/src/box/session.h b/src/box/session.h index 09a9ea34a5..b78f566b7a 100644 --- a/src/box/session.h +++ b/src/box/session.h @@ -120,6 +120,11 @@ extern struct rlist session_on_disconnect; void session_run_on_disconnect_triggers(struct session *session); +extern struct rlist session_on_auth; + +void +session_run_on_auth_triggers(const char *user_name); + void session_init(); diff --git a/src/lua/session.cc b/src/lua/session.cc index 8d14d3c007..c544e8fb54 100644 --- a/src/lua/session.cc +++ b/src/lua/session.cc @@ -101,6 +101,8 @@ static struct lbox_session_trigger on_connect = { &session_on_connect, LUA_NOREF}; static struct lbox_session_trigger on_disconnect = { &session_on_disconnect, LUA_NOREF}; +static struct lbox_session_trigger on_auth = + { &session_on_auth, LUA_NOREF}; static void lbox_session_run_trigger(void *param) @@ -176,6 +178,12 @@ lbox_session_on_disconnect(struct lua_State *L) return lbox_session_set_trigger(L, &on_disconnect); } +static int +lbox_session_on_auth(struct lua_State *L) +{ + return lbox_session_set_trigger(L, &on_auth); +} + void session_storage_cleanup(int sid) { @@ -203,6 +211,7 @@ static const struct luaL_reg sessionlib[] = { {"peer", lbox_session_peer}, {"on_connect", lbox_session_on_connect}, {"on_disconnect", lbox_session_on_disconnect}, + {"on_auth", lbox_session_on_auth}, {NULL, NULL} }; diff --git a/src/session.cc b/src/session.cc index 9abdc1acef..17a746c602 100644 --- a/src/session.cc +++ b/src/session.cc @@ -39,6 +39,7 @@ static struct mh_i32ptr_t *session_registry; struct session_trigger session_on_connect; struct session_trigger session_on_disconnect; +struct session_trigger session_on_auth; uint32_t session_create(int fd, uint64_t cookie) diff --git a/test-run b/test-run index 7a9dffa16d..6b4dcd6712 160000 --- a/test-run +++ b/test-run @@ -1 +1 @@ -Subproject commit 7a9dffa16d0da05ec33fe0b131e92f6d86a87fd6 +Subproject commit 6b4dcd67126709a92e722a62c8a87a6ec90ceb0f diff --git a/test/box/auth.result b/test/box/auth.result new file mode 100644 index 0000000000..478ef191fd --- /dev/null +++ b/test/box/auth.result @@ -0,0 +1,133 @@ +session = box.session +--- +... +fiber = require('fiber') +--- +... +space = box.schema.space.create('tweedledum') +--- +... +index = space:create_index('primary', { type = 'hash' }) +--- +... +box.schema.user.create('test', {password='pass'}) +--- +... +box.schema.user.grant('test', 'read,write,execute', 'universe') +--- +... +box.schema.user.grant('guest', 'read,write,execute', 'universe') +--- +... +-- check how authentication trigger work +-- no args trigger +function auth_trigger() counter = counter + 1 end +--- +... +-- get user name as argument +function auth_trigger2(user_name) msg = 'user ' .. user_name .. ' is there' end +--- +... +net = { box = require('net.box') } +--- +... +-- set trigger +handle = session.on_auth(auth_trigger) +--- +... +-- check handle +type(handle) +--- +- function +... +-- check triggers list +#session.on_auth() +--- +- 1 +... +handle2 = session.on_auth(auth_trigger2) +--- +... +counter = 0 +--- +... +msg = '' +--- +... +LISTEN = require('uri').parse(box.cfg.listen) +--- +... +-- check connection with authentication(counter must be incremented) +c = net.box:new('test:pass@' .. LISTEN.host .. ':' .. LISTEN.service) +--- +... +while counter < 1 do fiber.sleep(0.001) end +--- +... +counter +--- +- 1 +... +msg +--- +- user test is there +... +-- check guest connection without authentication(no increment) +c1 = net.box:new(LISTEN.host, LISTEN.service) +--- +... +c1:ping() +--- +- true +... +counter +--- +- 1 +... +-- cleanup +c:close() +--- +... +c1:close() +--- +... +session.on_auth(nil, auth_trigger) +--- +... +session.on_auth(nil, auth_trigger2) +--- +... +session.on_auth() +--- +- [] +... +space:drop() +--- +... +session.uid() +--- +- 1 +... +session.user() +--- +- admin +... +session.sync() +--- +- 0 +... +session = nil +--- +... +fiber = nil +--- +... +box.schema.user.revoke('guest', 'read,write,execute', 'universe') +--- +... +box.schema.user.revoke('test', 'read,write,execute', 'universe') +--- +... +box.schema.user.drop('test', { if_exists = true}) +--- +... diff --git a/test/box/auth.test.lua b/test/box/auth.test.lua new file mode 100644 index 0000000000..a8d65465df --- /dev/null +++ b/test/box/auth.test.lua @@ -0,0 +1,54 @@ +session = box.session +fiber = require('fiber') + +space = box.schema.space.create('tweedledum') +index = space:create_index('primary', { type = 'hash' }) +box.schema.user.create('test', {password='pass'}) +box.schema.user.grant('test', 'read,write,execute', 'universe') +box.schema.user.grant('guest', 'read,write,execute', 'universe') + +-- check how authentication trigger work +-- no args trigger +function auth_trigger() counter = counter + 1 end +-- get user name as argument +function auth_trigger2(user_name) msg = 'user ' .. user_name .. ' is there' end +net = { box = require('net.box') } + +-- set trigger +handle = session.on_auth(auth_trigger) +-- check handle +type(handle) +-- check triggers list +#session.on_auth() +handle2 = session.on_auth(auth_trigger2) +counter = 0 +msg = '' + +LISTEN = require('uri').parse(box.cfg.listen) + +-- check connection with authentication(counter must be incremented) +c = net.box:new('test:pass@' .. LISTEN.host .. ':' .. LISTEN.service) +while counter < 1 do fiber.sleep(0.001) end +counter +msg + +-- check guest connection without authentication(no increment) +c1 = net.box:new(LISTEN.host, LISTEN.service) +c1:ping() +counter + +-- cleanup +c:close() +c1:close() +session.on_auth(nil, auth_trigger) +session.on_auth(nil, auth_trigger2) +session.on_auth() +space:drop() +session.uid() +session.user() +session.sync() +session = nil +fiber = nil +box.schema.user.revoke('guest', 'read,write,execute', 'universe') +box.schema.user.revoke('test', 'read,write,execute', 'universe') +box.schema.user.drop('test', { if_exists = true}) -- GitLab