From 9219c029a7cac6124b2bd61d39536c542cd572eb Mon Sep 17 00:00:00 2001
From: Konstantin Osipov <kostja@tarantool.org>
Date: Thu, 20 Nov 2014 22:47:13 +0300
Subject: [PATCH] Allow GUEST user to pass authentication request without a
 password.

If no password is set for GUEST user, allow a client
to authenticate to GUEST.

For all other users, no password means that it's only possible to become
such user with session.su() or inside a setuid function.

The exception for GUEST user is useful for connection
pooling, where we would like to "reset" a connection to its
default, non-authenticated state, when returning it to the pool.
---
 src/box/authentication.cc | 21 ++++++++++++++++++---
 src/box/user_cache.h      |  2 +-
 2 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/src/box/authentication.cc b/src/box/authentication.cc
index b35669ad64..cb8414d1f7 100644
--- a/src/box/authentication.cc
+++ b/src/box/authentication.cc
@@ -30,21 +30,35 @@
 #include "user_def.h"
 #include "session.h"
 
+static char zero_hash[SCRAMBLE_SIZE];
+
 void
 authenticate(const char *user_name, uint32_t len,
 	     const char *tuple, const char * /* tuple_end */)
 {
 	struct user_def *user = user_cache_find_by_name(user_name, len);
 	struct session *session = current_session();
-	uint32_t part_count = mp_decode_array(&tuple);
+	uint32_t part_count;
+	uint32_t scramble_len;
+	const char *scramble;
+	/*
+	 * Allow authenticating back to GUEST user without
+	 * checking a password. This is useful for connection
+	 * pooling.
+	 */
+	if (user->uid == GUEST && memcmp(user->hash2, zero_hash, SCRAMBLE_SIZE)) {
+		/* No password is set for GUEST, OK. */
+		goto ok;
+	}
+
+	part_count = mp_decode_array(&tuple);
 	if (part_count < 2) {
 		/* Expected at least: authentication mechanism and data. */
 		tnt_raise(ClientError, ER_INVALID_MSGPACK,
 			   "authentication request body");
 	}
 	mp_next(&tuple); /* Skip authentication mechanism. */
-	uint32_t scramble_len;
-	const char *scramble = mp_decode_str(&tuple, &scramble_len);
+	scramble = mp_decode_str(&tuple, &scramble_len);
 	if (scramble_len != SCRAMBLE_SIZE) {
 		/* Authentication mechanism, data. */
 		tnt_raise(ClientError, ER_INVALID_MSGPACK,
@@ -54,6 +68,7 @@ authenticate(const char *user_name, uint32_t len,
 	if (scramble_check(scramble, session->salt, user->hash2))
 		tnt_raise(ClientError, ER_PASSWORD_MISMATCH, user->name);
 
+ok:
 	current_user_init(&session->user, user);
 }
 
diff --git a/src/box/user_cache.h b/src/box/user_cache.h
index d3da115278..ab7757b825 100644
--- a/src/box/user_cache.h
+++ b/src/box/user_cache.h
@@ -37,7 +37,7 @@ struct user_def;
  * in session->auth_token. This way it's easy to quickly find
  * the current user of the session.
  * An auth token, instead of a direct pointer, is stored in the
- * session because it make dropping of a signed in user safe.
+ * session because it makes dropping of a signed in user safe.
  * The same auth token (index in an array)
  * is also used to find out user privileges when accessing stored
  * objects, such as spaces and functions.
-- 
GitLab