diff --git a/src/box/alter.cc b/src/box/alter.cc
index cd20343e0cfec631e6cb71902d2f76fc3282d42c..e209f162fef272003d02535029080d2283ba932c 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
Binary files a/src/box/bootstrap.snap and b/src/box/bootstrap.snap differ
diff --git a/src/box/lua/net_box.lua b/src/box/lua/net_box.lua
index 48721f9f08dacfceb25515dad55430111c3cfc8f..e0c1c1f9616018989e6764d6ad3b861eed957cea 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 bc7cefa2c016b772c1e1b0c58615cdec1a51043c..128d9ed4241dc09fd669bbbcc9c1788473c78780 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 a3cf08af5c81ee659d2d440ad7020287acf8a324..9e51825866cd6b2c716b2d9d33fb5b8688376312 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 9120b9ed3403c0f6340161dd90c1faffa997f240..9ed1388576dc100bef044b438d67fcb8147ef4a6 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 478ef191fdd5c51418c4f3baccb17af7638e0945..e0e7cf1bda838c160a7e6970dd3f449de086dd00 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 a8d65465dfd656aa136e5e6457399b146075f992..bf5ca1f10e94f50901987447a4983b6fe2b965d3 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 6f0532658d8549157f5ef1b53c2213c4aff08c1a..0404326f1ffdfeee543bbc80b786aa60d46519c9 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 02471ad574c63171b89b45a310e392724c65167f..2a42136b3e8ea0f1718585f3d307e3b0391ebe40 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 3cc6a1d8fbce0a53ccd533d2cf45e8796ec8d33e..33a1bc0dc3a47b62b9e4297a3957a727cfbb58fa 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']