From 6090846ee18edb369f01ffbd31efb9f11271a5f5 Mon Sep 17 00:00:00 2001
From: Konstantin Osipov <kostja@tarantool.org>
Date: Thu, 28 Dec 2017 19:14:01 +0300
Subject: [PATCH] security: introduce all ANSI SQL ACL, as well as session and
 usage

Introduce all the necessary ACL for ANSI SQL, as well as SESSION
and USAGE.

Change access storage type from uint8_t to a typedef.

Necessary for gh-2898.
---
 src/box/alter.cc       |  2 +-
 src/box/call.cc        |  2 +-
 src/box/lua/schema.lua | 60 ++++++++++++++++++++++++++++++++++++++++++
 src/box/user_def.c     | 26 ++++++++++++++++--
 src/box/user_def.h     | 37 ++++++++++++++++++++------
 5 files changed, 115 insertions(+), 12 deletions(-)

diff --git a/src/box/alter.cc b/src/box/alter.cc
index 435febdd24..7df8e0ba6e 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -60,7 +60,7 @@
 
 /* {{{ Auxiliary functions and methods. */
 
-void
+static void
 access_check_ddl(uint32_t owner_uid, enum schema_object_type type)
 {
 	struct credentials *cr = current_user();
diff --git a/src/box/call.cc b/src/box/call.cc
index d730369459..b5f4c4fa8a 100644
--- a/src/box/call.cc
+++ b/src/box/call.cc
@@ -70,7 +70,7 @@ access_check_func(const char *name, uint32_t name_len, struct func **funcp)
 		return 0;
 	}
 
