From 076a842011e09c84c25fb5e68f1b23c9917a3750 Mon Sep 17 00:00:00 2001 From: Konstantin Nazarov <mail@racktear.com> Date: Fri, 1 Jul 2016 15:55:32 +0300 Subject: [PATCH] Permit empty passwords in net.box This is required to do the following: tarantoolctl user@host tarantoolctl guest@host tarantoolctl guest:@host Currently all of those will lead to error from net.box. Either because password is not specified, or because guest user can't login with empty password. This change effectively sets guest password to an empty string, to make it less of a special case to authentication. And since now guest can be authenticated with an empty password, net.box will replace nil passwords with empty strings, when user name is provided. We still support the case when username=nil and password=nil. In this case net.box doesn't send authentication packet at all. Guest login is just assumed. The bootstrap snapshot will now have guest user with an empty password, instead of no password. Fixes #1545 --- src/box/alter.cc | 14 +++- src/box/bootstrap.snap | Bin 4925 -> 4965 bytes src/box/lua/net_box.lua | 3 +- src/box/lua/upgrade.lua | 16 +++++ test/box-py/bootstrap.result | 4 +- test/box/access_misc.result | 2 +- test/box/auth.result | 136 +++++++++++++++++++++++++++++++++-- test/box/auth.test.lua | 49 ++++++++++++- test/box/net.box.result | 31 ++++++-- test/box/net.box.test.lua | 14 ++-- test/xlog/upgrade.result | 4 +- 11 files changed, 249 insertions(+), 24 deletions(-) diff --git a/src/box/alter.cc b/src/box/alter.cc index cd20343e0c..e209f162fe 100644 --- a/src/box/alter.cc +++ b/src/box/alter.cc @@ -79,6 +79,12 @@ /** _func columns */ #define FUNC_LANGUAGE 4 +/** + * chap-sha1 of empty string, i.e. + * base64_encode(sha1(sha1("")) + */ +#define CHAP_SHA1_EMPTY_PASSWORD "vhvewKp0tNyweZQ+cFKAlsyphfg=" + /* {{{ Auxiliary functions and methods. */ void @@ -1509,6 +1515,12 @@ user_def_fill_auth_data(struct user_def *user, const char *auth_data) tnt_raise(ClientError, ER_CREATE_USER, user->name, "invalid user password"); } + if (user->uid == GUEST) { + /** Guest user is permitted to have empty password */ + if (strncmp(hash2_base64, CHAP_SHA1_EMPTY_PASSWORD, len)) + tnt_raise(ClientError, ER_GUEST_USER_PASSWORD); + } + base64_decode(hash2_base64, len, user->hash2, sizeof(user->hash2)); break; @@ -1549,8 +1561,6 @@ user_def_create_from_tuple(struct user_def *user, struct tuple *tuple) tnt_raise(ClientError, ER_CREATE_ROLE, user->name, "authentication " "data can not be set for a role"); - if (user->uid == GUEST) - tnt_raise(ClientError, ER_GUEST_USER_PASSWORD); } user_def_fill_auth_data(user, auth_data); } diff --git a/src/box/bootstrap.snap b/src/box/bootstrap.snap index 34378bae7f3b1dda8c715d8cef73eab048982bb7..4bdaf0187f31436f4fa3a4c47171de679ba0d63a 100644 GIT binary patch delta 312 zcmdn1_EfDt*v~P5%RtZ2h$}d?s4TU}O2IJI!X(i&DOESk+#*TWB+W8SH_^z<RM*5T z(Kyv8&D6}?z>q7<IVV3k+e)F@&`QCemW%7^F7DMf4Cf|2YMi+|00NpAn3x%x1kN!q zFbXJ6TArL!T3nJ^bW<fYG0`l=$TCGY+04j99B8aTlCEW%xuvd|nW<??im7?Bsgc3N zX+|u{=>l;R&&V^eGi-d@&L8B=aIVte?33lo5XKuoj5ko6%D}iZy)?DBWJzgpYEk3L z<c!1u-QtWy!#!mgWvS)f1qLO4mF1~Xf!fJ#-i|rNl?54T>9(8a2}CimJm{LuIr)!} Nqy{k_zbdfyEdcj&WeNZQ delta 292 zcmaE=wpXn_*v~P5%RtZ2h$}d?s4TU}N+HR>JjL81F-_MrG1)}d#30RB*U~gONjEVy zIWg7LJk7u)#f&S=IVV3k+e)F@&`QCemW%7^F7DMf4CjJ>zM8l^00NpAn3x%x1kN!q zFbXJ6TArL!T3nJ^bW_DV%`(Nr%)mm|$kaSlT-U@jDOK0PA~8kR#3;?g%*@E##Lzr( z;xr?cT{0J*O*|vd#Ky7lZ9Bh~G{d>8AKVWuUxqN=0Ajp>;uHqPrRk-q#U)Ehi&Kj> g9}|dTa&@1QvJY9Y9YnE%;v~kKD#Up5s=(T}03qaFH~;_u diff --git a/src/box/lua/net_box.lua b/src/box/lua/net_box.lua index 48721f9f08..e0c1c1f961 100644 --- a/src/box/lua/net_box.lua +++ b/src/box/lua/net_box.lua @@ -335,8 +335,7 @@ local remote_methods = { end if self.opts.user ~= nil and self.opts.password == nil then - box.error(box.error.PROC_LUA, - "net.box: password is not defined") + self.opts.password = "" end if self.opts.user == nil and self.opts.password ~= nil then box.error(box.error.PROC_LUA, diff --git a/src/box/lua/upgrade.lua b/src/box/lua/upgrade.lua index bc7cefa2c0..128d9ed424 100644 --- a/src/box/lua/upgrade.lua +++ b/src/box/lua/upgrade.lua @@ -469,6 +469,21 @@ local function upgrade_to_1_6_8() box.space._schema:replace({'version', 1, 6, 8}) end +local function upgrade_users_to_1_7_0() + box.schema.user.passwd('guest', '') +end + +local function upgrade_to_1_7_0() + if VERSION_ID >= version_id(1, 7, 0) then + return + end + + upgrade_users_to_1_7_0() + + log.info("set schema version to 1.7.0") + box.space._schema:replace({'version', 1, 7, 0}) +end + -------------------------------------------------------------------------------- local function upgrade() @@ -483,6 +498,7 @@ local function upgrade() VERSION_ID = version_id(major, minor, patch) upgrade_to_1_6_8() + upgrade_to_1_7_0() end local function bootstrap() diff --git a/test/box-py/bootstrap.result b/test/box-py/bootstrap.result index a3cf08af5c..9e51825866 100644 --- a/test/box-py/bootstrap.result +++ b/test/box-py/bootstrap.result @@ -5,7 +5,7 @@ box.space._schema:select{} --- - - ['cluster', '<cluster uuid>'] - ['max_id', 511] - - ['version', 1, 6, 8] + - ['version', 1, 7, 0] ... box.space._cluster:select{} --- @@ -83,7 +83,7 @@ box.space._index:select{} ... box.space._user:select{} --- -- - [0, 1, 'guest', 'user'] +- - [0, 1, 'guest', 'user', {'chap-sha1': 'vhvewKp0tNyweZQ+cFKAlsyphfg='}] - [1, 1, 'admin', 'user'] - [2, 1, 'public', 'role'] - [3, 1, 'replication', 'role'] diff --git a/test/box/access_misc.result b/test/box/access_misc.result index 9120b9ed34..9ed1388576 100644 --- a/test/box/access_misc.result +++ b/test/box/access_misc.result @@ -573,7 +573,7 @@ s:drop() ... box.space._user:select() --- -- - [0, 1, 'guest', 'user'] +- - [0, 1, 'guest', 'user', {'chap-sha1': 'vhvewKp0tNyweZQ+cFKAlsyphfg='}] - [1, 1, 'admin', 'user'] - [2, 1, 'public', 'role'] - [3, 1, 'replication', 'role'] diff --git a/test/box/auth.result b/test/box/auth.result index 478ef191fd..e0e7cf1bda 100644 --- a/test/box/auth.result +++ b/test/box/auth.result @@ -16,6 +16,12 @@ box.schema.user.create('test', {password='pass'}) box.schema.user.grant('test', 'read,write,execute', 'universe') --- ... +box.schema.user.create('test2', {password=''}) +--- +... +box.schema.user.grant('test2', 'read,write,execute', 'universe') +--- +... box.schema.user.grant('guest', 'read,write,execute', 'universe') --- ... @@ -48,9 +54,6 @@ type(handle) handle2 = session.on_auth(auth_trigger2) --- ... -counter = 0 ---- -... msg = '' --- ... @@ -58,6 +61,9 @@ LISTEN = require('uri').parse(box.cfg.listen) --- ... -- check connection with authentication(counter must be incremented) +counter = 0 +--- +... c = net.box:new('test:pass@' .. LISTEN.host .. ':' .. LISTEN.service) --- ... @@ -72,7 +78,129 @@ msg --- - user test is there ... +counter = 0 +--- +... +c = net.box:new('test2:@' .. LISTEN.host .. ':' .. LISTEN.service) +--- +... +while counter < 1 do fiber.sleep(0.001) end +--- +... +counter +--- +- 1 +... +msg +--- +- user test2 is there +... +counter = 0 +--- +... +c = net.box:new('test2@' .. LISTEN.host .. ':' .. LISTEN.service) +--- +... +while counter < 1 do fiber.sleep(0.001) end +--- +... +counter +--- +- 1 +... +msg +--- +- user test2 is there +... +counter = 0 +--- +... +c1 = net.box:new(LISTEN.host, LISTEN.service, {user='test2'}) +--- +... +while counter < 1 do fiber.sleep(0.001) end +--- +... +counter +--- +- 1 +... +msg +--- +- user test2 is there +... +counter = 0 +--- +... +c1 = net.box:new('guest@' .. LISTEN.host .. ':' .. LISTEN.service) +--- +... +while counter < 1 do fiber.sleep(0.001) end +--- +... +counter +--- +- 1 +... +msg +--- +- user guest is there +... +counter = 0 +--- +... +c1 = net.box:new('guest:@' .. LISTEN.host .. ':' .. LISTEN.service) +--- +... +while counter < 1 do fiber.sleep(0.001) end +--- +... +counter +--- +- 1 +... +msg +--- +- user guest is there +... +counter = 0 +--- +... +c1 = net.box:new(LISTEN.host, LISTEN.service, {user='guest', password=''}) +--- +... +while counter < 1 do fiber.sleep(0.001) end +--- +... +counter +--- +- 1 +... +msg +--- +- user guest is there +... +counter = 0 +--- +... +c1 = net.box:new(LISTEN.host, LISTEN.service, {user='guest'}) +--- +... +while counter < 1 do fiber.sleep(0.001) end +--- +... +counter +--- +- 1 +... +msg +--- +- user guest is there +... -- check guest connection without authentication(no increment) +counter = 0 +--- +... c1 = net.box:new(LISTEN.host, LISTEN.service) --- ... @@ -82,7 +210,7 @@ c1:ping() ... counter --- -- 1 +- 0 ... -- cleanup c:close() diff --git a/test/box/auth.test.lua b/test/box/auth.test.lua index a8d65465df..bf5ca1f10e 100644 --- a/test/box/auth.test.lua +++ b/test/box/auth.test.lua @@ -5,6 +5,8 @@ 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.create('test2', {password=''}) +box.schema.user.grant('test2', 'read,write,execute', 'universe') box.schema.user.grant('guest', 'read,write,execute', 'universe') -- check how authentication trigger work @@ -21,18 +23,63 @@ 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) +counter = 0 c = net.box:new('test:pass@' .. LISTEN.host .. ':' .. LISTEN.service) while counter < 1 do fiber.sleep(0.001) end counter msg +counter = 0 +c = net.box:new('test2:@' .. LISTEN.host .. ':' .. LISTEN.service) +while counter < 1 do fiber.sleep(0.001) end +counter +msg + +counter = 0 +c = net.box:new('test2@' .. LISTEN.host .. ':' .. LISTEN.service) +while counter < 1 do fiber.sleep(0.001) end +counter +msg + +counter = 0 +c1 = net.box:new(LISTEN.host, LISTEN.service, {user='test2'}) +while counter < 1 do fiber.sleep(0.001) end +counter +msg + +counter = 0 +c1 = net.box:new('guest@' .. LISTEN.host .. ':' .. LISTEN.service) +while counter < 1 do fiber.sleep(0.001) end +counter +msg + +counter = 0 +c1 = net.box:new('guest:@' .. LISTEN.host .. ':' .. LISTEN.service) +while counter < 1 do fiber.sleep(0.001) end +counter +msg + +counter = 0 +c1 = net.box:new(LISTEN.host, LISTEN.service, {user='guest', password=''}) +while counter < 1 do fiber.sleep(0.001) end +counter +msg + +counter = 0 +c1 = net.box:new(LISTEN.host, LISTEN.service, {user='guest'}) +while counter < 1 do fiber.sleep(0.001) end +counter +msg + + -- check guest connection without authentication(no increment) +counter = 0 c1 = net.box:new(LISTEN.host, LISTEN.service) c1:ping() counter diff --git a/test/box/net.box.result b/test/box/net.box.result index 6f0532658d..0404326f1f 100644 --- a/test/box/net.box.result +++ b/test/box/net.box.result @@ -767,15 +767,28 @@ cnc:console('a = {1, 2, 3, 4}; return a[3]') ' ... --- #545 user or password is not defined -remote:new(LISTEN.host, LISTEN.service, { user = 'test' }) +-- #1545 empty password +cn = remote:new(LISTEN.host, LISTEN.service, { user = 'test' }) --- -- error: 'net.box: password is not defined' ... -remote:new(LISTEN.host, LISTEN.service, { password = 'test' }) +cn ~= nil +--- +- true +... +cn:close() +--- +... +cn = remote:new(LISTEN.host, LISTEN.service, { password = 'test' }) --- - error: 'net.box: user is not defined' ... +cn ~= nil +--- +- true +... +cn:close() +--- +... -- #544 usage for remote[point]method cn = remote:new(LISTEN.host, LISTEN.service) --- @@ -820,9 +833,15 @@ cn:close() uri = string.format('%s@%s:%s', 'netbox', LISTEN.host, LISTEN.service) --- ... -remote.new(uri) +cn = remote.new(uri) +--- +... +cn ~= nil +--- +- true +... +cn:close() --- -- error: 'net.box: password is not defined' ... cn = remote.new(uri, { password = 'test' }) --- diff --git a/test/box/net.box.test.lua b/test/box/net.box.test.lua index 02471ad574..2a42136b3e 100644 --- a/test/box/net.box.test.lua +++ b/test/box/net.box.test.lua @@ -287,9 +287,13 @@ cnc:console('return 1, 2, 3, "string", nil') cnc:console('error("test")') cnc:console('a = {1, 2, 3, 4}; return a[3]') --- #545 user or password is not defined -remote:new(LISTEN.host, LISTEN.service, { user = 'test' }) -remote:new(LISTEN.host, LISTEN.service, { password = 'test' }) +-- #1545 empty password +cn = remote:new(LISTEN.host, LISTEN.service, { user = 'test' }) +cn ~= nil +cn:close() +cn = remote:new(LISTEN.host, LISTEN.service, { password = 'test' }) +cn ~= nil +cn:close() -- #544 usage for remote[point]method cn = remote:new(LISTEN.host, LISTEN.service) @@ -313,7 +317,9 @@ cn:ping() cn:close() uri = string.format('%s@%s:%s', 'netbox', LISTEN.host, LISTEN.service) -remote.new(uri) +cn = remote.new(uri) +cn ~= nil +cn:close() cn = remote.new(uri, { password = 'test' }) cn:ping() cn:close() diff --git a/test/xlog/upgrade.result b/test/xlog/upgrade.result index 3cc6a1d8fb..33a1bc0dc3 100644 --- a/test/xlog/upgrade.result +++ b/test/xlog/upgrade.result @@ -36,7 +36,7 @@ box.space._schema:select() --- - - ['cluster', '<server_uuid>'] - ['max_id', 513] - - ['version', 1, 6, 8] + - ['version', 1, 7, 0] ... box.space._space:select() --- @@ -116,7 +116,7 @@ box.space._index:select() ... box.space._user:select() --- -- - [0, 1, 'guest', 'user'] +- - [0, 1, 'guest', 'user', {'chap-sha1': 'vhvewKp0tNyweZQ+cFKAlsyphfg='}] - [1, 1, 'admin', 'user'] - [2, 1, 'public', 'role'] - [3, 1, 'replication', 'role'] -- GitLab