LCOV - code coverage report
Current view: top level - sql/server - sql_privileges.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 475 570 83.3 %
Date: 2021-10-13 02:24:04 Functions: 34 36 94.4 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : /*
      10             :  * Privileges
      11             :  * ==========
      12             :  *
      13             :  * Sql has a simple access control schema. There are two types of authorization,
      14             :  * users and roles. Each user may be part of several roles.
      15             :  * For each authorization identity a set of privileges is administrated.
      16             :  * These are administrated on multiple levels where lower levels (ie.
      17             :  * table or column level) overwrite privileges on higher levels.
      18             :  *
      19             :  */
      20             : 
      21             : #include "monetdb_config.h"
      22             : #include "sql_privileges.h"
      23             : #include "sql_semantic.h"
      24             : #include "sql_parser.h"
      25             : #include "mal_exception.h"
      26             : 
      27             : #define PRIV_ROLE_ADMIN 0
      28             : 
      29             : #define GLOBAL_OBJID 0
      30             : 
      31             : static const char *
      32           0 : priv2string(int priv)
      33             : {
      34           0 :         switch (priv) {
      35             :         case PRIV_SELECT:
      36             :                 return "SELECT";
      37           0 :         case PRIV_UPDATE:
      38           0 :                 return "UPDATE";
      39           0 :         case PRIV_INSERT:
      40           0 :                 return "INSERT";
      41           0 :         case PRIV_DELETE:
      42           0 :                 return "DELETE";
      43           0 :         case PRIV_TRUNCATE:
      44           0 :                 return "TRUNCATE";
      45           0 :         case PRIV_EXECUTE:
      46           0 :                 return "EXECUTE";
      47             :         }
      48           0 :         return "UNKNOWN PRIV";
      49             : }
      50             : 
      51             : static int
      52       75443 : sql_insert_priv(mvc *sql, sqlid auth_id, sqlid obj_id, int privilege, sqlid grantor, int grantable)
      53             : {
      54       75443 :         sql_schema *ss = mvc_bind_schema(sql, "sys");
      55       75443 :         sql_table *pt = find_sql_table(sql->session->tr, ss, "privileges");
      56       75443 :         sqlstore *store = sql->session->tr->store;
      57             : 
      58       75443 :         return store->table_api.table_insert(sql->session->tr, pt, &obj_id, &auth_id, &privilege, &grantor, &grantable);
      59             : }
      60             : 
      61             : static int
      62           4 : sql_insert_all_privs(mvc *sql, sqlid auth_id, sqlid obj_id, int grantor, int grantable)
      63             : {
      64             :         int log_res = 0;
      65             : 
      66           8 :         if ((log_res = sql_insert_priv(sql, auth_id, obj_id, PRIV_SELECT, grantor, grantable)) ||
      67           8 :                 (log_res = sql_insert_priv(sql, auth_id, obj_id, PRIV_UPDATE, grantor, grantable)) ||
      68           8 :                 (log_res = sql_insert_priv(sql, auth_id, obj_id, PRIV_INSERT, grantor, grantable)) ||
      69           8 :                 (log_res = sql_insert_priv(sql, auth_id, obj_id, PRIV_DELETE, grantor, grantable)) ||
      70           4 :                 (log_res = sql_insert_priv(sql, auth_id, obj_id, PRIV_TRUNCATE, grantor, grantable)))
      71           0 :                 return log_res;
      72             :         return 0;
      73             : }
      74             : 
      75             : static bool
      76             : admin_privs(sqlid grantor)
      77             : {
      78     1067435 :         if (grantor == USER_MONETDB || grantor == ROLE_SYSADMIN) {
      79             :                 return true;
      80             :         }
      81             :         return false;
      82             : }
      83             : 
      84             : int
      85      252541 : mvc_schema_privs(mvc *m, sql_schema *s)
      86             : {
      87      252541 :         if (admin_privs(m->user_id) || admin_privs(m->role_id))
      88             :                 return 1;
      89        2396 :         if (!s)
      90             :                 return 0;
      91        2396 :         if (m->user_id == s->auth_id || m->role_id == s->auth_id)
      92        2378 :                 return 1;
      93             :         return 0;
      94             : }
      95             : 
      96             : static bool
      97             : schema_privs(sqlid grantor, sql_schema *s)
      98             : {
      99             :         if (admin_privs(grantor))
     100             :                 return true;
     101           8 :         if (!s)
     102             :                 return false;
     103           8 :         if (grantor == s->auth_id)
     104           1 :                 return true;
     105             :         return false;
     106             : }
     107             : 
     108             : str
     109           5 : sql_grant_global_privs( mvc *sql, char *grantee, int privs, int grant, sqlid grantor)
     110             : {
     111             :         bool allowed;
     112             :         sqlid grantee_id;
     113             :         int log_res;
     114             : 
     115             :         allowed = admin_privs(grantor);
     116             : 
     117             :         if (!allowed)
     118           0 :                 allowed = sql_grantable(sql, grantor, GLOBAL_OBJID, privs) == 1;
     119             : 
     120           5 :         if (!allowed)
     121           0 :                 throw(SQL,"sql.grant_global",SQLSTATE(01007) "GRANT: Grantor '%s' is not allowed to grant global privileges", get_string_global_var(sql, "current_user"));
     122             : 
     123           5 :         grantee_id = sql_find_auth(sql, grantee);
     124           5 :         if (grantee_id <= 0)
     125           2 :                 throw(SQL,"sql.grant_global",SQLSTATE(01007) "GRANT: User/role '%s' unknown", grantee);
     126             :         /* first check if privilege isn't already given */
     127           3 :         if ((sql_privilege(sql, grantee_id, GLOBAL_OBJID, privs) >= 0))
     128           0 :                 throw(SQL,"sql.grant_global",SQLSTATE(01007) "GRANT: User/role '%s' already has this privilege", grantee);
     129           3 :         if ((log_res = sql_insert_priv(sql, grantee_id, GLOBAL_OBJID, privs, grantor, grant)))
     130           0 :                 throw(SQL,"sql.grant_global",SQLSTATE(42000) "GRANT: failed%s", log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     131             : 
     132             :         /* Add dependencies created */
     133           3 :         if ((log_res = sql_trans_add_dependency(sql->session->tr, grantee_id, ddl)) != LOG_OK)
     134           0 :                 throw(SQL, "sql.grant_table", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     135           3 :         if ((log_res = sql_trans_add_dependency(sql->session->tr, grantor, ddl)) != LOG_OK)
     136           0 :                 throw(SQL, "sql.grant_table", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     137             :         return MAL_SUCCEED;
     138             : }
     139             : 
     140             : char *
     141        9430 : sql_grant_table_privs( mvc *sql, char *grantee, int privs, char *sname, char *tname, char *cname, int grant, sqlid grantor)
     142             : {
     143             :         sql_table *t = NULL;
     144             :         sql_column *c = NULL;
     145             :         bool allowed;
     146             :         sqlid grantee_id;
     147             :         int all = PRIV_SELECT | PRIV_UPDATE | PRIV_INSERT | PRIV_DELETE | PRIV_TRUNCATE, log_res;
     148             : 
     149        9430 :         if (!(t = find_table_or_view_on_scope(sql, NULL, sname, tname, "GRANT", false)))
     150           0 :                 throw(SQL,"sql.grant_table", "%s", sql->errstr);
     151        9430 :         if (isDeclaredTable(t))
     152           0 :                 throw(SQL,"sql.grant_table", SQLSTATE(42000) "GRANT: cannot grant on a declared table");
     153             : 
     154        9430 :         allowed = schema_privs(grantor, t->s);
     155             : 
     156        9430 :         if (!cname) {
     157        9417 :                 if (!allowed)
     158           7 :                         allowed = sql_grantable(sql, grantor, t->base.id, privs) == 1;
     159             : 
     160        9417 :                 if (!allowed)
     161           2 :                         throw(SQL,"sql.grant_table", SQLSTATE(01007) "GRANT: Grantor '%s' is not allowed to grant privileges for table '%s'", get_string_global_var(sql, "current_user"), tname);
     162             :         }
     163        9428 :         if (cname) {
     164          13 :                 c = mvc_bind_column(sql, t, cname);
     165          13 :                 if (!c)
     166           1 :                         throw(SQL,"sql.grant_table",SQLSTATE(42S22) "GRANT: Table '%s' has no column '%s'", tname, cname);
     167             :                 /* allowed on column */
     168          12 :                 if (!allowed)
     169           0 :                         allowed = sql_grantable(sql, grantor, c->base.id, privs) == 1;
     170             : 
     171          12 :                 if (!allowed)
     172           0 :                         throw(SQL, "sql.grant_table", SQLSTATE(01007) "GRANT: Grantor '%s' is not allowed to grant privilege %s for table '%s'", get_string_global_var(sql, "current_user"), priv2string(privs), tname);
     173             :         }
     174             : 
     175        9427 :         grantee_id = sql_find_auth(sql, grantee);
     176        9427 :         if (grantee_id <= 0)
     177           1 :                 throw(SQL,"sql.grant_table", SQLSTATE(01007) "GRANT: User/role '%s' unknown", grantee);
     178             :         /* first check if privilege isn't already given */
     179        9430 :         if ((privs == all &&
     180           8 :             (sql_privilege(sql, grantee_id, t->base.id, PRIV_SELECT) >= 0 ||
     181           8 :              sql_privilege(sql, grantee_id, t->base.id, PRIV_UPDATE) >= 0 ||
     182           8 :              sql_privilege(sql, grantee_id, t->base.id, PRIV_INSERT) >= 0 ||
     183           8 :              sql_privilege(sql, grantee_id, t->base.id, PRIV_DELETE) >= 0 ||
     184           4 :              sql_privilege(sql, grantee_id, t->base.id, PRIV_TRUNCATE) >= 0)) ||
     185        9426 :             (privs != all && !c && sql_privilege(sql, grantee_id, t->base.id, privs) >= 0) ||
     186        9425 :             (privs != all && c && sql_privilege(sql, grantee_id, c->base.id, privs) >= 0)) {
     187           1 :                 throw(SQL, "sql.grant_table", SQLSTATE(01007) "GRANT: User/role '%s' already has this privilege", grantee);
     188             :         }
     189        9425 :         if (privs == all) {
     190           4 :                 if ((log_res = sql_insert_all_privs(sql, grantee_id, t->base.id, grantor, grant)))
     191           0 :                         throw(SQL, "sql.grant_table", SQLSTATE(42000) "GRANT: failed%s", log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     192        9421 :         } else if (!c) {
     193        9409 :                 if ((log_res = sql_insert_priv(sql, grantee_id, t->base.id, privs, grantor, grant)))
     194           0 :                         throw(SQL, "sql.grant_table", SQLSTATE(42000) "GRANT: failed%s", log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     195             :         } else {
     196          12 :                 if ((log_res = sql_insert_priv(sql, grantee_id, c->base.id, privs, grantor, grant)))
     197           0 :                         throw(SQL, "sql.grant_table", SQLSTATE(42000) "GRANT: failed%s", log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     198             :         }
     199             : 
     200             :         /* Add dependencies created */
     201        9425 :         if (privs == all || !c) {
     202        9413 :                 if (!isNew(t) && (log_res = sql_trans_add_dependency(sql->session->tr, t->base.id, ddl)) != LOG_OK)
     203           0 :                         throw(SQL, "sql.grant_table", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     204             :         } else {
     205          12 :                 if (!isNew(c) && (log_res = sql_trans_add_dependency(sql->session->tr, c->base.id, ddl)) != LOG_OK)
     206           0 :                         throw(SQL, "sql.grant_table", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     207             :         }
     208        9425 :         if ((log_res = sql_trans_add_dependency(sql->session->tr, grantee_id, ddl)) != LOG_OK)
     209           0 :                 throw(SQL, "sql.grant_table", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     210        9425 :         if ((log_res = sql_trans_add_dependency(sql->session->tr, grantor, ddl)) != LOG_OK)
     211           0 :                 throw(SQL, "sql.grant_table", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     212             : 
     213             :         return NULL;
     214             : }
     215             : 
     216             : char *
     217       65999 : sql_grant_func_privs( mvc *sql, char *grantee, int privs, char *sname, sqlid func_id, int grant, sqlid grantor)
     218             : {
     219             :         sql_schema *s = NULL;
     220             :         bool allowed;
     221             :         sqlid grantee_id;
     222             :         int log_res;
     223             : 
     224       65999 :         assert(sname);
     225       65999 :         if (!(s = mvc_bind_schema(sql, sname)))
     226           0 :                 throw(SQL,"sql.grant_func",SQLSTATE(3F000) "GRANT: no such schema '%s'", sname);
     227       65999 :         sql_base *b = os_find_id(s->funcs, sql->session->tr, func_id);
     228             :         sql_func *f = (sql_func*)b;
     229       65999 :         assert(f);
     230       65999 :         allowed = schema_privs(grantor, f->s);
     231             : 
     232             :         if (!allowed)
     233           0 :                 allowed = sql_grantable(sql, grantor, f->base.id, privs) == 1;
     234             : 
     235       65999 :         if (!allowed)
     236           0 :                 throw(SQL, "sql.grant_func", SQLSTATE(01007) "GRANT: Grantor '%s' is not allowed to grant privileges for function '%s'", get_string_global_var(sql, "current_user"), f->base.name);
     237             : 
     238       65999 :         grantee_id = sql_find_auth(sql, grantee);
     239       65999 :         if (grantee_id <= 0)
     240           0 :                 throw(SQL, "sql.grant_func", SQLSTATE(01007) "GRANT: User/role '%s' unknown", grantee);
     241             :         /* first check if privilege isn't already given */
     242       65999 :         if (sql_privilege(sql, grantee_id, f->base.id, privs) >= 0)
     243           0 :                 throw(SQL,"sql.grant_func", SQLSTATE(01007) "GRANT: User/role '%s' already has this privilege", grantee);
     244       65999 :         if ((log_res = sql_insert_priv(sql, grantee_id, f->base.id, privs, grantor, grant)))
     245           0 :                 throw(SQL,"sql.grant_func", SQLSTATE(42000) "GRANT: failed%s", log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     246             : 
     247             :         /* Add dependencies created */
     248       65999 :         if (!isNew(f) && (log_res = sql_trans_add_dependency(sql->session->tr, func_id, ddl)) != LOG_OK)
     249           0 :                 throw(SQL, "sql.grant_func", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     250       65999 :         if ((log_res = sql_trans_add_dependency(sql->session->tr, grantor, ddl)) != LOG_OK)
     251           0 :                 throw(SQL, "sql.grant_func", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     252             :         return NULL;
     253             : }
     254             : 
     255             : static char *
     256          16 : sql_delete_priv(mvc *sql, sqlid auth_id, sqlid obj_id, int privilege, sqlid grantor, int grantable, const char *op, const char *call)
     257             : {
     258          16 :         sql_schema *ss = mvc_bind_schema(sql, "sys");
     259          16 :         sql_table *privs = find_sql_table(sql->session->tr, ss, "privileges");
     260          16 :         sql_column *priv_obj = find_sql_column(privs, "obj_id");
     261          16 :         sql_column *priv_auth = find_sql_column(privs, "auth_id");
     262          16 :         sql_column *priv_priv = find_sql_column(privs, "privileges");
     263          16 :         sql_trans *tr = sql->session->tr;
     264          16 :         sqlstore *store = tr->store;
     265             :         rids *A;
     266             :         oid rid = oid_nil;
     267             :         int log_res = LOG_OK;
     268             : 
     269             :         (void) grantor;
     270             :         (void) grantable;
     271             : 
     272             :         /* select privileges of this auth_id, privilege, obj_id */
     273          16 :         A = store->table_api.rids_select(tr, priv_auth, &auth_id, &auth_id, priv_priv, &privilege, &privilege, priv_obj, &obj_id, &obj_id, NULL );
     274             : 
     275             :         /* remove them */
     276          32 :         for(rid = store->table_api.rids_next(A); !is_oid_nil(rid) && log_res == LOG_OK; rid = store->table_api.rids_next(A))
     277          16 :                 log_res = store->table_api.table_delete(tr, privs, rid);
     278          16 :         store->table_api.rids_destroy(A);
     279          16 :         if (log_res != LOG_OK)
     280           0 :                 throw(SQL, op, SQLSTATE(42000) "%s: failed%s", call, log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     281             :         return NULL;
     282             : }
     283             : 
     284             : char *
     285           2 : sql_revoke_global_privs( mvc *sql, char *grantee, int privs, int grant, sqlid grantor)
     286             : {
     287             :         bool allowed;
     288             :         sqlid grantee_id;
     289             : 
     290             :         allowed = admin_privs(grantor);
     291             : 
     292             :         if (!allowed)
     293           0 :                 allowed = sql_grantable(sql, grantor, GLOBAL_OBJID, privs) == 1;
     294             : 
     295           2 :         if (!allowed)
     296           0 :                 throw(SQL, "sql.revoke_global", SQLSTATE(01006) "REVOKE: Grantor '%s' is not allowed to revoke global privileges", get_string_global_var(sql, "current_user"));
     297             : 
     298           2 :         grantee_id = sql_find_auth(sql, grantee);
     299           2 :         if (grantee_id <= 0)
     300           0 :                 throw(SQL, "sql.revoke_global", SQLSTATE(01006) "REVOKE: User/role '%s' unknown", grantee);
     301           2 :         return sql_delete_priv(sql, grantee_id, GLOBAL_OBJID, privs, grantor, grant, "sql.revoke_global", "REVOKE");
     302             : }
     303             : 
     304             : char *
     305          13 : sql_revoke_table_privs( mvc *sql, char *grantee, int privs, char *sname, char *tname, char *cname, int grant, sqlid grantor)
     306             : {
     307             :         sql_table *t = NULL;
     308             :         sql_column *c = NULL;
     309             :         bool allowed;
     310             :         sqlid grantee_id;
     311             :         int all = PRIV_SELECT | PRIV_UPDATE | PRIV_INSERT | PRIV_DELETE | PRIV_TRUNCATE;
     312             :         char *msg = NULL;
     313             : 
     314          13 :         if (!(t = find_table_or_view_on_scope(sql, NULL, sname, tname, "REVOKE", false)))
     315           0 :                 throw(SQL,"sql.revoke_table","%s", sql->errstr);
     316          13 :         if (isDeclaredTable(t))
     317           0 :                 throw(SQL,"sql.revoke_table", SQLSTATE(42000) "REVOKE: cannot revoke on a declared table");
     318             : 
     319          13 :         allowed = schema_privs(grantor, t->s);
     320             :         if (!allowed)
     321           0 :                 allowed = sql_grantable(sql, grantor, t->base.id, privs) == 1;
     322             : 
     323          13 :         if (!allowed)
     324           0 :                 throw(SQL, "sql.revoke_table", SQLSTATE(01006) "REVOKE: Grantor '%s' is not allowed to revoke privileges for table '%s'", get_string_global_var(sql, "current_user"), tname);
     325             : 
     326          13 :         if (cname) {
     327           2 :                 c = mvc_bind_column(sql, t, cname);
     328           2 :                 if (!c)
     329           0 :                         throw(SQL,"sql.revoke_table", SQLSTATE(42S22) "REVOKE: table '%s' has no column '%s'", tname, cname);
     330             :                 /* allowed on column */
     331             :                 if (!allowed)
     332             :                         allowed = sql_grantable(sql, grantor, c->base.id, privs) == 1;
     333             : 
     334             :                 if (!allowed)
     335             :                         throw(SQL, "sql.revoke_table", SQLSTATE(01006) "REVOKE: Grantor '%s' is not allowed to revoke privilege %s for table '%s'", get_string_global_var(sql, "current_user"), priv2string(privs), tname);
     336             :         }
     337             : 
     338          13 :         grantee_id = sql_find_auth(sql, grantee);
     339          13 :         if (grantee_id <= 0)
     340           0 :                  throw(SQL,"sql.revoke_table", SQLSTATE(01006) "REVOKE: User/role '%s' unknown", grantee);
     341          13 :         if (privs == all) {
     342           0 :                 if ((msg = sql_delete_priv(sql, grantee_id, t->base.id, PRIV_SELECT, grantor, grant, "sql.revoke_table", "REVOKE")) ||
     343           0 :                         (msg = sql_delete_priv(sql, grantee_id, t->base.id, PRIV_UPDATE, grantor, grant, "sql.revoke_table", "REVOKE")) ||
     344           0 :                         (msg = sql_delete_priv(sql, grantee_id, t->base.id, PRIV_INSERT, grantor, grant, "sql.revoke_table", "REVOKE")) ||
     345           0 :                         (msg = sql_delete_priv(sql, grantee_id, t->base.id, PRIV_DELETE, grantor, grant, "sql.revoke_table", "REVOKE")) ||
     346           0 :                         (msg = sql_delete_priv(sql, grantee_id, t->base.id, PRIV_TRUNCATE, grantor, grant, "sql.revoke_table", "REVOKE")))
     347           0 :                         return msg;
     348          13 :         } else if (!c) {
     349          11 :                 msg = sql_delete_priv(sql, grantee_id, t->base.id, privs, grantor, grant, "sql.revoke_table", "REVOKE");
     350             :         } else {
     351           2 :                 msg = sql_delete_priv(sql, grantee_id, c->base.id, privs, grantor, grant, "sql.revoke_table", "REVOKE");
     352             :         }
     353             :         return msg;
     354             : }
     355             : 
     356             : char *
     357           1 : sql_revoke_func_privs( mvc *sql, char *grantee, int privs, char *sname, sqlid func_id, int grant, sqlid grantor)
     358             : {
     359             :         sql_schema *s = NULL;
     360             :         bool allowed;
     361             :         sqlid grantee_id;
     362             : 
     363           1 :         assert(sname);
     364           1 :         if (!(s = mvc_bind_schema(sql, sname)))
     365           0 :                 throw(SQL,"sql.revoke_func", SQLSTATE(3F000) "REVOKE: no such schema '%s'", sname);
     366           1 :         sql_base *b = os_find_id(s->funcs, sql->session->tr, func_id);
     367             :         sql_func *f = (sql_func*)b;
     368           1 :         assert(f);
     369           1 :         allowed = schema_privs(grantor, f->s);
     370             :         if (!allowed)
     371           0 :                 allowed = sql_grantable(sql, grantor, f->base.id, privs) == 1;
     372             : 
     373           1 :         if (!allowed)
     374           0 :                 throw(SQL, "sql.revoke_func", SQLSTATE(01006) "REVOKE: Grantor '%s' is not allowed to revoke privileges for function '%s'", get_string_global_var(sql, "current_user"), f->base.name);
     375             : 
     376           1 :         grantee_id = sql_find_auth(sql, grantee);
     377           1 :         if (grantee_id <= 0)
     378           0 :                 throw(SQL, "sql.revoke_func", SQLSTATE(01006) "REVOKE: User/role '%s' unknown", grantee);
     379           1 :         return sql_delete_priv(sql, grantee_id, f->base.id, privs, grantor, grant, "sql.revoke_func", "REVOKE");
     380             : }
     381             : 
     382             : static bool
     383         558 : sql_create_auth_id(mvc *m, sqlid id, str auth)
     384             : {
     385         558 :         int grantor = 0; /* no grantor */
     386         558 :         sql_schema *sys = find_sql_schema(m->session->tr, "sys");
     387         558 :         sql_table *auths = find_sql_table(m->session->tr, sys, "auths");
     388         558 :         sql_column *auth_name = find_sql_column(auths, "name");
     389         558 :         sqlstore *store = m->session->tr->store;
     390             :         int log_res = LOG_OK;
     391             : 
     392         558 :         if (!is_oid_nil(store->table_api.column_find_row(m->session->tr, auth_name, auth, NULL)))
     393             :                 return false;
     394             : 
     395         558 :         if ((log_res = store->table_api.table_insert(m->session->tr, auths, &id, &auth, &grantor)) != LOG_OK)
     396           0 :                 throw(SQL, "sql.create_auth_id", SQLSTATE(42000) "CREATE AUTH: failed%s", log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     397             :         return true;
     398             : }
     399             : 
     400             : str
     401          21 : sql_create_role(mvc *m, str auth, sqlid grantor)
     402             : {
     403             :         sqlid id;
     404          21 :         sql_trans *tr = m->session->tr;
     405          21 :         sqlstore *store = m->session->tr->store;
     406          21 :         sql_schema *sys = find_sql_schema(tr, "sys");
     407          21 :         sql_table *auths = find_sql_table(tr, sys, "auths");
     408          21 :         sql_column *auth_name = find_sql_column(auths, "name");
     409             :         int log_res = LOG_OK;
     410             : 
     411          21 :         if (!admin_privs(grantor))
     412           0 :                 throw(SQL, "sql.create_role", SQLSTATE(0P000) "Insufficient privileges to create role '%s'", auth);
     413          21 :         if (!is_oid_nil(store->table_api.column_find_row(tr, auth_name, auth, NULL)))
     414           1 :                 throw(SQL, "sql.create_role", SQLSTATE(0P000) "Role '%s' already exists", auth);
     415             : 
     416          20 :         id = store_next_oid(tr->store);
     417          20 :         if ((log_res = store->table_api.table_insert(tr, auths, &id, &auth, &grantor)) != LOG_OK)
     418           1 :                 throw(SQL, "sql.create_role", SQLSTATE(42000) "CREATE ROLE: failed%s", log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     419             :         return NULL;
     420             : }
     421             : 
     422             : str
     423          18 : sql_drop_role(mvc *m, str auth)
     424             : {
     425          18 :         sqlid role_id = sql_find_auth(m, auth);
     426          18 :         sql_schema *sys = find_sql_schema(m->session->tr, "sys");
     427          18 :         sql_table *auths = find_sql_table(m->session->tr, sys, "auths");
     428          18 :         sql_table *user_roles = find_sql_table(m->session->tr, sys, "user_role");
     429          18 :         sql_trans *tr = m->session->tr;
     430          18 :         sqlstore *store = m->session->tr->store;
     431             :         rids *A;
     432             :         oid rid;
     433             :         int log_res = LOG_OK;
     434             : 
     435          18 :         rid = store->table_api.column_find_row(tr, find_sql_column(auths, "name"), auth, NULL);
     436          18 :         if (is_oid_nil(rid))
     437           1 :                 throw(SQL, "sql.drop_role", SQLSTATE(0P000) "DROP ROLE: no such role '%s'", auth);
     438          17 :         if ((log_res = store->table_api.table_delete(m->session->tr, auths, rid)) != LOG_OK)
     439           0 :                 throw(SQL, "sql.drop_role", SQLSTATE(42000) "DROP ROLE: failed%s", log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     440             : 
     441             :         /* select user roles of this role_id */
     442          17 :         A = store->table_api.rids_select(tr, find_sql_column(user_roles, "role_id"), &role_id, &role_id, NULL);
     443             :         /* remove them */
     444          18 :         for(rid = store->table_api.rids_next(A); !is_oid_nil(rid) && log_res == LOG_OK; rid = store->table_api.rids_next(A))
     445           1 :                 log_res = store->table_api.table_delete(tr, user_roles, rid);
     446          17 :         store->table_api.rids_destroy(A);
     447          17 :         if (log_res != LOG_OK)
     448           0 :                 throw(SQL, "sql.drop_role", SQLSTATE(42000) "DROP ROLE: failed%s", log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     449             : 
     450             :         /* Flag as removed */
     451          17 :         if ((log_res = sql_trans_add_dependency_change(tr, role_id, ddl)) != LOG_OK)
     452           0 :                 throw(SQL, "sql.drop_role", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     453             :         return NULL;
     454             : }
     455             : 
     456             : static oid
     457       77994 : sql_privilege_rid(mvc *m, sqlid auth_id, sqlid obj_id, int priv)
     458             : {
     459       77994 :         sql_schema *sys = find_sql_schema(m->session->tr, "sys");
     460       77994 :         sql_table *privs = find_sql_table(m->session->tr, sys, "privileges");
     461       77994 :         sql_column *priv_obj = find_sql_column(privs, "obj_id");
     462       77994 :         sql_column *priv_auth = find_sql_column(privs, "auth_id");
     463       77994 :         sql_column *priv_priv = find_sql_column(privs, "privileges");
     464       77994 :         sqlstore *store = m->session->tr->store;
     465             : 
     466       77994 :         return store->table_api.column_find_row(m->session->tr, priv_obj, &obj_id, priv_auth, &auth_id, priv_priv, &priv, NULL);
     467             : }
     468             : 
     469             : int
     470       77987 : sql_privilege(mvc *m, sqlid auth_id, sqlid obj_id, int priv)
     471             : {
     472       77987 :         oid rid = sql_privilege_rid(m, auth_id, obj_id, priv);
     473             :         int res = -1;
     474             : 
     475       77987 :         if (!is_oid_nil(rid)) {
     476             :                 /* found priv */
     477             :                 res = priv;
     478             :         }
     479       77987 :         return res;
     480             : }
     481             : 
     482             : int
     483         356 : global_privs(mvc *m, int priv)
     484             : {
     485         362 :         if (admin_privs(m->user_id) || admin_privs(m->role_id) ||
     486          10 :             sql_privilege(m, m->user_id, GLOBAL_OBJID, priv) == priv ||
     487           8 :             sql_privilege(m, m->role_id, GLOBAL_OBJID, priv) == priv ||
     488           4 :             sql_privilege(m, ROLE_PUBLIC, GLOBAL_OBJID, priv) == priv) {
     489         352 :                 return 1;
     490             :         }
     491             :         return 0;
     492             : }
     493             : 
     494             : int
     495      493967 : table_privs(mvc *m, sql_table *t, int priv)
     496             : {
     497             :         /* temporary tables are owned by the session user */
     498      493967 :         if (t->persistence == SQL_DECLARED_TABLE ||
     499      493825 :             (!t->system && t->persistence != SQL_PERSIST) ||
     500      408954 :             (priv == PRIV_SELECT && (t->persistence != SQL_PERSIST || t->commit_action)))
     501             :                 return 1;
     502      463344 :         if (admin_privs(m->user_id) || admin_privs(m->role_id) ||
     503        1551 :             (t->s && (m->user_id == t->s->auth_id || m->role_id == t->s->auth_id)) ||
     504        1106 :             sql_privilege(m, m->user_id, t->base.id, priv) == priv ||
     505        1013 :             sql_privilege(m, m->role_id, t->base.id, priv) == priv ||
     506         500 :             sql_privilege(m, ROLE_PUBLIC, t->base.id, priv) == priv) {
     507      463189 :                 return 1;
     508             :         }
     509             :         return 0;
     510             : }
     511             : 
     512             : int
     513         823 : column_privs(mvc *m, sql_column *c, int priv)
     514             : {
     515             :         /* only SELECT and UPDATE privileges for columns are available */
     516             :         /* temporary tables are owned by the session user, so does it's columns */
     517         823 :         if (c->t->persistence == SQL_DECLARED_TABLE ||
     518         823 :             (!c->t->system && c->t->persistence != SQL_PERSIST) ||
     519         823 :             (priv == PRIV_SELECT && (c->t->persistence != SQL_PERSIST || c->t->commit_action)))
     520             :                 return 1;
     521         781 :         if (admin_privs(m->user_id) || admin_privs(m->role_id) ||
     522         546 :             (c->t->s && (m->user_id == c->t->s->auth_id || m->role_id == c->t->s->auth_id)) ||
     523         487 :             sql_privilege(m, m->user_id, c->base.id, priv) == priv ||
     524         428 :             sql_privilege(m, m->role_id, c->base.id, priv) == priv ||
     525         214 :             sql_privilege(m, ROLE_PUBLIC, c->base.id, priv) == priv) {
     526         567 :                 return 1;
     527             :         }
     528             :         return 0;
     529             : }
     530             : 
     531             : int
     532      840145 : execute_priv(mvc *m, sql_func *f)
     533             : {
     534             :         int priv = PRIV_EXECUTE;
     535             : 
     536      840145 :         if (!f->s || admin_privs(m->user_id) || admin_privs(m->role_id))
     537             :                 return 1;
     538        2760 :         if (m->user_id == f->s->auth_id || m->role_id == f->s->auth_id)
     539             :                 return 1;
     540          99 :         if (sql_privilege(m, m->user_id, f->base.id, priv) == priv ||
     541          72 :             sql_privilege(m, m->role_id, f->base.id, priv) == priv ||
     542          36 :             sql_privilege(m, ROLE_PUBLIC, f->base.id, priv) == priv)
     543          51 :                 return 1;
     544             :         return 0;
     545             : }
     546             : 
     547             : static bool
     548           7 : role_granting_privs(mvc *m, oid role_rid, sqlid role_id, sqlid grantor_id)
     549             : {
     550           7 :         sql_schema *sys = find_sql_schema(m->session->tr, "sys");
     551           7 :         sql_table *auths = find_sql_table(m->session->tr, sys, "auths");
     552           7 :         sql_column *auths_grantor = find_sql_column(auths, "grantor");
     553             :         sqlid owner_id;
     554           7 :         sqlstore *store = m->session->tr->store;
     555             : 
     556           7 :         owner_id = store->table_api.column_find_sqlid(m->session->tr, auths_grantor, role_rid);
     557           7 :         if (owner_id == grantor_id)
     558             :                 return true;
     559           7 :         if (sql_privilege(m, grantor_id, role_id, PRIV_ROLE_ADMIN) == PRIV_ROLE_ADMIN)
     560           3 :                 return true;
     561             :         /* check for grant rights in the privs table */
     562             :         return false;
     563             : }
     564             : 
     565             : char *
     566          36 : sql_grant_role(mvc *m, str grantee, str role, sqlid grantor, int admin)
     567             : {
     568             :         oid rid;
     569          36 :         sql_schema *sys = find_sql_schema(m->session->tr, "sys");
     570          36 :         sql_table *auths = find_sql_table(m->session->tr, sys, "auths");
     571          36 :         sql_table *roles = find_sql_table(m->session->tr, sys, "user_role");
     572          36 :         sql_column *auths_name = find_sql_column(auths, "name");
     573          36 :         sql_column *auths_id = find_sql_column(auths, "id");
     574             :         sqlid role_id, grantee_id;
     575          36 :         sqlstore *store = m->session->tr->store;
     576             :         int log_res = LOG_OK;
     577             : 
     578          36 :         rid = store->table_api.column_find_row(m->session->tr, auths_name, role, NULL);
     579          36 :         if (is_oid_nil(rid))
     580           1 :                 throw(SQL, "sql.grant_role", SQLSTATE(M1M05) "GRANT: no such role '%s' or grantee '%s'", role, grantee);
     581          35 :         role_id = store->table_api.column_find_sqlid(m->session->tr, auths_id, rid);
     582          35 :         if (backend_find_user(m, role) >= 0)
     583           0 :                 throw(SQL,"sql.grant_role", SQLSTATE(M1M05) "GRANT: '%s' is a USER not a ROLE", role);
     584          35 :         if (!admin_privs(grantor) && !role_granting_privs(m, rid, role_id, grantor))
     585           4 :                 throw(SQL,"sql.grant_role", SQLSTATE(0P000) "GRANT: Insufficient privileges to grant ROLE '%s'", role);
     586          31 :         rid = store->table_api.column_find_row(m->session->tr, auths_name, grantee, NULL);
     587          31 :         if (is_oid_nil(rid))
     588           1 :                 throw(SQL,"sql.grant_role", SQLSTATE(M1M05) "GRANT: no such role '%s' or grantee '%s'", role, grantee);
     589          30 :         grantee_id = store->table_api.column_find_sqlid(m->session->tr, auths_id, rid);
     590          30 :         rid = store->table_api.column_find_row(m->session->tr, find_sql_column(roles, "login_id"), &grantee_id, find_sql_column(roles, "role_id"), &role_id, NULL);
     591          30 :         if (!is_oid_nil(rid))
     592           2 :                 throw(SQL,"sql.grant_role", SQLSTATE(M1M05) "GRANT: User '%s' already has ROLE '%s'", grantee, role);
     593             : 
     594          28 :         if ((log_res = store->table_api.table_insert(m->session->tr, roles, &grantee_id, &role_id)) != LOG_OK)
     595           1 :                 throw(SQL, "sql.grant_role", SQLSTATE(42000) "GRANT: failed%s", log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     596          27 :         if (admin) {
     597           2 :                 int priv = PRIV_ROLE_ADMIN, one = 1;
     598           2 :                 sql_table *privs = find_sql_table(m->session->tr, sys, "privileges");
     599             : 
     600           2 :                 if ((log_res = store->table_api.table_insert(m->session->tr, privs, &role_id, &grantee_id, &priv, &grantor, &one)) != LOG_OK)
     601           0 :                         throw(SQL, "sql.grant_role", SQLSTATE(42000) "GRANT: failed%s", log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     602             :         }
     603             : 
     604             :         /* Add dependencies created */
     605          27 :         if ((log_res = sql_trans_add_dependency(m->session->tr, grantee_id, ddl)) != LOG_OK)
     606           0 :                 throw(SQL, "sql.grant_role", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     607          27 :         if ((log_res = sql_trans_add_dependency(m->session->tr, role_id, ddl)) != LOG_OK)
     608           0 :                 throw(SQL, "sql.grant_role", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     609          27 :         if ((log_res = sql_trans_add_dependency(m->session->tr, grantor, ddl)) != LOG_OK)
     610           0 :                 throw(SQL, "sql.grant_role", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     611             :         return NULL;
     612             : }
     613             : 
     614             : char *
     615          10 : sql_revoke_role(mvc *m, str grantee, str role, sqlid grantor, int admin)
     616             : /* grantee no longer belongs the role (role) */
     617             : {
     618             :         oid rid;
     619          10 :         sql_schema *sys = find_sql_schema(m->session->tr, "sys");
     620          10 :         sql_table *auths = find_sql_table(m->session->tr, sys, "auths");
     621          10 :         sql_table *roles = find_sql_table(m->session->tr, sys, "user_role");
     622          10 :         sql_table *privs = find_sql_table(m->session->tr, sys, "privileges");
     623          10 :         sql_column *auths_name = find_sql_column(auths, "name");
     624          10 :         sql_column *auths_id = find_sql_column(auths, "id");
     625          10 :         sql_column *roles_role_id = find_sql_column(roles, "role_id");
     626          10 :         sql_column *roles_login_id = find_sql_column(roles, "login_id");
     627             :         sqlid role_id, grantee_id;
     628          10 :         sqlstore *store = m->session->tr->store;
     629             :         int log_res = LOG_OK;
     630             : 
     631          10 :         rid = store->table_api.column_find_row(m->session->tr, auths_name, grantee, NULL);
     632          10 :         if (is_oid_nil(rid))
     633           1 :                 throw(SQL,"sql.revoke_role", SQLSTATE(01006) "REVOKE: no such role '%s' or grantee '%s'", role, grantee);
     634           9 :         grantee_id = store->table_api.column_find_sqlid(m->session->tr, auths_id, rid);
     635           9 :         rid = store->table_api.column_find_row(m->session->tr, auths_name, role, NULL);
     636           9 :         if (is_oid_nil(rid))
     637           0 :                 throw(SQL,"sql.revoke_role", SQLSTATE(01006) "REVOKE: no such role '%s' or grantee '%s'", role, grantee);
     638           9 :         role_id = store->table_api.column_find_sqlid(m->session->tr, auths_id, rid);
     639           0 :         if (!admin_privs(grantor) && !role_granting_privs(m, rid, role_id, grantor))
     640           0 :                 throw(SQL,"sql.revoke_role", SQLSTATE(0P000) "REVOKE: insufficient privileges to revoke ROLE '%s'", role);
     641             : 
     642           9 :         if (!admin) {
     643           9 :                 rid = store->table_api.column_find_row(m->session->tr, roles_login_id, &grantee_id, roles_role_id, &role_id, NULL);
     644           9 :                 if (!is_oid_nil(rid)) {
     645           7 :                         if ((log_res = store->table_api.table_delete(m->session->tr, roles, rid)) != LOG_OK)
     646           0 :                                 throw(SQL, "sql.revoke_role", SQLSTATE(42000) "REVOKE: failed%s", log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     647             :                 } else
     648           2 :                         throw(SQL,"sql.revoke_role", SQLSTATE(01006) "REVOKE: User '%s' does not have ROLE '%s'", grantee, role);
     649             :         }
     650           7 :         rid = sql_privilege_rid(m, grantee_id, role_id, PRIV_ROLE_ADMIN);
     651           7 :         if (!is_oid_nil(rid)) {
     652           1 :                 if ((log_res = store->table_api.table_delete(m->session->tr, privs, rid)) != LOG_OK)
     653           0 :                         throw(SQL, "sql.revoke_role", SQLSTATE(42000) "REVOKE: failed%s", log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     654           6 :         } else if (admin)
     655           0 :                 throw(SQL,"sql.revoke_role", SQLSTATE(01006) "REVOKE: User '%s' does not have ROLE '%s'", grantee, role);
     656             :         return NULL;
     657             : }
     658             : 
     659             : sqlid
     660       75613 : sql_find_auth(mvc *m, str auth)
     661             : {
     662             :         sqlid res = -1;
     663             :         oid rid;
     664       75613 :         sql_schema *sys = find_sql_schema(m->session->tr, "sys");
     665       75613 :         sql_table *auths = find_sql_table(m->session->tr, sys, "auths");
     666       75613 :         sql_column *auths_name = find_sql_column(auths, "name");
     667       75613 :         sqlstore *store = m->session->tr->store;
     668             : 
     669       75613 :         rid = store->table_api.column_find_row(m->session->tr, auths_name, auth, NULL);
     670             : 
     671       75613 :         if (!is_oid_nil(rid)) {
     672       75607 :                 sql_column *auths_id = find_sql_column(auths, "id");
     673       75607 :                 sqlid p = store->table_api.column_find_sqlid(m->session->tr, auths_id, rid);
     674             : 
     675             :                 if (p > -1)
     676             :                         res = p;
     677             :         }
     678       75613 :         return res;
     679             : }
     680             : 
     681             : int
     682         139 : sql_schema_has_user(mvc *m, sql_schema *s)
     683             : {
     684         139 :         return(backend_schema_has_user(m, s));
     685             : }
     686             : 
     687             : static int
     688           6 : sql_grantable_(mvc *m, sqlid grantorid, sqlid obj_id, int privs)
     689             : {
     690             :         oid rid;
     691           6 :         sql_schema *sys = find_sql_schema(m->session->tr, "sys");
     692           6 :         sql_table *prvs = find_sql_table(m->session->tr, sys, "privileges");
     693           6 :         sql_column *priv_obj = find_sql_column(prvs, "obj_id");
     694           6 :         sql_column *priv_auth = find_sql_column(prvs, "auth_id");
     695           6 :         sql_column *priv_priv = find_sql_column(prvs, "privileges");
     696           6 :         sql_column *priv_allowed = find_sql_column(prvs, "grantable");
     697           6 :         sqlstore *store = m->session->tr->store;
     698             :         int priv;
     699             : 
     700          24 :         for (priv = 1; priv <= privs; priv <<= 1) {
     701          18 :                 if (!(priv & privs))
     702           8 :                         continue;
     703          10 :                 rid = store->table_api.column_find_row(m->session->tr, priv_obj, &obj_id, priv_auth, &grantorid, priv_priv, &priv, NULL);
     704          10 :                 if (!is_oid_nil(rid)) {
     705           4 :                         int allowed = store->table_api.column_find_int(m->session->tr, priv_allowed, rid);
     706             : 
     707             :                         /* switch of priv bit */
     708           4 :                         if (allowed)
     709           4 :                                 privs = (privs & ~priv);
     710             :                 }
     711             :         }
     712           6 :         if (privs != 0)
     713           2 :                 return 0;
     714             :         return 1;
     715             : }
     716             : 
     717             : int
     718           7 : sql_grantable(mvc *m, sqlid grantorid, sqlid obj_id, int privs)
     719             : {
     720           7 :         if (admin_privs(m->user_id) || admin_privs(m->role_id))
     721             :                 return 1;
     722           6 :         return sql_grantable_(m, grantorid, obj_id, privs);
     723             : }
     724             : 
     725             : sqlid
     726          28 : mvc_set_role(mvc *m, char *role)
     727             : {
     728             :         oid rid;
     729          28 :         sql_schema *sys = find_sql_schema(m->session->tr, "sys");
     730          28 :         sql_table *auths = find_sql_table(m->session->tr, sys, "auths");
     731          28 :         sql_column *auths_name = find_sql_column(auths, "name");
     732             :         sqlid res = 0;
     733          28 :         sqlstore *store = m->session->tr->store;
     734             : 
     735          28 :         TRC_DEBUG(SQL_TRANS, "Set role: %s\n", role);
     736             : 
     737          28 :         rid = store->table_api.column_find_row(m->session->tr, auths_name, role, NULL);
     738          28 :         if (!is_oid_nil(rid)) {
     739          26 :                 sql_column *auths_id = find_sql_column(auths, "id");
     740          26 :                 sqlid id = store->table_api.column_find_sqlid(m->session->tr, auths_id, rid);
     741             : 
     742          26 :                 if (m->user_id == id) {
     743           2 :                         m->role_id = id;
     744             :                         res = 1;
     745             :                 } else {
     746          24 :                         sql_table *roles = find_sql_table(m->session->tr, sys, "user_role");
     747          24 :                         sql_column *role_id = find_sql_column(roles, "role_id");
     748          24 :                         sql_column *login_id = find_sql_column(roles, "login_id");
     749             : 
     750          24 :                         rid = store->table_api.column_find_row(m->session->tr, login_id, &m->user_id, role_id, &id, NULL);
     751          24 :                         if (!is_oid_nil(rid)) {
     752          17 :                                 m->role_id = id;
     753             :                                 res = 1;
     754             :                         }
     755             :                 }
     756             :         }
     757          28 :         return res;
     758             : }
     759             : 
     760             : int
     761        5282 : mvc_set_schema(mvc *m, char *schema)
     762             : {
     763             :         int ret = 0;
     764        5282 :         sql_schema *s = find_sql_schema(m->session->tr, schema);
     765        5282 :         char* new_schema_name = sa_strdup(m->session->sa, schema);
     766             : 
     767        5282 :         if (s && new_schema_name) {
     768        5281 :                 m->session->schema_name = new_schema_name;
     769        5281 :                 m->type = Q_SCHEMA;
     770        5281 :                 if (m->session->tr->active)
     771        5273 :                         m->session->schema = s;
     772             :                 ret = 1;
     773             :         }
     774        5282 :         return ret;
     775             : }
     776             : 
     777             : char *
     778         272 : sql_create_user(mvc *sql, char *user, char *passwd, char enc, char *fullname, char *schema, char *schema_path)
     779             : {
     780             :         char *err;
     781             :         sql_schema *s = NULL;
     782             :         sqlid schema_id = 0;
     783             : 
     784         272 :         if (!admin_privs(sql->user_id) && !admin_privs(sql->role_id))
     785           1 :                 throw(SQL,"sql.create_user", SQLSTATE(42M31) "Insufficient privileges to create user '%s'", user);
     786             : 
     787         271 :         if (backend_find_user(sql, user) >= 0)
     788           2 :                 throw(SQL,"sql.create_user", SQLSTATE(42M31) "CREATE USER: user '%s' already exists", user);        
     789             : 
     790         269 :         if (!(s = find_sql_schema(sql->session->tr, schema)))
     791           1 :                 throw(SQL,"sql.create_user", SQLSTATE(3F000) "CREATE USER: no such schema '%s'", schema);
     792         268 :         schema_id = s->base.id;
     793         268 :         if (!isNew(s) && sql_trans_add_dependency(sql->session->tr, schema_id, ddl) != LOG_OK)
     794           0 :                 throw(SQL, "sql.create_user", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     795         268 :         if (sql_trans_add_dependency(sql->session->tr, sql->user_id, ddl) != LOG_OK)
     796           0 :                 throw(SQL, "sql.create_user", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     797             : 
     798         268 :         if ((err = backend_create_user(sql, user, passwd, enc, fullname, schema_id, schema_path, sql->user_id)) != NULL)
     799             :         {
     800             :                 /* strip off MAL exception decorations */
     801             :                 char *r;
     802             :                 char *e = err;
     803           0 :                 if ((e = strchr(e, ':')) == NULL) {
     804             :                         e = err;
     805           0 :                 } else if ((e = strchr(++e, ':')) == NULL) {
     806             :                         e = err;
     807             :                 } else {
     808           0 :                         e++;
     809             :                 }
     810           0 :                 r = createException(SQL,"sql.create_user", SQLSTATE(M0M27) "CREATE USER: %s", e);
     811           0 :                 _DELETE(err);
     812           0 :                 return r;
     813             :         }
     814             :         return NULL;
     815             : }
     816             : 
     817             : static int
     818           0 : id_cmp(sqlid *id1, sqlid *id2)
     819             : {
     820           0 :         return *id1 == *id2;
     821             : }
     822             : 
     823             : static char *
     824          79 : sql_drop_granted_users(mvc *sql, sqlid user_id, char *user, list *deleted_users)
     825             : {
     826          79 :         sql_schema *ss = mvc_bind_schema(sql, "sys");
     827          79 :         sql_table *privs = find_sql_table(sql->session->tr, ss, "privileges");
     828          79 :         sql_table *user_roles = find_sql_table(sql->session->tr, ss, "user_role");
     829          79 :         sql_table *auths = find_sql_table(sql->session->tr, ss, "auths");
     830          79 :         sql_trans *tr = sql->session->tr;
     831          79 :         sqlstore *store = tr->store;
     832             :         rids *A;
     833             :         oid rid;
     834             :         int log_res = LOG_OK;
     835             :         char *msg = NULL;
     836             : 
     837          79 :         if (!list_find(deleted_users, &user_id, (fcmp) &id_cmp)) {
     838          79 :                 if (mvc_check_dependency(sql, user_id, OWNER_DEPENDENCY, NULL))
     839           4 :                         throw(SQL,"sql.drop_user",SQLSTATE(M1M05) "DROP USER: '%s' owns a schema", user);
     840          75 :                 if (backend_drop_user(sql, user) == FALSE)
     841           1 :                         throw(SQL,"sql.drop_user",SQLSTATE(M0M27) "%s", sql->errstr);
     842             : 
     843             :                 /* select privileges of this user_id */
     844          74 :                 A = store->table_api.rids_select(tr, find_sql_column(privs, "auth_id"), &user_id, &user_id, NULL);
     845             :                 /* remove them */
     846         109 :                 for(rid = store->table_api.rids_next(A); !is_oid_nil(rid) && log_res == LOG_OK; rid = store->table_api.rids_next(A))
     847          35 :                         log_res = store->table_api.table_delete(tr, privs, rid);
     848          74 :                 store->table_api.rids_destroy(A);
     849          74 :                 if (log_res != LOG_OK)
     850           0 :                         throw(SQL, "sql.drop_user", SQLSTATE(42000) "DROP USER: failed%s", log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     851             : 
     852             :                 /* select privileges granted by this user_id */
     853          74 :                 A = store->table_api.rids_select(tr, find_sql_column(privs, "grantor"), &user_id, &user_id, NULL);
     854             :                 /* remove them */
     855          74 :                 for(rid = store->table_api.rids_next(A); !is_oid_nil(rid) && log_res == LOG_OK; rid = store->table_api.rids_next(A))
     856           0 :                         log_res = store->table_api.table_delete(tr, privs, rid);
     857          74 :                 store->table_api.rids_destroy(A);
     858          74 :                 if (log_res != LOG_OK)
     859           0 :                         throw(SQL, "sql.drop_user", SQLSTATE(42000) "DROP USER: failed%s", log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     860             : 
     861             :                 /* delete entry from auths table */
     862          74 :                 rid = store->table_api.column_find_row(tr, find_sql_column(auths, "name"), user, NULL);
     863          74 :                 if (is_oid_nil(rid))
     864           1 :                         throw(SQL, "sql.drop_user", SQLSTATE(0P000) "DROP USER: no such user role '%s'", user);
     865          73 :                 if ((log_res = store->table_api.table_delete(tr, auths, rid)) != LOG_OK)
     866           0 :                         throw(SQL, "sql.drop_user", SQLSTATE(42000) "DROP USER: failed%s", log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     867             : 
     868             :                 /* select user roles of this user_id */
     869          73 :                 A = store->table_api.rids_select(tr, find_sql_column(user_roles, "login_id"), &user_id, &user_id, NULL);
     870             :                 /* remove them */
     871          93 :                 for(rid = store->table_api.rids_next(A); !is_oid_nil(rid) && log_res == LOG_OK; rid = store->table_api.rids_next(A))
     872          20 :                         log_res = store->table_api.table_delete(tr, user_roles, rid);
     873          73 :                 store->table_api.rids_destroy(A);
     874          73 :                 if (log_res != LOG_OK)
     875           0 :                         throw(SQL, "sql.drop_user", SQLSTATE(42000) "DROP USER: failed%s", log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     876             : 
     877          73 :                 list_append(deleted_users, &user_id);
     878             : 
     879             :                 /* select users created by this user_id */
     880          73 :                 A = store->table_api.rids_select(tr, find_sql_column(auths, "grantor"), &user_id, &user_id, NULL);
     881             :                 /* remove them and continue the deletion */
     882          73 :                 for(rid = store->table_api.rids_next(A); !is_oid_nil(rid) && log_res == LOG_OK && msg; rid = store->table_api.rids_next(A)) {
     883             :                         sqlid nuid = store->table_api.column_find_sqlid(tr, find_sql_column(auths, "id"), rid);
     884             :                         char *nname = store->table_api.column_find_value(tr, find_sql_column(auths, "name"), rid);
     885             : 
     886             :                         if (!nname)
     887             :                                 msg = createException(SQL, "sql.drop_user", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     888             :                         else if (!(msg = sql_drop_granted_users(sql, nuid, nname, deleted_users)))
     889             :                                 log_res = store->table_api.table_delete(tr, auths, rid);
     890             :                         _DELETE(nname);
     891             :                 }
     892          73 :                 store->table_api.rids_destroy(A);
     893             :                 if (!msg && log_res != LOG_OK)
     894             :                         throw(SQL, "sql.drop_user", SQLSTATE(42000) "DROP USER: failed%s", log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     895             :         }
     896             :         return msg;
     897             : }
     898             : 
     899             : char *
     900          79 : sql_drop_user(mvc *sql, char *user)
     901             : {
     902          79 :         sqlid user_id = sql_find_auth(sql, user);
     903          79 :         list *deleted = list_create(NULL);
     904             :         str msg = NULL;
     905             : 
     906          79 :         if (!deleted)
     907           0 :                 throw(SQL, "sql.drop_user", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     908          79 :         msg = sql_drop_granted_users(sql, user_id, user, deleted);
     909          79 :         list_destroy(deleted);
     910             : 
     911             :         /* Flag as removed */
     912          79 :         if (!msg && sql_trans_add_dependency_change(sql->session->tr, user_id, ddl) != LOG_OK)
     913           0 :                 throw(SQL, "sql.drop_user", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     914             :         return msg;
     915             : }
     916             : 
     917             : char *
     918          59 : sql_alter_user(mvc *sql, char *user, char *passwd, char enc, char *schema, char *schema_path, char *oldpasswd)
     919             : {
     920             :         sql_schema *s = NULL;
     921             :         sqlid schema_id = 0;
     922             : 
     923             :         /* we may be called from MAL (nil) */
     924          59 :         if (strNil(user))
     925             :                 user = NULL;
     926             :         /* USER == NULL -> current_user */
     927             : 
     928          59 :         if (!admin_privs(sql->user_id) && !admin_privs(sql->role_id) && user != NULL && strcmp(user, get_string_global_var(sql, "current_user")) != 0)
     929           0 :                 throw(SQL,"sql.alter_user", SQLSTATE(M1M05) "Insufficient privileges to change user '%s'", user);
     930             : 
     931          59 :         if (user != NULL && backend_find_user(sql, user) < 0)
     932           1 :                 throw(SQL,"sql.alter_user", SQLSTATE(42M32) "ALTER USER: no such user '%s'", user);
     933          58 :         if (schema) {
     934          47 :                 if (!(s = find_sql_schema(sql->session->tr, schema)))
     935           1 :                         throw(SQL,"sql.alter_user", SQLSTATE(3F000) "ALTER USER: no such schema '%s'", schema);
     936          46 :                 schema_id = s->base.id;
     937          46 :                 if (!isNew(s) && sql_trans_add_dependency(sql->session->tr, s->base.id, ddl) != LOG_OK)
     938           0 :                         throw(SQL, "sql.alter_user", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     939             :         }
     940          57 :         if (backend_alter_user(sql, user, passwd, enc, schema_id, schema_path, oldpasswd) == FALSE)
     941           6 :                 throw(SQL,"sql.alter_user", SQLSTATE(M0M27) "%s", sql->errstr);
     942             :         return NULL;
     943             : }
     944             : 
     945             : char *
     946           5 : sql_rename_user(mvc *sql, char *olduser, char *newuser)
     947             : {
     948           5 :         if (!admin_privs(sql->user_id) && !admin_privs(sql->role_id))
     949           1 :                 throw(SQL,"sql.rename_user", SQLSTATE(M1M05) "ALTER USER: insufficient privileges to rename user '%s'", olduser);
     950             : 
     951           4 :         if (backend_find_user(sql, olduser) < 0)
     952           1 :                 throw(SQL,"sql.rename_user", SQLSTATE(42M32) "ALTER USER: no such user '%s'", olduser);
     953           3 :         if (backend_find_user(sql, newuser) >= 0)
     954           1 :                 throw(SQL,"sql.rename_user", SQLSTATE(42M31) "ALTER USER: user '%s' already exists", newuser);
     955           2 :         if (backend_rename_user(sql, olduser, newuser) == FALSE)
     956           0 :                 throw(SQL,"sql.rename_user", SQLSTATE(M1M05) "%s", sql->errstr);
     957             :         return NULL;
     958             : }
     959             : 
     960             : int
     961         186 : sql_create_privileges(mvc *m, sql_schema *s)
     962             : {
     963         186 :         int pub, p, zero = 0;
     964         186 :         sql_table *t = NULL, *privs = NULL;
     965         186 :         sql_column *col = NULL;
     966             :         sql_subfunc *f = NULL;
     967         186 :         sql_trans *tr = m->session->tr;
     968             : 
     969         186 :         backend_create_privileges(m, s);
     970             : 
     971         186 :         mvc_create_table(&t, m, s, "user_role", tt_table, 1, SQL_PERSIST, 0, -1, 0);
     972         186 :         mvc_create_column_(&col, m, t, "login_id", "int", 32);
     973         186 :         mvc_create_column_(&col, m, t, "role_id", "int", 32);
     974             : 
     975             :         /* all roles and users are in the auths table */
     976         186 :         mvc_create_table(&t, m, s, "auths", tt_table, 1, SQL_PERSIST, 0, -1, 0);
     977         186 :         mvc_create_column_(&col, m, t, "id", "int", 32);
     978         186 :         mvc_create_column_(&col, m, t, "name", "varchar", 1024);
     979         186 :         mvc_create_column_(&col, m, t, "grantor", "int", 32);
     980             : 
     981         186 :         mvc_create_table(&t, m, s, "privileges", tt_table, 1, SQL_PERSIST, 0, -1, 0);
     982         186 :         mvc_create_column_(&col, m, t, "obj_id", "int", 32);
     983         186 :         mvc_create_column_(&col, m, t, "auth_id", "int", 32);
     984         186 :         mvc_create_column_(&col, m, t, "privileges", "int", 32);
     985         186 :         mvc_create_column_(&col, m, t, "grantor", "int", 32);
     986         186 :         mvc_create_column_(&col, m, t, "grantable", "int", 32);
     987             : 
     988             :         /* add roles public and sysadmin and user monetdb */
     989         186 :         sql_create_auth_id(m, ROLE_PUBLIC, "public");
     990         186 :         sql_create_auth_id(m, ROLE_SYSADMIN, "sysadmin");
     991         186 :         sql_create_auth_id(m, USER_MONETDB, "monetdb");
     992             : 
     993         186 :         pub = ROLE_PUBLIC;
     994         186 :         p = PRIV_SELECT;
     995         186 :         privs = find_sql_table(tr, s, "privileges");
     996             : 
     997         186 :         sqlstore *store = m->session->tr->store;
     998         186 :         t = find_sql_table(tr, s, "schemas");
     999         186 :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1000         186 :         t = find_sql_table(tr, s, "types");
    1001         186 :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1002         186 :         t = find_sql_table(tr, s, "functions");
    1003         186 :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1004         186 :         t = find_sql_table(tr, s, "args");
    1005         186 :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1006         186 :         t = find_sql_table(tr, s, "sequences");
    1007         186 :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1008         186 :         t = find_sql_table(tr, s, "dependencies");
    1009         186 :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1010         186 :         t = find_sql_table(tr, s, "_tables");
    1011         186 :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1012         186 :         t = find_sql_table(tr, s, "_columns");
    1013         186 :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1014         186 :         t = find_sql_table(tr, s, "keys");
    1015         186 :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1016         186 :         t = find_sql_table(tr, s, "idxs");
    1017         186 :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1018         186 :         t = find_sql_table(tr, s, "triggers");
    1019         186 :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1020         186 :         t = find_sql_table(tr, s, "objects");
    1021         186 :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1022         186 :         t = find_sql_table(tr, s, "tables");
    1023         186 :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1024         186 :         t = find_sql_table(tr, s, "columns");
    1025         186 :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1026         186 :         t = find_sql_table(tr, s, "comments");
    1027         186 :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1028         186 :         t = find_sql_table(tr, s, "user_role");
    1029         186 :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1030         186 :         t = find_sql_table(tr, s, "auths");
    1031         186 :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1032         186 :         t = find_sql_table(tr, s, "privileges");
    1033         186 :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1034         186 :         t = find_sql_table(tr, s, "table_partitions");
    1035         186 :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1036         186 :         t = find_sql_table(tr, s, "range_partitions");
    1037         186 :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1038         186 :         t = find_sql_table(tr, s, "value_partitions");
    1039         186 :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1040             : 
    1041         186 :         p = PRIV_EXECUTE;
    1042         186 :         f = sql_bind_func_(m, s->base.name, "env", NULL, F_UNION);
    1043         186 :         store->table_api.table_insert(m->session->tr, privs, &f->func->base.id, &pub, &p, &zero, &zero);
    1044         186 :         f = sql_bind_func_(m, s->base.name, "var", NULL, F_UNION);
    1045         186 :         store->table_api.table_insert(m->session->tr, privs, &f->func->base.id, &pub, &p, &zero, &zero);
    1046             : 
    1047             :         /* owned by the users anyway
    1048             :         s = mvc_bind_schema(m, "tmp");
    1049             :         t = find_sql_table(tr, s, "profile");
    1050             :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1051             :         t = find_sql_table(tr, s, "_tables");
    1052             :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1053             :         t = find_sql_table(tr, s, "_columns");
    1054             :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1055             :         t = find_sql_table(tr, s, "keys");
    1056             :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1057             :         t = find_sql_table(tr, s, "idxs");
    1058             :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1059             :         t = find_sql_table(tr, s, "triggers");
    1060             :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1061             :         t = find_sql_table(tr, s, "objects");
    1062             :         store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
    1063             :         */
    1064             : 
    1065         186 :         return 0;
    1066             : }

Generated by: LCOV version 1.14