-	uint8_t access = PRIV_X & ~credentials->universal_access;
+	user_access_t access = PRIV_X & ~credentials->universal_access;
 	if (func == NULL || (func->def->uid != credentials->uid &&
 	     access & ~func->access[credentials->auth_token].effective)) {
 		/* Access violation, report error. */
diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua
index 846d97b7c4..c1b45a41e5 100644
--- a/src/box/lua/schema.lua
+++ b/src/box/lua/schema.lua
@@ -1574,6 +1574,36 @@ local function privilege_resolve(privilege)
         if string.find(privilege, 'execute') then
             numeric = numeric + 4
         end
+        if string.find(privilege, 'session') then
+            numeric = numeric + 8
+        end
+        if string.find(privilege, 'usage') then
+            numeric = numeric + 16
+        end
+        if string.find(privilege, 'create') then
+            numeric = numeric + 32
+        end
+        if string.find(privilege, 'drop') then
+            numeric = numeric + 64
+        end
+        if string.find(privilege, 'alter') then
+            numeric = numeric + 128
+        end
+        if string.find(privilege, 'reference') then
+            numeric = numeric + 256
+        end
+        if string.find(privilege, 'trigger') then
+            numeric = numeric + 512
+        end
+        if string.find(privilege, 'insert') then
+            numeric = numeric + 1024
+        end
+        if string.find(privilege, 'update') then
+            numeric = numeric + 2048
+        end
+        if string.find(privilege, 'delete') then
+            numeric = numeric + 4096
+        end
     else
         numeric = privilege
     end
@@ -1599,6 +1629,36 @@ local function privilege_name(privilege)
     if bit.band(privilege, 4) ~= 0 then
         table.insert(names, "execute")
     end
+    if bit.band(privilege, 8) ~= 0 then
+        table.insert(names, "session")
+    end
+    if bit.band(privilege, 16) ~= 0 then
+        table.insert(names, "usage")
+    end
+    if bit.band(privilege, 32) ~= 0 then
+        table.insert(names, "create")
+    end
+    if bit.band(privilege, 64) ~= 0 then
+        table.insert(names, "drop")
+    end
+    if bit.band(privilege, 128) ~= 0 then
+        table.insert(names, "alter")
+    end
+    if bit.band(privilege, 256) ~= 0 then
+        table.insert(names, "reference")
+    end
+    if bit.band(privilege, 512) ~= 0 then
+        table.insert(names, "trigger")
+    end
+    if bit.band(privilege, 1024) ~= 0 then
+        table.insert(names, "insert")
+    end
+    if bit.band(privilege, 2048) ~= 0 then
+        table.insert(names, "update")
+    end
+    if bit.band(privilege, 4096) ~= 0 then
+        table.insert(names, "delete")
+    end
     return table.concat(names, ",")
 end
 
diff --git a/src/box/user_def.c b/src/box/user_def.c
index a382152bf9..def541fd0e 100644
--- a/src/box/user_def.c
+++ b/src/box/user_def.c
@@ -30,12 +30,34 @@
  */
 #include "user_def.h"
 const char *
-priv_name(uint8_t access)
+priv_name(user_access_t access)
 {
 	if (access & PRIV_R)
 		return "Read";
 	if (access & PRIV_W)
 		return "Write";
-	return "Execute";
+	if (access & PRIV_X)
+		return "Execute";
+	if (access & PRIV_S)
+		return "Session";
+	if (access & PRIV_U)
+		return "Usage";
+	if (access & PRIV_C)
+		return "Create";
+	if (access & PRIV_D)
+		return "Drop";
+	if (access & PRIV_A)
+		return "Alter";
+	if (access & PRIV_REFERENCE)
+		return "Reference";
+	if (access & PRIV_TRIGGER)
+		return "Trigger";
+	if (access & PRIV_INSERT)
+		return "Insert";
+	if (access & PRIV_UPDATE)
+		return "Update";
+	if (access & PRIV_DELETE)
+		return "Delete";
+	return "Any";
 }
 
diff --git a/src/box/user_def.h b/src/box/user_def.h
index 602ac512fa..f23fc3bb5a 100644
--- a/src/box/user_def.h
+++ b/src/box/user_def.h
@@ -39,6 +39,7 @@
 extern "C" {
 #endif /* defined(__cplusplus) */
 
+typedef uint16_t user_access_t;
 /**
  * Effective session user. A cache of user data
  * and access stored in session and fiber local storage.
@@ -52,7 +53,7 @@ struct credentials {
 	 * Cached global grants, to avoid an extra look up
 	 * when checking global grants.
 	 */
-	uint8_t universal_access;
+	user_access_t universal_access;
 	/** User id of the authenticated user. */
 	uint32_t uid;
 };
@@ -60,12 +61,32 @@ struct credentials {
 enum {
 	/* SELECT */
 	PRIV_R = 1,
-	/* INSERT, UPDATE, DELETE, REPLACE */
+	/* INSERT, UPDATE, UPSERT, DELETE, REPLACE */
 	PRIV_W = 2,
 	/* CALL */
 	PRIV_X = 4,
-	/** Everything. */
-	PRIV_ALL = PRIV_R + PRIV_W + PRIV_X
+	/* SESSION */
+	PRIV_S = 8,
+	/* USAGE */
+	PRIV_U = 16,
+	/* CREATE */
+	PRIV_C = 32,
+	/* DROP */
+	PRIV_D = 64,
+	/* ALTER */
+	PRIV_A = 128,
+	/* REFERENCE - required by ANSI - not implemented */
+	PRIV_REFERENCE = 256,
+	/* TRIGGER - required by ANSI - not implemented */
+	PRIV_TRIGGER = 512,
+	/* INSERT - required by ANSI - not implemented */
+	PRIV_INSERT = 1024,
+	/* UPDATE - required by ANSI - not implemented */
+	PRIV_UPDATE = 2048,
+	/* DELETE - required by ANSI - not implemented */
+	PRIV_DELETE = 4096,
+	/* all bits */
+	PRIV_ALL  = ~((user_access_t) 0),
 };
 
 /**
@@ -84,14 +105,14 @@ struct priv_def {
 	 * What is being granted, has been granted, or is being
 	 * revoked.
 	 */
-	uint8_t access;
+	user_access_t access;
 	/** To maintain a set of effective privileges. */
 	rb_node(struct priv_def) link;
 };
 
 /* Privilege name for error messages */
 const char *
-priv_name(uint8_t access);
+priv_name(user_access_t access);
 
 /**
  * Encapsulates privileges of a user on an object.
@@ -103,14 +124,14 @@ struct access {
 	 * Granted access has been given to a user explicitly
 	 * via some form of a grant.
 	 */
-	uint8_t granted;
+	user_access_t granted;
 	/**
 	 * Effective access is a sum of granted access and
 	 * all privileges inherited by a user on this object
 	 * via some role. Since roles may be granted to other
 	 * roles, this may include indirect grants.
 	 */
-	uint8_t effective;
+	user_access_t effective;
 };
 
 /**
-- 
GitLab