LCOV - code coverage report
Current view: top level - sql/backends/monet5 - sql_user.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 419 597 70.2 %
Date: 2024-04-25 20:03:45 Functions: 21 23 91.3 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : /*
      14             :  * @f sql_user
      15             :  * @t SQL catalog management
      16             :  * @a N. Nes, F. Groffen
      17             :  * @+ SQL user
      18             :  * The SQL user and authorisation implementation differs per backend.  This
      19             :  * file implements the authorisation and user management based on the M5
      20             :  * system authorisation.
      21             :  */
      22             : #include "monetdb_config.h"
      23             : #include "sql_user.h"
      24             : #include "sql_mvc.h"
      25             : #include "sql_privileges.h"
      26             : #include "mal_interpreter.h"
      27             : #include "mal_authorize.h"
      28             : #include "mcrypt.h"
      29             : #include "sql_execute.h"
      30             : 
      31             : static inline sql_table*
      32       76475 : getUsersTbl(mvc *m)
      33             : {
      34       76475 :         sql_trans *tr = m->session->tr;
      35       76475 :         sql_schema *sys = find_sql_schema(tr, "sys");
      36       76475 :         return find_sql_table(tr, sys, USER_TABLE_NAME);
      37             : }
      38             : 
      39             : oid
      40       38465 : getUserOIDByName(mvc *m, const char *user)
      41             : {
      42       38465 :         sql_trans *tr = m->session->tr;
      43       38465 :         sqlstore *store = m->session->tr->store;
      44       38465 :         sql_table *users = getUsersTbl(m);
      45       38465 :         sql_column *users_name = find_sql_column(users, "name");
      46       38465 :         return store->table_api.column_find_row(tr, users_name, user, NULL);
      47             : }
      48             : 
      49             : 
      50             : static str
      51           2 : getUserName(mvc *m, oid rid)
      52             : {
      53           2 :         if (is_oid_nil(rid))
      54             :                 return NULL;
      55           2 :         sql_trans *tr = m->session->tr;
      56           2 :         sqlstore *store = m->session->tr->store;
      57           2 :         sql_table *users = getUsersTbl(m);
      58           2 :         return store->table_api.column_find_value(tr, find_sql_column(users, "name"), rid);
      59             : }
      60             : 
      61             : str
      62       38010 : getUserPassword(mvc *m, oid rid)
      63             : {
      64       38010 :         if (is_oid_nil(rid)) {
      65             :                 return NULL;
      66             :         }
      67       38006 :         sql_trans *tr = m->session->tr;
      68       38006 :         sqlstore *store = m->session->tr->store;
      69       38006 :         sql_table *users = getUsersTbl(m);
      70       38006 :         return store->table_api.column_find_value(tr, find_sql_column(users, USER_PASSWORD_COLUMN), rid);
      71             : }
      72             : 
      73             : 
      74             : static int
      75           3 : setUserPassword(mvc *m, oid rid, str value)
      76             : {
      77           3 :         str err = NULL;
      78           3 :         str hash = NULL;
      79           3 :         int res;
      80           3 :         if (is_oid_nil(rid)) {
      81           0 :                 (void) sql_error(m, 02, SQLSTATE(42000) "setUserPassword: invalid user");
      82           0 :                 return LOG_ERR;
      83             :         }
      84           3 :         if (strNil(value)) {
      85           0 :                 (void) sql_error(m, 02, SQLSTATE(42000) "setUserPassword: password cannot be nil");
      86           0 :                 return LOG_ERR;
      87             :         }
      88           3 :         if ((err = AUTHverifyPassword(value)) != MAL_SUCCEED) {
      89           0 :                 (void) sql_error(m, 02, SQLSTATE(42000) "setUserPassword: %s", getExceptionMessage(err));
      90           0 :                 freeException(err);
      91           0 :                 return LOG_ERR;
      92             :         }
      93           3 :         if ((err = AUTHcypherValue(&hash, value)) != MAL_SUCCEED) {
      94           0 :                 (void) sql_error(m, 02, SQLSTATE(42000) "setUserPassword: %s", getExceptionMessage(err));
      95           0 :                 freeException(err);
      96           0 :                 GDKfree(hash);
      97           0 :                 return LOG_ERR;
      98             :         }
      99             : 
     100           3 :         sql_trans *tr = m->session->tr;
     101           3 :         sqlstore *store = m->session->tr->store;
     102           3 :         sql_table *users = getUsersTbl(m);
     103           3 :         res = store->table_api.column_update_value(tr, find_sql_column(users, USER_PASSWORD_COLUMN), rid, hash);
     104           3 :         GDKfree(hash);
     105           3 :         return res;
     106             : }
     107             : 
     108             : 
     109             : static int
     110           2 : changeUserPassword(mvc *m, oid rid, str oldpass, str newpass)
     111             : {
     112           2 :         str err = NULL;
     113           2 :         str hash = NULL;
     114           2 :         str passValue = NULL;
     115           2 :         if (is_oid_nil(rid)) {
     116           0 :                 (void) sql_error(m, 02, SQLSTATE(42000) "changeUserPassword: invalid user");
     117           0 :                 return LOG_ERR;
     118             :         }
     119           2 :         if (strNil(newpass)) {
     120           0 :                 (void) sql_error(m, 02, SQLSTATE(42000) "changeUserPassword: password cannot be nil");
     121           0 :                 return LOG_ERR;
     122             :         }
     123           2 :         if (oldpass) {
     124             :                 // validate old password match
     125           2 :                 if ((err = AUTHdecypherValue(&hash, passValue=getUserPassword(m, rid))) != MAL_SUCCEED) {
     126           0 :                         (void) sql_error(m, 02, SQLSTATE(42000) "changeUserPassword: %s", getExceptionMessage(err));
     127           0 :                         freeException(err);
     128           0 :                         GDKfree(passValue);
     129           0 :                         return LOG_ERR;
     130             :                 }
     131           2 :                 GDKfree(passValue);
     132           2 :                 if (strcmp(oldpass, hash) != 0) {
     133           1 :                         (void) sql_error(m, 02, SQLSTATE(42000) "changeUserPassword: password mismatch");
     134           1 :                         GDKfree(hash);
     135           1 :                         return LOG_ERR;
     136             :                 }
     137           1 :                 GDKfree(hash);
     138             :         }
     139           1 :         return setUserPassword(m, rid, newpass);
     140             : }
     141             : 
     142             : 
     143             : static int
     144          10 : monet5_find_role(ptr _mvc, str role, sqlid *role_id)
     145             : {
     146          10 :         mvc *m = (mvc *) _mvc;
     147          10 :         sql_trans *tr = m->session->tr;
     148          10 :         sqlstore *store = m->session->tr->store;
     149          10 :         sql_schema *sys = find_sql_schema(tr, "sys");
     150          10 :         sql_table *auths = find_sql_table(tr, sys, "auths");
     151          10 :         sql_column *auth_name = find_sql_column(auths, "name");
     152          10 :         oid rid = store->table_api.column_find_row(tr, auth_name, role, NULL);
     153          10 :         if (is_oid_nil(rid))
     154             :                 return -1;
     155          10 :         *role_id = store->table_api.column_find_sqlid(m->session->tr, find_sql_column(auths, "id"), rid);
     156          10 :         return 1;
     157             : }
     158             : 
     159             : 
     160             : static int
     161          93 : monet5_drop_user(ptr _mvc, str user)
     162             : {
     163          93 :         mvc *m = (mvc *) _mvc;
     164          93 :         oid rid;
     165          93 :         sql_schema *sys = find_sql_schema(m->session->tr, "sys");
     166          93 :         sql_table *users = find_sql_table(m->session->tr, sys, "db_user_info");
     167          93 :         sql_column *users_name = find_sql_column(users, "name");
     168          93 :         sqlstore *store = m->session->tr->store;
     169          93 :         int log_res = LOG_OK;
     170             : 
     171          93 :         rid = store->table_api.column_find_row(m->session->tr, users_name, user, NULL);
     172          93 :         if (!is_oid_nil(rid) && (log_res = store->table_api.table_delete(m->session->tr, users, rid)) != LOG_OK) {
     173           0 :                 (void) sql_error(m, 02, "DROP USER: failed%s", log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     174           0 :                 return FALSE;
     175             :         }
     176             : 
     177             :         return TRUE;
     178             : }
     179             : 
     180             : #define outside_str 1
     181             : #define inside_str 2
     182             : #define default_schema_path "\"sys\"" /* "sys" will be the default schema path */
     183             : #define default_optimizer "default_pipe"
     184             : #define MAX_SCHEMA_SIZE 1024
     185             : 
     186             : 
     187             : static str
     188       38216 : parse_schema_path_str(mvc *m, str schema_path, bool build) /* this function for both building and validating the schema path */
     189             : {
     190       38216 :         list *l = m->schema_path;
     191       38216 :         char next_schema[MAX_SCHEMA_SIZE]; /* needs one extra character for null terminator */
     192       38216 :         int status = outside_str;
     193       38216 :         size_t bp = 0;
     194             : 
     195       38216 :         if (strNil(schema_path))
     196           0 :                 throw(SQL, "sql.schema_path", SQLSTATE(42000) "A schema path cannot be NULL");
     197             : 
     198       38216 :         if (build) {
     199       75760 :                 while (l->t) /* if building, empty schema_path list */
     200       37880 :                         (void) list_remove_node(l, NULL, l->t);
     201       37880 :                 m->schema_path_has_sys = false;
     202       37880 :                 m->schema_path_has_tmp = false;
     203             :         }
     204             : 
     205      231379 :         for (size_t i = 0; schema_path[i]; i++) {
     206      193167 :                 char next = schema_path[i];
     207             : 
     208      193167 :                 if (next == '"') {
     209       76439 :                         if (status == inside_str && schema_path[i + 1] == '"') {
     210           2 :                                 next_schema[bp++] = '"';
     211           2 :                                 i++; /* has to advance two positions */
     212       38223 :                         } else if (status == inside_str) {
     213       38223 :                                 if (bp == 0)
     214           1 :                                         throw(SQL, "sql.schema_path", SQLSTATE(42000) "A schema name cannot be empty");
     215       38222 :                                 if (bp == 1023)
     216           1 :                                         throw(SQL, "sql.schema_path", SQLSTATE(42000) "A schema has up to 1023 characters");
     217             : 
     218       38221 :                                 if (build) {
     219       37885 :                                         char *val = NULL;
     220       37885 :                                         next_schema[bp++] = '\0';
     221       37885 :                                         if (!(val = _STRDUP(next_schema)) || !list_append(l, val)) {
     222           0 :                                                 _DELETE(val);
     223           0 :                                                 throw(SQL, "sql.schema_path", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     224             :                                         }
     225       37885 :                                         if (strcmp(next_schema, "sys") == 0)
     226       37876 :                                                 m->schema_path_has_sys = true;
     227           9 :                                         else if (strcmp(next_schema, "tmp") == 0)
     228           0 :                                                 m->schema_path_has_tmp = true;
     229             :                                 }
     230             : 
     231             :                                 bp = 0;
     232             :                                 status = outside_str;
     233             :                         } else {
     234       38214 :                                 assert(status == outside_str);
     235             :                                 status = inside_str;
     236             :                         }
     237      116728 :                 } else if (next == ',') {
     238          12 :                         if (status == outside_str && schema_path[i + 1] == '"') {
     239             :                                 status = inside_str;
     240             :                                 i++; /* has to advance two positions */
     241           2 :                         } else if (status == inside_str) {
     242           2 :                                 if (bp == 1023)
     243           0 :                                         throw(SQL, "sql.schema_path", SQLSTATE(42000) "A schema has up to 1023 characters");
     244           2 :                                 next_schema[bp++] = ','; /* used inside a schema name */
     245           0 :                         } else if (status == outside_str) {
     246           0 :                                 throw(SQL, "sql.schema_path", SQLSTATE(42000) "The '\"' character is expected after the comma separator");
     247             :                         }
     248      116716 :                 } else if (status == inside_str) {
     249      116714 :                         if (bp == 1023)
     250           0 :                                 throw(SQL, "sql.schema_path", SQLSTATE(42000) "A schema has up to 1023 characters");
     251      116714 :                         if (bp == 0 && next == '%')
     252           0 :                                 throw(SQL, "sql.schema_path", SQLSTATE(42000) "The character '%%' is not allowed as the first schema character");
     253      116714 :                         next_schema[bp++] = next;
     254             :                 } else {
     255           2 :                         assert(status == outside_str);
     256           2 :                         throw(SQL, "sql.schema_path", SQLSTATE(42000) "A schema in the path must be within '\"'");
     257             :                 }
     258             :         }
     259       38212 :         if (status == inside_str)
     260           1 :                 throw(SQL, "sql.schema_path", SQLSTATE(42000) "A schema path cannot end inside inside a schema name");
     261             :         return MAL_SUCCEED;
     262             : }
     263             : 
     264             : static str
     265         328 : monet5_create_user(ptr _mvc, str user, str passwd, bool enc, str fullname, sqlid schema_id, str schema_path, sqlid grantorid, lng max_memory, int max_workers, str optimizer, sqlid role_id)
     266             : {
     267         328 :         mvc *m = (mvc *) _mvc;
     268         328 :         oid rid;
     269         328 :         str ret, err, pwd, hash, schema_buf = NULL;
     270         328 :         sqlid user_id;
     271         328 :         sql_schema *s = find_sql_schema(m->session->tr, "sys");
     272         328 :         sql_table *db_user_info = find_sql_table(m->session->tr, s, "db_user_info"),
     273         328 :                           *auths = find_sql_table(m->session->tr, s, "auths"),
     274         328 :                           *schemas_tbl = find_sql_table(m->session->tr, s, "schemas");
     275             :         // Client c = MCgetClient(m->clientid);
     276         328 :         sqlstore *store = m->session->tr->store;
     277         328 :         int log_res = 0;
     278         328 :         bool new_schema = false;
     279             : 
     280         328 :         if (schema_id == 0) {
     281             :                 // create default schema matching $user
     282          13 :                 switch (sql_trans_create_schema(m->session->tr, user, m->role_id, m->user_id, &schema_id)) {
     283           0 :                         case -1:
     284           0 :                                 throw(SQL,"sql.create_user",SQLSTATE(HY013) MAL_MALLOC_FAIL);
     285           0 :                         case -2:
     286             :                         case -3:
     287           0 :                                 throw(SQL,"sql.create_user",SQLSTATE(42000) "Create user schema failed due to transaction conflict");
     288             :                         default:
     289             :                                 break;
     290             :                 }
     291             :                 new_schema = true;
     292             :         }
     293         328 :         assert(schema_id);
     294             : 
     295         328 :         if (is_oid_nil(rid = store->table_api.column_find_row(m->session->tr, find_sql_column(schemas_tbl, "id"), &schema_id, NULL)))
     296           0 :                 throw(SQL,"sql.create_user",SQLSTATE(42000) "User schema not found");
     297             : 
     298         328 :         if (!schema_path) {
     299             :                 // schema_name = store->table_api.column_find_value(m->session->tr, find_sql_column(schemas_tbl, "name"), rid);
     300             :                 // if (schema_name) {
     301             :                 //      // "\"$schema_name\"\0"
     302             :                 //      if ((strlen(schema_name) + 4) > MAX_SCHEMA_SIZE) {
     303             :                 //              if (schema_name)
     304             :                 //                      GDKfree(schema_name);
     305             :                 //              throw(SQL, "sql.schema_path", SQLSTATE(42000) "A schema has up to 1023 characters");
     306             :                 //      }
     307             :                 //      schema_buf = GDKmalloc(MAX_SCHEMA_SIZE);
     308             :                 //      snprintf(schema_buf, MAX_SCHEMA_SIZE, "\"%s\"", schema_name);
     309             :                 //      schema_path = schema_buf;
     310             :                 //      GDKfree(schema_name);
     311             :                 // } else {
     312             :                 //      schema_path = default_schema_path;
     313             :                 // }
     314         325 :                 schema_path = default_schema_path;
     315             :         }
     316             : 
     317         328 :         if ((ret = parse_schema_path_str(m, schema_path, false)) != MAL_SUCCEED) {
     318           1 :                 GDKfree(schema_buf);
     319           1 :                 return ret;
     320             :         }
     321             : 
     322         327 :         if (!optimizer)
     323         323 :                 optimizer = default_optimizer;
     324             : 
     325         327 :         if (!enc) {
     326          95 :                 if (!(pwd = mcrypt_BackendSum(passwd, strlen(passwd)))) {
     327           0 :                         GDKfree(schema_buf);
     328           0 :                         throw(MAL, "sql.create_user", SQLSTATE(42000) "Crypt backend hash not found");
     329             :                 }
     330             :         } else {
     331             :                 pwd = passwd;
     332             :         }
     333             : 
     334         327 :         err = AUTHGeneratePasswordHash(&hash, pwd);
     335         327 :         if (!enc)
     336          95 :                 free(pwd);
     337         327 :         if (err != MAL_SUCCEED) {
     338           0 :                 GDKfree(schema_buf);
     339           0 :                 throw(MAL, "sql.create_user", SQLSTATE(42000) "create backend hash failure");
     340             :         }
     341             : 
     342         327 :         user_id = store_next_oid(m->session->tr->store);
     343         327 :         sqlid default_role_id = role_id > 0 ? role_id : user_id;
     344         327 :         if ((log_res = store->table_api.table_insert(m->session->tr, db_user_info, &user, &fullname, &schema_id, &schema_path, &max_memory, &max_workers, &optimizer, &default_role_id, &hash))) {
     345           1 :                 GDKfree(schema_buf);
     346           1 :                 GDKfree(hash);
     347           1 :                 throw(SQL, "sql.create_user", SQLSTATE(42000) "Create user failed%s", log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     348             :         }
     349             :         // clean up
     350         326 :         GDKfree(schema_buf);
     351         326 :         GDKfree(hash);
     352             : 
     353         326 :         if ((log_res = store->table_api.table_insert(m->session->tr, auths, &user_id, &user, &grantorid))) {
     354           0 :                 throw(SQL, "sql.create_user", SQLSTATE(42000) "Create user failed%s", log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     355             :         }
     356             : 
     357         326 :         if (new_schema) {
     358             :                 // update schema authorization to be default_role_id
     359          12 :                 switch (sql_trans_change_schema_authorization(m->session->tr, schema_id, default_role_id)) {
     360           0 :                         case -1:
     361           0 :                                 throw(SQL,"sql.create_user",SQLSTATE(HY013) MAL_MALLOC_FAIL);
     362           0 :                         case -2:
     363             :                         case -3:
     364           0 :                                 throw(SQL,"sql.create_user",SQLSTATE(42000) "Update schema authorization failed due to transaction conflict");
     365             :                         default:
     366             :                                 break;
     367             :                 }
     368             : 
     369             :         }
     370             :         return ret;
     371             : }
     372             : 
     373             : static oid
     374         455 : monet5_find_user(ptr mp, str user)
     375             : {
     376         455 :         return getUserOIDByName((mvc *) mp, user);
     377             : }
     378             : 
     379             : str
     380          42 : monet5_password_hash(mvc *m, const char *username)
     381             : {
     382          42 :         str msg, hash = NULL;
     383          42 :         oid rid = getUserOIDByName(m, username);
     384          42 :         str password = getUserPassword(m, rid);
     385          42 :         if (password) {
     386          42 :                 msg = AUTHdecypherValue(&hash, password);
     387          42 :                 GDKfree(password);
     388          42 :                 if (msg) {
     389           0 :                         (void) sql_error(m, 02, SQLSTATE(42000) "monet5_password_hash: %s", getExceptionMessage(msg));
     390           0 :                         freeException(msg);
     391             :                 }
     392             :         }
     393          42 :         return hash;
     394             : }
     395             : 
     396             : static void
     397         223 : monet5_create_privileges(ptr _mvc, sql_schema *s, const char *initpasswd)
     398             : {
     399         223 :         sql_schema *sys;
     400         223 :         sql_table *t = NULL;
     401         223 :         sql_table *uinfo = NULL;
     402         223 :         sql_column *col = NULL;
     403         223 :         mvc *m = (mvc *) _mvc;
     404         223 :         sqlid schema_id = 0;
     405         223 :         str err = NULL;
     406             : 
     407             :         /* create the authorisation related tables */
     408         223 :         mvc_create_table(&t, m, s, REMOTE_USER_INFO, tt_table, 1, SQL_PERSIST, 0, -1, 0);
     409         223 :         mvc_create_column_(&col, m, t, "table_id", "int", 32);
     410         223 :         mvc_create_column_(&col, m, t, "username", "varchar", 1024);
     411         223 :         mvc_create_column_(&col, m, t, "password", "varchar", 256);
     412             : 
     413         223 :         mvc_create_table(&t, m, s, "db_user_info", tt_table, 1, SQL_PERSIST, 0, -1, 0);
     414         223 :         mvc_create_column_(&col, m, t, "name", "varchar", 1024);
     415         223 :         mvc_create_column_(&col, m, t, "fullname", "varchar", 2048);
     416         223 :         mvc_create_column_(&col, m, t, "default_schema", "int", 9);
     417         223 :         mvc_create_column_(&col, m, t, "schema_path", "clob", 0);
     418         223 :         mvc_create_column_(&col, m, t, "max_memory", "bigint", 64);
     419         223 :         mvc_create_column_(&col, m, t, "max_workers", "int", 32);
     420         223 :         mvc_create_column_(&col, m, t, "optimizer", "varchar", 1024);
     421         223 :         mvc_create_column_(&col, m, t, "default_role", "int", 32);
     422         223 :         mvc_create_column_(&col, m, t, "password", "varchar", 256);
     423         223 :         uinfo = t;
     424             : 
     425         223 :         sys = find_sql_schema(m->session->tr, "sys");
     426         223 :         schema_id = sys->base.id;
     427         223 :         assert(schema_id == 2000);
     428             : 
     429         223 :         sqlstore *store = m->session->tr->store;
     430         223 :         char *username = "monetdb";
     431         223 :         char *password = initpasswd ? mcrypt_BackendSum(initpasswd, strlen(initpasswd)) : mcrypt_BackendSum("monetdb", strlen("monetdb"));
     432         223 :         char *hash = NULL;
     433         223 :         if (password == NULL ||
     434         223 :                 (err = AUTHGeneratePasswordHash(&hash, password)) != MAL_SUCCEED) {
     435           0 :                 TRC_CRITICAL(SQL_TRANS, "generate password hash failure");
     436           0 :                 freeException(err);
     437           0 :                 free(password);
     438           0 :                 return ;
     439             :         }
     440         223 :         free(password);
     441             : 
     442         223 :         char *fullname = "MonetDB Admin";
     443         223 :         char *schema_path = default_schema_path;
     444             :         // default values
     445         223 :         char *optimizer = default_optimizer;
     446         223 :         lng max_memory = 0;
     447         223 :         int max_workers = 0;
     448         223 :         sqlid default_role_id = USER_MONETDB;
     449             : 
     450         223 :         store->table_api.table_insert(m->session->tr, uinfo, &username, &fullname, &schema_id, &schema_path, &max_memory,
     451             :                 &max_workers, &optimizer, &default_role_id, &hash);
     452         223 :         GDKfree(hash);
     453             : }
     454             : 
     455             : static int
     456         164 : monet5_schema_has_user(ptr _mvc, sql_schema *s)
     457             : {
     458         164 :         mvc *m = (mvc *) _mvc;
     459         164 :         oid rid;
     460         164 :         sql_schema *sys = find_sql_schema(m->session->tr, "sys");
     461         164 :         sql_table *users = find_sql_table(m->session->tr, sys, "db_user_info");
     462         164 :         sql_column *users_schema = find_sql_column(users, "default_schema");
     463         164 :         sqlid schema_id = s->base.id;
     464             : 
     465         164 :         sqlstore *store = m->session->tr->store;
     466         164 :         rid = store->table_api.column_find_row(m->session->tr, users_schema, &schema_id, NULL);
     467         164 :         if (is_oid_nil(rid))
     468         156 :                 return FALSE;
     469             :         return TRUE;
     470             : }
     471             : 
     472             : static int
     473          74 : monet5_alter_user(ptr _mvc, str user, str passwd, bool enc, sqlid schema_id, str schema_path, str oldpasswd, sqlid
     474             :                 role_id, lng max_memory, int max_workers)
     475             : {
     476          74 :         mvc *m = (mvc *) _mvc;
     477          74 :         Client c = MCgetClient(m->clientid);
     478          74 :         str err;
     479          74 :         int res = LOG_OK;
     480          74 :         oid rid = oid_nil;
     481             : 
     482          74 :         sqlstore *store = m->session->tr->store;
     483          74 :         sql_schema *sys = find_sql_schema(m->session->tr, "sys");
     484          74 :         sql_table *info = find_sql_table(m->session->tr, sys, "db_user_info");
     485          74 :         sql_column *users_name = find_sql_column(info, "name");
     486             : 
     487          74 :         if (schema_id || schema_path || role_id || max_memory > -1 || max_workers > -1) {
     488          70 :                 rid = store->table_api.column_find_row(m->session->tr, users_name, user, NULL);
     489             :                 // user should be checked here since the way `ALTER USER ident ...` stmt is
     490          70 :                 if (is_oid_nil(rid)) {
     491           0 :                         (void) sql_error(m, 02, "ALTER USER: local inconsistency, "
     492             :                                  "your database is damaged, auth not found in SQL catalog");
     493           0 :                         return FALSE;
     494             :                 }
     495             :         }
     496             : 
     497             : 
     498          74 :         if (passwd != NULL) {
     499           4 :                 str pwd = NULL;
     500           4 :                 str opwd = NULL;
     501           4 :                 if (!enc) {
     502           4 :                         pwd = mcrypt_BackendSum(passwd, strlen(passwd));
     503           4 :                         if (pwd == NULL) {
     504           0 :                                 (void) sql_error(m, 02, SQLSTATE(42000) "ALTER USER: crypt backend hash not found");
     505           0 :                                 return FALSE;
     506             :                         }
     507           4 :                         if (oldpasswd != NULL) {
     508           2 :                                 opwd = mcrypt_BackendSum(oldpasswd, strlen(oldpasswd));
     509           2 :                                 if (opwd == NULL) {
     510           0 :                                         free(pwd);
     511           0 :                                         (void) sql_error(m, 02, SQLSTATE(42000) "ALTER USER: crypt backend hash not found");
     512           0 :                                         return FALSE;
     513             :                                 }
     514             :                         }
     515             :                 } else {
     516             :                         pwd = passwd;
     517             :                         opwd = oldpasswd;
     518             :                 }
     519             : 
     520           4 :                 if (user) {
     521             :                         // verify query user value is not the session user
     522           2 :                         str username = NULL;
     523           2 :                         if ((username = getUserName(m, c->user)) == NULL) {
     524           0 :                                 if (!enc) {
     525           0 :                                         free(pwd);
     526           0 :                                         free(opwd);
     527             :                                 }
     528           0 :                                 (void) sql_error(m, 02, "ALTER USER: invalid user");
     529           0 :                                 return (FALSE);
     530             :                         }
     531           2 :                         if (strcmp(username, user) == 0) {
     532           0 :                                 GDKfree(username);
     533           0 :                                 if (!enc) {
     534           0 :                                         free(pwd);
     535           0 :                                         free(opwd);
     536             :                                 }
     537           0 :                                 (void) sql_error(m, 02, "ALTER USER: "
     538             :                                         "use 'ALTER USER SET [ ENCRYPTED ] PASSWORD xxx "
     539             :                                         "USING OLD PASSWORD yyy' "
     540             :                                         "when changing your own password");
     541           0 :                                 return (FALSE);
     542             :                         }
     543           2 :                         GDKfree(username);
     544             :                         // verify current user is MAL_ADMIN ?
     545           2 :                         if ((err = AUTHrequireAdmin(c)) != MAL_SUCCEED) {
     546           0 :                                 (void) sql_error(m, 02, "ALTER USER: %s", getExceptionMessage(err));
     547           0 :                                 freeException(err);
     548           0 :                                 if (!enc) {
     549           0 :                                         free(pwd);
     550           0 :                                         free(opwd);
     551             :                                 }
     552           0 :                                 return (FALSE);
     553             :                         }
     554           2 :                         if (setUserPassword(m, getUserOIDByName(m, user), pwd) != LOG_OK) {
     555           0 :                                 if (!enc) {
     556           0 :                                         free(pwd);
     557           0 :                                         free(opwd);
     558             :                                 }
     559           0 :                                 return (FALSE);
     560             :                         }
     561             : 
     562             :                 } else {
     563           2 :                         if (changeUserPassword(m, c->user, opwd, pwd) != LOG_OK) {
     564           1 :                                 if (!enc) {
     565           1 :                                         free(pwd);
     566           1 :                                         free(opwd);
     567             :                                 }
     568           1 :                                 return (FALSE);
     569             :                         }
     570             :                 }
     571           3 :                 if (!enc) {
     572           3 :                         free(pwd);
     573           3 :                         free(opwd);
     574             :                 }
     575             :         }
     576             : 
     577          73 :         if (schema_id) {
     578          57 :                 sql_column *users_schema = find_sql_column(info, "default_schema");
     579             : 
     580          57 :                 if ((res = store->table_api.column_update_value(m->session->tr, users_schema, rid, &schema_id))) {
     581           0 :                         (void) sql_error(m, 02, SQLSTATE(42000) "ALTER USER: failed%s",
     582             :                                                         res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     583           0 :                         return (FALSE);
     584             :                 }
     585             :         }
     586             : 
     587          73 :         if (schema_path) {
     588           8 :                 sql_column *sp = find_sql_column(info, "schema_path");
     589             : 
     590           8 :                 if ((err = parse_schema_path_str(m, schema_path, false)) != MAL_SUCCEED) {
     591           4 :                         (void) sql_error(m, 02, "ALTER USER: %s", getExceptionMessage(err));
     592           4 :                         freeException(err);
     593           4 :                         return (FALSE);
     594             :                 }
     595             : 
     596           4 :                 if ((res = store->table_api.column_update_value(m->session->tr, sp, rid, schema_path))) {
     597           0 :                         (void) sql_error(m, 02, SQLSTATE(42000) "ALTER USER: failed%s",
     598             :                                                         res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     599           0 :                         return (FALSE);
     600             :                 }
     601             :         }
     602             : 
     603          69 :         if (role_id) {
     604           3 :                 sql_column *users_role = find_sql_column(info, "default_role");
     605             : 
     606           3 :                 if ((res = store->table_api.column_update_value(m->session->tr, users_role, rid, &role_id))) {
     607           0 :                         (void) sql_error(m, 02, SQLSTATE(42000) "ALTER USER: failed%s",
     608             :                                                         res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     609           0 :                         return (FALSE);
     610             :                 }
     611             :         }
     612             : 
     613          69 :         if (max_memory > -1) {
     614           2 :                 sql_column *users_max_memory = find_sql_column(info, "max_memory");
     615             : 
     616           2 :                 if ((res = store->table_api.column_update_value(m->session->tr, users_max_memory, rid, &max_memory))) {
     617           0 :                         (void) sql_error(m, 02, SQLSTATE(42000) "ALTER USER: failed%s",
     618             :                                                         res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     619           0 :                         return (FALSE);
     620             :                 }
     621             :         }
     622             : 
     623          69 :         if (max_workers > -1) {
     624           2 :                 sql_column *users_max_workers = find_sql_column(info, "max_workers");
     625             : 
     626           2 :                 if ((res = store->table_api.column_update_value(m->session->tr, users_max_workers, rid, &max_workers))) {
     627           0 :                         (void) sql_error(m, 02, SQLSTATE(42000) "ALTER USER: failed%s",
     628             :                                                         res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     629           0 :                         return (FALSE);
     630             :                 }
     631             :         }
     632             : 
     633             :         return TRUE;
     634             : }
     635             : 
     636             : static int
     637           2 : monet5_rename_user(ptr _mvc, str olduser, str newuser)
     638             : {
     639           2 :         mvc *m = (mvc *) _mvc;
     640           2 :         oid rid;
     641           2 :         sql_schema *sys = find_sql_schema(m->session->tr, "sys");
     642           2 :         sql_table *info = find_sql_table(m->session->tr, sys, "db_user_info");
     643           2 :         sql_column *users_name = find_sql_column(info, "name");
     644           2 :         sql_table *auths = find_sql_table(m->session->tr, sys, "auths");
     645           2 :         sql_column *auths_name = find_sql_column(auths, "name");
     646           2 :         int res = LOG_OK;
     647             : 
     648           2 :         sqlstore *store = m->session->tr->store;
     649           2 :         rid = store->table_api.column_find_row(m->session->tr, users_name, olduser, NULL);
     650           2 :         if (is_oid_nil(rid)) {
     651           0 :                 (void) sql_error(m, 02, "ALTER USER: local inconsistency, "
     652             :                                  "your database is damaged, user not found in SQL catalog");
     653           0 :                 return (FALSE);
     654             :         }
     655           2 :         if ((res = store->table_api.column_update_value(m->session->tr, users_name, rid, newuser))) {
     656           0 :                 (void) sql_error(m, 02, SQLSTATE(42000) "ALTER USER: failed%s",
     657             :                                                  res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     658           0 :                 return (FALSE);
     659             :         }
     660             : 
     661           2 :         rid = store->table_api.column_find_row(m->session->tr, auths_name, olduser, NULL);
     662           2 :         if (is_oid_nil(rid)) {
     663           0 :                 (void) sql_error(m, 02, "ALTER USER: local inconsistency, "
     664             :                                  "your database is damaged, auth not found in SQL catalog");
     665           0 :                 return (FALSE);
     666             :         }
     667           2 :         if ((res = store->table_api.column_update_value(m->session->tr, auths_name, rid, newuser))) {
     668           0 :                 (void) sql_error(m, 02, SQLSTATE(42000) "ALTER USER: failed%s",
     669             :                                                  res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     670           0 :                 return (FALSE);
     671             :         }
     672             :         return (TRUE);
     673             : }
     674             : 
     675             : static void *
     676           0 : monet5_schema_user_dependencies(ptr _trans, int schema_id)
     677             : {
     678           0 :         rids *A, *U;
     679           0 :         sql_trans *tr = (sql_trans *) _trans;
     680           0 :         sql_schema *s = find_sql_schema(tr, "sys");
     681             : 
     682           0 :         sql_table *auths = find_sql_table(tr, s, "auths");
     683           0 :         sql_column *auth_name = find_sql_column(auths, "name");
     684             : 
     685           0 :         sql_table *users = find_sql_table(tr, s, "db_user_info");
     686           0 :         sql_column *users_name = find_sql_column(users, "name");
     687           0 :         sql_column *users_sch = find_sql_column(users, "default_schema");
     688             : 
     689           0 :         sqlstore *store = tr->store;
     690             :         /* select users with given schema */
     691           0 :         U = store->table_api.rids_select(tr, users_sch, &schema_id, &schema_id, NULL);
     692             :         /* select all authorization ids */
     693           0 :         A = store->table_api.rids_select(tr, auth_name, NULL, NULL);
     694             :         /* join all authorization with the selected users */
     695           0 :         if (A && U)
     696           0 :                 A = store->table_api.rids_join(tr, A, auth_name, U, users_name);
     697           0 :         store->table_api.rids_destroy(U);
     698           0 :         return A;
     699             : }
     700             : 
     701             : void
     702         336 : monet5_user_init(backend_functions *be_funcs)
     703             : {
     704         336 :         be_funcs->fcuser = &monet5_create_user;
     705         336 :         be_funcs->fduser = &monet5_drop_user;
     706         336 :         be_funcs->ffuser = &monet5_find_user;
     707         336 :         be_funcs->ffrole = &monet5_find_role;
     708         336 :         be_funcs->fcrpriv = &monet5_create_privileges;
     709         336 :         be_funcs->fshuser = &monet5_schema_has_user;
     710         336 :         be_funcs->fauser = &monet5_alter_user;
     711         336 :         be_funcs->fruser = &monet5_rename_user;
     712         336 :         be_funcs->fschuserdep = &monet5_schema_user_dependencies;
     713         336 : }
     714             : 
     715             : int
     716           0 : monet5_user_get_def_schema(mvc *m, int user, str *schema)
     717             : {
     718           0 :         oid rid;
     719           0 :         sqlid schema_id = int_nil;
     720           0 :         sql_schema *sys = NULL;
     721           0 :         sql_table *user_info = NULL;
     722           0 :         sql_table *schemas = NULL;
     723           0 :         sql_table *auths = NULL;
     724           0 :         str username = NULL, sname = NULL;
     725           0 :         sqlstore *store = m->session->tr->store;
     726             : 
     727           0 :         sys = find_sql_schema(m->session->tr, "sys");
     728           0 :         auths = find_sql_table(m->session->tr, sys, "auths");
     729           0 :         user_info = find_sql_table(m->session->tr, sys, "db_user_info");
     730           0 :         schemas = find_sql_table(m->session->tr, sys, "schemas");
     731             : 
     732           0 :         rid = store->table_api.column_find_row(m->session->tr, find_sql_column(auths, "id"), &user, NULL);
     733           0 :         if (is_oid_nil(rid))
     734             :                 return -2;
     735           0 :         if (!(username = store->table_api.column_find_value(m->session->tr, find_sql_column(auths, "name"), rid)))
     736             :                 return -1;
     737           0 :         rid = store->table_api.column_find_row(m->session->tr, find_sql_column(user_info, "name"), username, NULL);
     738           0 :         _DELETE(username);
     739             : 
     740           0 :         if (!is_oid_nil(rid))
     741           0 :                 schema_id = store->table_api.column_find_sqlid(m->session->tr, find_sql_column(user_info, "default_schema"), rid);
     742           0 :         if (is_int_nil(schema_id))
     743             :                 return -3;
     744           0 :         rid = store->table_api.column_find_row(m->session->tr, find_sql_column(schemas, "id"), &schema_id, NULL);
     745           0 :         if (is_oid_nil(rid))
     746             :                 return -3;
     747             : 
     748           0 :         if (!(sname = store->table_api.column_find_value(m->session->tr, find_sql_column(schemas, "name"), rid)))
     749             :                 return -1;
     750           0 :         *schema = sa_strdup(m->session->sa, sname);
     751           0 :         _DELETE(sname);
     752           0 :         return *schema ? 0 : -1;
     753             : }
     754             : 
     755             : int
     756       37880 : monet5_user_set_def_schema(mvc *m, oid user, str username)
     757             : {
     758       37880 :         oid rid;
     759       37880 :         sqlid schema_id, default_role_id;
     760       37880 :         sql_schema *sys = NULL;
     761       37880 :         sql_table *user_info = NULL;
     762       37880 :         sql_column *users_name = NULL;
     763       37880 :         sql_column *users_schema = NULL;
     764       37880 :         sql_column *users_schema_path = NULL;
     765       37880 :         sql_column *users_default_role = NULL;
     766       37880 :         sql_table *schemas = NULL;
     767       37880 :         sql_column *schemas_name = NULL;
     768       37880 :         sql_column *schemas_id = NULL;
     769       37880 :         sql_table *auths = NULL;
     770       37880 :         sql_column *auths_id = NULL;
     771       37880 :         sql_column *auths_name = NULL;
     772       37880 :         str path_err = NULL, other = NULL, schema = NULL, schema_cpy, schema_path = NULL, userrole = NULL;
     773       37880 :         int ok = 1, res = 0;
     774             : 
     775       37880 :         TRC_DEBUG(SQL_TRANS, OIDFMT "\n", user);
     776             : 
     777       37880 :         sys = find_sql_schema(m->session->tr, "sys");
     778       37880 :         user_info = find_sql_table(m->session->tr, sys, "db_user_info");
     779       37880 :         users_name = find_sql_column(user_info, "name");
     780       37880 :         users_schema = find_sql_column(user_info, "default_schema");
     781       37879 :         users_schema_path = find_sql_column(user_info, "schema_path");
     782       37878 :         users_default_role = find_sql_column(user_info, "default_role");
     783             : 
     784       37879 :         sqlstore *store = m->session->tr->store;
     785       37879 :         rid = store->table_api.column_find_row(m->session->tr, users_name, username, NULL);
     786       37880 :         if (is_oid_nil(rid)) {
     787           0 :                 if (m->session->tr->active && (other = mvc_rollback(m, 0, NULL, false)) != MAL_SUCCEED)
     788           0 :                         freeException(other);
     789           0 :                 return -2;
     790             :         }
     791       37880 :         schema_id = store->table_api.column_find_sqlid(m->session->tr, users_schema, rid);
     792       37880 :         if (!(schema_path = store->table_api.column_find_value(m->session->tr, users_schema_path, rid))) {
     793           0 :                 if (m->session->tr->active && (other = mvc_rollback(m, 0, NULL, false)) != MAL_SUCCEED)
     794           0 :                         freeException(other);
     795           0 :                 return -1;
     796             :         }
     797             : 
     798       37880 :         default_role_id = store->table_api.column_find_sqlid(m->session->tr, users_default_role, rid);
     799             : 
     800       37880 :         schemas = find_sql_table(m->session->tr, sys, "schemas");
     801       37878 :         schemas_name = find_sql_column(schemas, "name");
     802       37879 :         schemas_id = find_sql_column(schemas, "id");
     803       37879 :         auths = find_sql_table(m->session->tr, sys, "auths");
     804       37879 :         auths_id = find_sql_column(auths, "id");
     805       37880 :         auths_name = find_sql_column(auths, "name");
     806             : 
     807       37880 :         rid = store->table_api.column_find_row(m->session->tr, schemas_id, &schema_id, NULL);
     808       37880 :         if (is_oid_nil(rid)) {
     809           0 :                 if (m->session->tr->active && (other = mvc_rollback(m, 0, NULL, false)) != MAL_SUCCEED)
     810           0 :                         freeException(other);
     811           0 :                 _DELETE(schema_path);
     812           0 :                 return -3;
     813             :         }
     814       37880 :         if (!(schema = store->table_api.column_find_value(m->session->tr, schemas_name, rid))) {
     815           0 :                 if (m->session->tr->active && (other = mvc_rollback(m, 0, NULL, false)) != MAL_SUCCEED)
     816           0 :                         freeException(other);
     817           0 :                 _DELETE(schema_path);
     818           0 :                 return -1;
     819             :         }
     820       37880 :         schema_cpy = schema;
     821       37880 :         schema = sa_strdup(m->session->sa, schema);
     822       37880 :         _DELETE(schema_cpy);
     823             : 
     824             :         /* check if username exists */
     825       37880 :         rid = store->table_api.column_find_row(m->session->tr, auths_name, username, NULL);
     826       37880 :         if (is_oid_nil(rid)) {
     827           0 :                 if (m->session->tr->active && (other = mvc_rollback(m, 0, NULL, false)) != MAL_SUCCEED)
     828           0 :                         freeException(other);
     829           0 :                 _DELETE(schema_path);
     830           0 :                 return -2;
     831             :         }
     832             : 
     833       37880 :         m->user_id = store->table_api.column_find_sqlid(m->session->tr, auths_id, rid);
     834             : 
     835             :         /* check if role exists */
     836       37880 :         rid = store->table_api.column_find_row(m->session->tr, auths_id, &default_role_id, NULL);
     837       37880 :         if (is_oid_nil(rid)) {
     838           0 :                 if (m->session->tr->active && (other = mvc_rollback(m, 0, NULL, false)) != MAL_SUCCEED)
     839           0 :                         freeException(other);
     840           0 :                 _DELETE(schema_path);
     841           0 :                 return -4;
     842             :         }
     843       37880 :         m->role_id = default_role_id;
     844       37880 :         if (!(userrole = store->table_api.column_find_value(m->session->tr, auths_name, rid))) {
     845           0 :                 if (m->session->tr->active && (other = mvc_rollback(m, 0, NULL, false)) != MAL_SUCCEED)
     846           0 :                         freeException(other);
     847           0 :                 _DELETE(schema_path);
     848           0 :                 return -1;
     849             :         }
     850             : 
     851             :         /* while getting the session's schema, set the search path as well */
     852       37880 :         if (!(ok = mvc_set_schema(m, schema)) || (path_err = parse_schema_path_str(m, schema_path, true)) != MAL_SUCCEED) {
     853           0 :                 if (m->session->tr->active && (other = mvc_rollback(m, 0, NULL, false)) != MAL_SUCCEED)
     854           0 :                         freeException(other);
     855           0 :                 _DELETE(schema_path);
     856           0 :                 _DELETE(userrole);
     857           0 :                 freeException(path_err);
     858           0 :                 return ok == 0 ? -3 : -1;
     859             :         }
     860             : 
     861             : 
     862             :         /* reset the user and schema names */
     863       75760 :         if (!sqlvar_set_string(find_global_var(m, sys, "current_schema"), schema) ||
     864       75760 :                 !sqlvar_set_string(find_global_var(m, sys, "current_user"), username) ||
     865       37880 :                 !sqlvar_set_string(find_global_var(m, sys, "current_role"), userrole)) {
     866             :                 res = -1;
     867             :         }
     868       37880 :         _DELETE(schema_path);
     869       37880 :         _DELETE(userrole);
     870       37880 :         return res;
     871             : }
     872             : 
     873             : int
     874       37880 : monet5_user_get_limits(mvc *m, int user, lng *maxmem, int *maxwrk)
     875             : {
     876       37880 :         oid rid;
     877       37880 :         sql_schema *sys = NULL;
     878       37880 :         sql_table *user_info = NULL;
     879       37880 :         sql_table *auths = NULL;
     880       37880 :         str username = NULL;
     881       37880 :         sqlstore *store = m->session->tr->store;
     882       37880 :         lng max_memory = 0;
     883       37880 :         int max_workers = 0;
     884             : 
     885       37880 :         assert(m->session->tr->active);
     886             : 
     887       37880 :         sys = find_sql_schema(m->session->tr, "sys");
     888       37880 :         auths = find_sql_table(m->session->tr, sys, "auths");
     889       37880 :         user_info = find_sql_table(m->session->tr, sys, "db_user_info");
     890             : 
     891       37880 :         rid = store->table_api.column_find_row(m->session->tr, find_sql_column(auths, "id"), &user, NULL);
     892       37880 :         if (is_oid_nil(rid))
     893             :                 return -2;
     894       37880 :         if (!(username = store->table_api.column_find_value(m->session->tr, find_sql_column(auths, "name"), rid)))
     895             :                 return -1;
     896       37880 :         rid = store->table_api.column_find_row(m->session->tr, find_sql_column(user_info, "name"), username, NULL);
     897       37880 :         _DELETE(username);
     898             : 
     899       37880 :         if (!is_oid_nil(rid)) {
     900       37880 :                 max_memory = store->table_api.column_find_lng(m->session->tr, find_sql_column(user_info, "max_memory"), rid);
     901       37880 :                 max_workers = store->table_api.column_find_int(m->session->tr, find_sql_column(user_info, "max_workers"), rid);
     902             :         }
     903             : 
     904       37880 :         *maxmem = max_memory > 0 ? max_memory : 0;
     905       37880 :         *maxwrk = max_workers > 0 ? max_workers : 0;
     906       37880 :         return 0;
     907             : }
     908             : 
     909             : /* move into mvc_remote_create */
     910             : /* and mvc_remote_drop */
     911             : str
     912          94 : remote_create(mvc *m, sqlid id, const str username, const str password, int pw_encrypted)
     913             : {
     914          94 :         int log_res = 0;
     915          94 :         sql_trans *tr = m->session->tr;
     916          94 :         sqlstore *store = tr->store;
     917          94 :         sql_schema *sys = find_sql_schema(tr, "sys");
     918          94 :         sql_table *remote_user_info = find_sql_table(tr, sys, REMOTE_USER_INFO);
     919             : 
     920          94 :         char *pwhash = password, *cypher = NULL;
     921          94 :         if (!pw_encrypted) {
     922          10 :                 if((pwhash = mcrypt_BackendSum(password, strlen(password))) == NULL)
     923           0 :                         throw(MAL, "addRemoteTableCredentials", SQLSTATE(42000) "Crypt backend hash not found");
     924             :         }
     925          94 :         if (strNil(password)) {
     926          80 :                 oid rid = getUserOIDByName(m, username);
     927          80 :                 str cypher = getUserPassword(m, rid);
     928          80 :                 str err = AUTHdecypherValue(&pwhash, cypher);
     929          80 :                 GDKfree(cypher);
     930          80 :                 if (err) {
     931           0 :                         GDKfree(err);
     932           0 :                         throw(MAL, "addRemoteTableCredentials", SQLSTATE(42000) "Crypt backend hash not found");
     933             :                 }
     934             :         }
     935          94 :         str msg = AUTHcypherValue(&cypher, pwhash);
     936          94 :         if (pwhash != password) {
     937          90 :                 if (!pw_encrypted)
     938          10 :                         free(pwhash);
     939             :                 else
     940          80 :                         GDKfree(pwhash);
     941             :         }
     942          94 :         if (msg != MAL_SUCCEED)
     943             :                 return msg;
     944          94 :         log_res = store->table_api.table_insert(m->session->tr, remote_user_info, &id, &username, &cypher, NULL);
     945          94 :         GDKfree(cypher);
     946          94 :         if (log_res != 0)
     947           0 :                 throw(SQL, "sql.create_table", SQLSTATE(42000) "Create table failed%s", log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
     948             :         return MAL_SUCCEED;
     949             : }
     950             : 
     951             : str
     952         185 : remote_get(mvc *m, sqlid id, str *username, str *pwhash)
     953             : {
     954         185 :         sql_trans *tr = m->session->tr;
     955         185 :         sqlstore *store = tr->store;
     956         185 :         sql_schema *sys = find_sql_schema(tr, "sys");
     957         185 :         sql_table *remote_user_info = find_sql_table(tr, sys, REMOTE_USER_INFO);
     958         185 :         sql_column *remote_user_info_id = find_sql_column(remote_user_info, "table_id");
     959         185 :         oid rid = store->table_api.column_find_row(tr, remote_user_info_id, &id, NULL);
     960             : 
     961         185 :         if (is_oid_nil(rid))
     962           0 :                 throw(MAL, "remote", SQLSTATE(42000) "remote table credentials not found");
     963         185 :         *username = store->table_api.column_find_value(tr, find_sql_column(remote_user_info, "username"), rid);
     964         185 :         if (strNil(*username)) {
     965           0 :                 GDKfree(*username);
     966           0 :                 *username = GDKstrdup("");
     967             :         }
     968         185 :         str cypher = store->table_api.column_find_value(tr, find_sql_column(remote_user_info, "password"), rid);
     969         185 :         str err = AUTHdecypherValue(pwhash, cypher);
     970         185 :         GDKfree(cypher);
     971         185 :         if (err)
     972             :                 return err;
     973             :         return MAL_SUCCEED;
     974             : }

Generated by: LCOV version 1.14