| 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 - 2019 MonetDB B.V. |
| 7 | */ |
| 8 | |
| 9 | /* |
| 10 | * @f sql_user |
| 11 | * @t SQL catalog management |
| 12 | * @a N. Nes, F. Groffen |
| 13 | * @+ SQL user |
| 14 | * The SQL user and authorisation implementation differs per backend. This |
| 15 | * file implements the authorisation and user management based on the M5 |
| 16 | * system authorisation. |
| 17 | */ |
| 18 | #include "monetdb_config.h" |
| 19 | #include "sql_user.h" |
| 20 | #include "sql_mvc.h" |
| 21 | #include "sql_privileges.h" |
| 22 | #include "bat5.h" |
| 23 | #include "mal_interpreter.h" |
| 24 | #include "mal_authorize.h" |
| 25 | #include "mcrypt.h" |
| 26 | |
| 27 | #if 0 |
| 28 | int |
| 29 | sql_find_auth_schema(mvc *m, str auth) |
| 30 | { |
| 31 | int res = -1; |
| 32 | oid rid; |
| 33 | sql_schema *sys = find_sql_schema(m->session->tr, "sys" ); |
| 34 | sql_table *users = find_sql_table(sys, "db_user_info" ); |
| 35 | sql_column *users_name = find_sql_column(users, "name" ); |
| 36 | |
| 37 | rid = table_funcs.column_find_row(m->session->tr, users_name, auth, NULL); |
| 38 | |
| 39 | if (!is_oid_nil(rid)) { |
| 40 | sql_column *users_schema = find_sql_column(users, "default_schema" ); |
| 41 | int *p = (int *) table_funcs.column_find_value(m->session->tr, users_schema, rid); |
| 42 | |
| 43 | if (p) { |
| 44 | res = *p; |
| 45 | _DELETE(p); |
| 46 | } |
| 47 | } |
| 48 | return res; |
| 49 | } |
| 50 | #endif |
| 51 | |
| 52 | static int |
| 53 | monet5_drop_user(ptr _mvc, str user) |
| 54 | { |
| 55 | mvc *m = (mvc *) _mvc; |
| 56 | oid rid; |
| 57 | sql_schema *sys; |
| 58 | sql_table *users; |
| 59 | sql_column *users_name; |
| 60 | str err; |
| 61 | Client c = MCgetClient(m->clientid); |
| 62 | |
| 63 | err = AUTHremoveUser(c, user); |
| 64 | if (err !=MAL_SUCCEED) { |
| 65 | (void) sql_error(m, 02, "DROP USER: %s" , getExceptionMessage(err)); |
| 66 | _DELETE(err); |
| 67 | return FALSE; |
| 68 | } |
| 69 | sys = find_sql_schema(m->session->tr, "sys" ); |
| 70 | users = find_sql_table(sys, "db_user_info" ); |
| 71 | users_name = find_sql_column(users, "name" ); |
| 72 | |
| 73 | rid = table_funcs.column_find_row(m->session->tr, users_name, user, NULL); |
| 74 | if (!is_oid_nil(rid)) |
| 75 | table_funcs.table_delete(m->session->tr, users, rid); |
| 76 | /* FIXME: We have to ignore this inconsistency here, because the |
| 77 | * user was already removed from the system authorisation. Once |
| 78 | * we have warnings, we could issue a warning about this |
| 79 | * (seemingly) inconsistency between system and sql shadow |
| 80 | * administration. */ |
| 81 | |
| 82 | return TRUE; |
| 83 | } |
| 84 | |
| 85 | static str |
| 86 | monet5_create_user(ptr _mvc, str user, str passwd, char enc, str fullname, sqlid schema_id, sqlid grantorid) |
| 87 | { |
| 88 | mvc *m = (mvc *) _mvc; |
| 89 | oid uid = 0; |
| 90 | bat bid = 0; |
| 91 | str ret; |
| 92 | sqlid user_id; |
| 93 | str pwd; |
| 94 | sql_schema *s = find_sql_schema(m->session->tr, "sys" ); |
| 95 | sql_table *db_user_info, *auths; |
| 96 | Client c = MCgetClient(m->clientid); |
| 97 | |
| 98 | if (!enc) { |
| 99 | pwd = mcrypt_BackendSum(passwd, strlen(passwd)); |
| 100 | if (pwd == NULL) { |
| 101 | BBPunfix(bid); |
| 102 | throw(MAL, "sql.create_user" , SQLSTATE(42000) "Crypt backend hash not found" ); |
| 103 | } |
| 104 | } else { |
| 105 | pwd = passwd; |
| 106 | } |
| 107 | /* add the user to the M5 authorisation administration */ |
| 108 | ret = AUTHaddUser(&uid, c, user, pwd); |
| 109 | if (!enc) |
| 110 | free(pwd); |
| 111 | if (ret != MAL_SUCCEED) |
| 112 | return ret; |
| 113 | |
| 114 | user_id = store_next_oid(); |
| 115 | db_user_info = find_sql_table(s, "db_user_info" ); |
| 116 | auths = find_sql_table(s, "auths" ); |
| 117 | table_funcs.table_insert(m->session->tr, db_user_info, user, fullname, &schema_id); |
| 118 | table_funcs.table_insert(m->session->tr, auths, &user_id, user, &grantorid); |
| 119 | return NULL; |
| 120 | } |
| 121 | |
| 122 | static int |
| 123 | monet5_find_user(ptr mp, str user) |
| 124 | { |
| 125 | BAT *uid, *nme; |
| 126 | BUN p; |
| 127 | mvc *m = (mvc *) mp; |
| 128 | Client c = MCgetClient(m->clientid); |
| 129 | str err; |
| 130 | |
| 131 | if ((err = AUTHgetUsers(&uid, &nme, c)) != MAL_SUCCEED) { |
| 132 | _DELETE(err); |
| 133 | return -1; |
| 134 | } |
| 135 | p = BUNfnd(nme, user); |
| 136 | BBPunfix(uid->batCacheid); |
| 137 | BBPunfix(nme->batCacheid); |
| 138 | |
| 139 | /* yeah, I would prefer to return something different too */ |
| 140 | return (p == BUN_NONE ? -1 : 1); |
| 141 | } |
| 142 | |
| 143 | str |
| 144 | db_users_wrap(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) |
| 145 | { |
| 146 | bat *r = getArgReference_bat(stk, pci, 0); |
| 147 | BAT *uid, *nme; |
| 148 | str err; |
| 149 | |
| 150 | (void) mb; |
| 151 | if ((err = AUTHgetUsers(&uid, &nme, cntxt)) != MAL_SUCCEED) |
| 152 | return err; |
| 153 | BBPunfix(uid->batCacheid); |
| 154 | *r = nme->batCacheid; |
| 155 | BBPkeepref(*r); |
| 156 | return MAL_SUCCEED; |
| 157 | } |
| 158 | |
| 159 | str |
| 160 | db_password_wrap(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) |
| 161 | { |
| 162 | (void) mb; |
| 163 | |
| 164 | if (stk->stk[pci->argv[0]].vtype == TYPE_bat) { |
| 165 | BAT *b = BATdescriptor(*getArgReference_bat(stk, pci, 1)); |
| 166 | if (b == NULL) |
| 167 | throw(SQL, "sql.password" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
| 168 | BAT *bn = COLnew(b->hseqbase, TYPE_str, BATcount(b), TRANSIENT); |
| 169 | if (bn == NULL) { |
| 170 | BBPunfix(b->batCacheid); |
| 171 | throw(SQL, "sql.password" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
| 172 | } |
| 173 | BATiter bi = bat_iterator(b); |
| 174 | BUN p, q; |
| 175 | BATloop(b, p, q) { |
| 176 | char *hash, *msg; |
| 177 | msg = AUTHgetPasswordHash(&hash, cntxt, BUNtvar(bi, p)); |
| 178 | if (msg != MAL_SUCCEED) { |
| 179 | BBPunfix(b->batCacheid); |
| 180 | BBPreclaim(bn); |
| 181 | return msg; |
| 182 | } |
| 183 | if (BUNappend(bn, hash, false) != GDK_SUCCEED) { |
| 184 | BBPunfix(b->batCacheid); |
| 185 | BBPreclaim(bn); |
| 186 | throw(SQL, "sql.password" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
| 187 | } |
| 188 | GDKfree(hash); |
| 189 | } |
| 190 | BBPunfix(b->batCacheid); |
| 191 | BBPkeepref(bn->batCacheid); |
| 192 | *getArgReference_bat(stk, pci, 0) = bn->batCacheid; |
| 193 | return MAL_SUCCEED; |
| 194 | } |
| 195 | str *hash = getArgReference_str(stk, pci, 0); |
| 196 | str *user = getArgReference_str(stk, pci, 1); |
| 197 | |
| 198 | return AUTHgetPasswordHash(hash, cntxt, *user); |
| 199 | } |
| 200 | |
| 201 | static void |
| 202 | monet5_create_privileges(ptr _mvc, sql_schema *s) |
| 203 | { |
| 204 | sql_table *t, *uinfo; |
| 205 | mvc *m = (mvc *) _mvc; |
| 206 | char *err = NULL; |
| 207 | sqlid schema_id = 0; |
| 208 | str monetdbuser = "monetdb" ; |
| 209 | list *res, *ops; |
| 210 | |
| 211 | /* create the authorisation related tables */ |
| 212 | t = mvc_create_table(m, s, "db_user_info" , tt_table, 1, SQL_PERSIST, 0, -1, 0); |
| 213 | mvc_create_column_(m, t, "name" , "varchar" , 1024); |
| 214 | mvc_create_column_(m, t, "fullname" , "varchar" , 2048); |
| 215 | mvc_create_column_(m, t, "default_schema" , "int" , 9); |
| 216 | uinfo = t; |
| 217 | |
| 218 | (void) err; |
| 219 | res = sa_list(m->sa); |
| 220 | list_append(res, sql_create_arg(m->sa, "name" , sql_bind_subtype(m->sa, "varchar" , 2048, 0), ARG_OUT)); |
| 221 | |
| 222 | /* add function */ |
| 223 | ops = sa_list(m->sa); |
| 224 | /* following funcion returns a table (single column) of user names |
| 225 | with the approriate scenario (sql) */ |
| 226 | mvc_create_func(m, NULL, s, "db_users" , ops, res, F_UNION, FUNC_LANG_SQL, "sql" , "db_users" , "CREATE FUNCTION db_users () RETURNS TABLE( name varchar(2048)) EXTERNAL NAME sql.db_users;" , FALSE, FALSE, TRUE); |
| 227 | |
| 228 | t = mvc_init_create_view(m, s, "users" , |
| 229 | "SELECT u.\"name\" AS \"name\", " |
| 230 | "ui.\"fullname\", ui.\"default_schema\" " |
| 231 | "FROM db_users() AS u LEFT JOIN " |
| 232 | "\"sys\".\"db_user_info\" AS ui " |
| 233 | "ON u.\"name\" = ui.\"name\";" ); |
| 234 | if (!t) { |
| 235 | fprintf(stderr, "!monet5_create_privileges: failed to create 'users' view\n" ); |
| 236 | return ; |
| 237 | } |
| 238 | |
| 239 | mvc_create_column_(m, t, "name" , "varchar" , 1024); |
| 240 | mvc_create_column_(m, t, "fullname" , "varchar" , 2024); |
| 241 | mvc_create_column_(m, t, "default_schema" , "int" , 9); |
| 242 | |
| 243 | schema_id = sql_find_schema(m, "sys" ); |
| 244 | assert(schema_id >= 0); |
| 245 | |
| 246 | table_funcs.table_insert(m->session->tr, uinfo, monetdbuser, "MonetDB Admin" , &schema_id); |
| 247 | } |
| 248 | |
| 249 | static int |
| 250 | monet5_schema_has_user(ptr _mvc, sql_schema *s) |
| 251 | { |
| 252 | mvc *m = (mvc *) _mvc; |
| 253 | oid rid; |
| 254 | sql_schema *sys = find_sql_schema(m->session->tr, "sys" ); |
| 255 | sql_table *users = find_sql_table(sys, "db_user_info" ); |
| 256 | sql_column *users_schema = find_sql_column(users, "default_schema" ); |
| 257 | sqlid schema_id = s->base.id; |
| 258 | |
| 259 | rid = table_funcs.column_find_row(m->session->tr, users_schema, &schema_id, NULL); |
| 260 | if (is_oid_nil(rid)) |
| 261 | return FALSE; |
| 262 | return TRUE; |
| 263 | } |
| 264 | |
| 265 | static int |
| 266 | monet5_alter_user(ptr _mvc, str user, str passwd, char enc, sqlid schema_id, str oldpasswd) |
| 267 | { |
| 268 | mvc *m = (mvc *) _mvc; |
| 269 | Client c = MCgetClient(m->clientid); |
| 270 | str err; |
| 271 | |
| 272 | if (passwd != NULL) { |
| 273 | str pwd = NULL; |
| 274 | str opwd = NULL; |
| 275 | if (!enc) { |
| 276 | pwd = mcrypt_BackendSum(passwd, strlen(passwd)); |
| 277 | if (pwd == NULL) { |
| 278 | (void) sql_error(m, 02, SQLSTATE(42000) "ALTER USER: crypt backend hash not found" ); |
| 279 | return FALSE; |
| 280 | } |
| 281 | if (oldpasswd != NULL) { |
| 282 | opwd = mcrypt_BackendSum(oldpasswd, strlen(oldpasswd)); |
| 283 | if (opwd == NULL) { |
| 284 | free(pwd); |
| 285 | (void) sql_error(m, 02, SQLSTATE(42000) "ALTER USER: crypt backend hash not found" ); |
| 286 | return FALSE; |
| 287 | } |
| 288 | } |
| 289 | } else { |
| 290 | pwd = passwd; |
| 291 | opwd = oldpasswd; |
| 292 | } |
| 293 | if (user == NULL) { |
| 294 | err = AUTHchangePassword(c, opwd, pwd); |
| 295 | if (!enc) { |
| 296 | free(pwd); |
| 297 | free(opwd); |
| 298 | } |
| 299 | if (err !=MAL_SUCCEED) { |
| 300 | (void) sql_error(m, 02, "ALTER USER: %s" , getExceptionMessage(err)); |
| 301 | freeException(err); |
| 302 | return (FALSE); |
| 303 | } |
| 304 | } else { |
| 305 | str username = NULL; |
| 306 | if ((err = AUTHresolveUser(&username, c->user)) !=MAL_SUCCEED) { |
| 307 | if (!enc) { |
| 308 | free(pwd); |
| 309 | free(opwd); |
| 310 | } |
| 311 | (void) sql_error(m, 02, "ALTER USER: %s" , getExceptionMessage(err)); |
| 312 | freeException(err); |
| 313 | return (FALSE); |
| 314 | } |
| 315 | if (strcmp(username, user) == 0) { |
| 316 | /* avoid message about changePassword (from MAL level) */ |
| 317 | GDKfree(username); |
| 318 | if (!enc) { |
| 319 | free(pwd); |
| 320 | free(opwd); |
| 321 | } |
| 322 | (void) sql_error(m, 02, "ALTER USER: " |
| 323 | "use 'ALTER USER SET [ ENCRYPTED ] PASSWORD xxx " |
| 324 | "USING OLD PASSWORD yyy' " |
| 325 | "when changing your own password" ); |
| 326 | return (FALSE); |
| 327 | } |
| 328 | GDKfree(username); |
| 329 | err = AUTHsetPassword(c, user, pwd); |
| 330 | if (!enc) { |
| 331 | free(pwd); |
| 332 | free(opwd); |
| 333 | } |
| 334 | if (err !=MAL_SUCCEED) { |
| 335 | (void) sql_error(m, 02, "ALTER USER: %s" , getExceptionMessage(err)); |
| 336 | freeException(err); |
| 337 | return (FALSE); |
| 338 | } |
| 339 | } |
| 340 | } |
| 341 | |
| 342 | if (schema_id) { |
| 343 | oid rid; |
| 344 | sql_schema *sys = find_sql_schema(m->session->tr, "sys" ); |
| 345 | sql_table *info = find_sql_table(sys, "db_user_info" ); |
| 346 | sql_column *users_name = find_sql_column(info, "name" ); |
| 347 | sql_column *users_schema = find_sql_column(info, "default_schema" ); |
| 348 | |
| 349 | /* FIXME: we don't really check against the backend here */ |
| 350 | rid = table_funcs.column_find_row(m->session->tr, users_name, user, NULL); |
| 351 | if (is_oid_nil(rid)) |
| 352 | return FALSE; |
| 353 | |
| 354 | table_funcs.column_update_value(m->session->tr, users_schema, rid, &schema_id); |
| 355 | } |
| 356 | |
| 357 | return TRUE; |
| 358 | } |
| 359 | |
| 360 | static int |
| 361 | monet5_rename_user(ptr _mvc, str olduser, str newuser) |
| 362 | { |
| 363 | mvc *m = (mvc *) _mvc; |
| 364 | Client c = MCgetClient(m->clientid); |
| 365 | str err; |
| 366 | oid rid; |
| 367 | sql_schema *sys = find_sql_schema(m->session->tr, "sys" ); |
| 368 | sql_table *info = find_sql_table(sys, "db_user_info" ); |
| 369 | sql_column *users_name = find_sql_column(info, "name" ); |
| 370 | sql_table *auths = find_sql_table(sys, "auths" ); |
| 371 | sql_column *auths_name = find_sql_column(auths, "name" ); |
| 372 | |
| 373 | if ((err = AUTHchangeUsername(c, olduser, newuser)) !=MAL_SUCCEED) { |
| 374 | (void) sql_error(m, 02, "ALTER USER: %s" , getExceptionMessage(err)); |
| 375 | freeException(err); |
| 376 | return (FALSE); |
| 377 | } |
| 378 | |
| 379 | rid = table_funcs.column_find_row(m->session->tr, users_name, olduser, NULL); |
| 380 | if (is_oid_nil(rid)) { |
| 381 | (void) sql_error(m, 02, "ALTER USER: local inconsistency, " |
| 382 | "your database is damaged, user not found in SQL catalog" ); |
| 383 | return (FALSE); |
| 384 | } |
| 385 | table_funcs.column_update_value(m->session->tr, users_name, rid, newuser); |
| 386 | |
| 387 | rid = table_funcs.column_find_row(m->session->tr, auths_name, olduser, NULL); |
| 388 | if (is_oid_nil(rid)) { |
| 389 | (void) sql_error(m, 02, "ALTER USER: local inconsistency, " |
| 390 | "your database is damaged, auth not found in SQL catalog" ); |
| 391 | return (FALSE); |
| 392 | } |
| 393 | table_funcs.column_update_value(m->session->tr, auths_name, rid, newuser); |
| 394 | |
| 395 | return (TRUE); |
| 396 | } |
| 397 | |
| 398 | static void * |
| 399 | monet5_schema_user_dependencies(ptr _trans, int schema_id) |
| 400 | { |
| 401 | rids *A, *U; |
| 402 | sql_trans *tr = (sql_trans *) _trans; |
| 403 | sql_schema *s = find_sql_schema(tr, "sys" ); |
| 404 | |
| 405 | sql_table *auths = find_sql_table(s, "auths" ); |
| 406 | sql_column *auth_name = find_sql_column(auths, "name" ); |
| 407 | |
| 408 | sql_table *users = find_sql_table(s, "db_user_info" ); |
| 409 | sql_column *users_name = find_sql_column(users, "name" ); |
| 410 | sql_column *users_sch = find_sql_column(users, "default_schema" ); |
| 411 | |
| 412 | /* select users with given schema */ |
| 413 | U = table_funcs.rids_select(tr, users_sch, &schema_id, &schema_id, NULL); |
| 414 | /* select all authorization ids */ |
| 415 | A = table_funcs.rids_select(tr, auth_name, NULL, NULL); |
| 416 | /* join all authorization with the selected users */ |
| 417 | A = table_funcs.rids_join(tr, A, auth_name, U, users_name); |
| 418 | table_funcs.rids_destroy(U); |
| 419 | return A; |
| 420 | } |
| 421 | |
| 422 | void |
| 423 | monet5_user_init(backend_functions *be_funcs) |
| 424 | { |
| 425 | be_funcs->fcuser = &monet5_create_user; |
| 426 | be_funcs->fduser = &monet5_drop_user; |
| 427 | be_funcs->ffuser = &monet5_find_user; |
| 428 | be_funcs->fcrpriv = &monet5_create_privileges; |
| 429 | be_funcs->fshuser = &monet5_schema_has_user; |
| 430 | be_funcs->fauser = &monet5_alter_user; |
| 431 | be_funcs->fruser = &monet5_rename_user; |
| 432 | be_funcs->fschuserdep = &monet5_schema_user_dependencies; |
| 433 | } |
| 434 | |
| 435 | str |
| 436 | monet5_user_get_def_schema(mvc *m, int user) |
| 437 | { |
| 438 | oid rid; |
| 439 | sqlid schema_id; |
| 440 | sql_schema *sys = NULL; |
| 441 | sql_table *user_info = NULL; |
| 442 | sql_column *users_name = NULL; |
| 443 | sql_column *users_schema = NULL; |
| 444 | sql_table *schemas = NULL; |
| 445 | sql_column *schemas_name = NULL; |
| 446 | sql_column *schemas_id = NULL; |
| 447 | sql_table *auths = NULL; |
| 448 | sql_column *auths_id = NULL; |
| 449 | sql_column *auths_name = NULL; |
| 450 | void *p = 0; |
| 451 | str username = NULL; |
| 452 | str schema = NULL; |
| 453 | |
| 454 | sys = find_sql_schema(m->session->tr, "sys" ); |
| 455 | auths = find_sql_table(sys, "auths" ); |
| 456 | auths_id = find_sql_column(auths, "id" ); |
| 457 | auths_name = find_sql_column(auths, "name" ); |
| 458 | rid = table_funcs.column_find_row(m->session->tr, auths_id, &user, NULL); |
| 459 | if (!is_oid_nil(rid)) |
| 460 | username = table_funcs.column_find_value(m->session->tr, auths_name, rid); |
| 461 | |
| 462 | user_info = find_sql_table(sys, "db_user_info" ); |
| 463 | users_name = find_sql_column(user_info, "name" ); |
| 464 | users_schema = find_sql_column(user_info, "default_schema" ); |
| 465 | rid = table_funcs.column_find_row(m->session->tr, users_name, username, NULL); |
| 466 | if (!is_oid_nil(rid)) |
| 467 | p = table_funcs.column_find_value(m->session->tr, users_schema, rid); |
| 468 | |
| 469 | _DELETE(username); |
| 470 | assert(p); |
| 471 | schema_id = *(sqlid *) p; |
| 472 | _DELETE(p); |
| 473 | |
| 474 | schemas = find_sql_table(sys, "schemas" ); |
| 475 | schemas_name = find_sql_column(schemas, "name" ); |
| 476 | schemas_id = find_sql_column(schemas, "id" ); |
| 477 | |
| 478 | rid = table_funcs.column_find_row(m->session->tr, schemas_id, &schema_id, NULL); |
| 479 | if (!is_oid_nil(rid)) |
| 480 | schema = table_funcs.column_find_value(m->session->tr, schemas_name, rid); |
| 481 | if(!stack_set_string(m, "current_schema" , schema)) |
| 482 | return NULL; |
| 483 | return schema; |
| 484 | } |
| 485 | |
| 486 | str |
| 487 | monet5_user_set_def_schema(mvc *m, oid user) |
| 488 | { |
| 489 | oid rid; |
| 490 | sqlid schema_id; |
| 491 | sql_schema *sys = NULL; |
| 492 | sql_table *user_info = NULL; |
| 493 | sql_column *users_name = NULL; |
| 494 | sql_column *users_schema = NULL; |
| 495 | sql_table *schemas = NULL; |
| 496 | sql_column *schemas_name = NULL; |
| 497 | sql_column *schemas_id = NULL; |
| 498 | sql_table *auths = NULL; |
| 499 | sql_column *auths_name = NULL; |
| 500 | str other; |
| 501 | |
| 502 | void *p = 0; |
| 503 | |
| 504 | str schema = NULL; |
| 505 | str username = NULL; |
| 506 | str err = NULL; |
| 507 | |
| 508 | if (m->debug &1) |
| 509 | fprintf(stderr, "monet5_user_set_def_schema " OIDFMT "\n" , user); |
| 510 | |
| 511 | if ((err = AUTHresolveUser(&username, user)) !=MAL_SUCCEED) { |
| 512 | freeException(err); |
| 513 | return (NULL); /* don't reveal that the user doesn't exist */ |
| 514 | } |
| 515 | |
| 516 | if(mvc_trans(m) < 0) { |
| 517 | GDKfree(username); |
| 518 | return NULL; |
| 519 | } |
| 520 | |
| 521 | sys = find_sql_schema(m->session->tr, "sys" ); |
| 522 | user_info = find_sql_table(sys, "db_user_info" ); |
| 523 | users_name = find_sql_column(user_info, "name" ); |
| 524 | users_schema = find_sql_column(user_info, "default_schema" ); |
| 525 | |
| 526 | rid = table_funcs.column_find_row(m->session->tr, users_name, username, NULL); |
| 527 | if (!is_oid_nil(rid)) |
| 528 | p = table_funcs.column_find_value(m->session->tr, users_schema, rid); |
| 529 | |
| 530 | assert(p); |
| 531 | schema_id = *(sqlid *) p; |
| 532 | _DELETE(p); |
| 533 | |
| 534 | schemas = find_sql_table(sys, "schemas" ); |
| 535 | schemas_name = find_sql_column(schemas, "name" ); |
| 536 | schemas_id = find_sql_column(schemas, "id" ); |
| 537 | auths = find_sql_table(sys, "auths" ); |
| 538 | auths_name = find_sql_column(auths, "name" ); |
| 539 | |
| 540 | rid = table_funcs.column_find_row(m->session->tr, schemas_id, &schema_id, NULL); |
| 541 | if (!is_oid_nil(rid)) |
| 542 | schema = table_funcs.column_find_value(m->session->tr, schemas_name, rid); |
| 543 | |
| 544 | /* only set schema if user is found */ |
| 545 | rid = table_funcs.column_find_row(m->session->tr, auths_name, username, NULL); |
| 546 | if (!is_oid_nil(rid)) { |
| 547 | sql_column *auths_id = find_sql_column(auths, "id" ); |
| 548 | int id; |
| 549 | p = table_funcs.column_find_value(m->session->tr, auths_id, rid); |
| 550 | id = *(int *) p; |
| 551 | _DELETE(p); |
| 552 | |
| 553 | m->user_id = m->role_id = id; |
| 554 | } else { |
| 555 | schema = NULL; |
| 556 | } |
| 557 | |
| 558 | if (!schema || !mvc_set_schema(m, schema)) { |
| 559 | if (m->session->tr->active) { |
| 560 | if((other = mvc_rollback(m, 0, NULL, false)) != MAL_SUCCEED) |
| 561 | freeException(other); |
| 562 | } |
| 563 | GDKfree(username); |
| 564 | return NULL; |
| 565 | } |
| 566 | /* reset the user and schema names */ |
| 567 | if(!stack_set_string(m, "current_schema" , schema) || |
| 568 | !stack_set_string(m, "current_user" , username) || |
| 569 | !stack_set_string(m, "current_role" , username)) { |
| 570 | schema = NULL; |
| 571 | } |
| 572 | GDKfree(username); |
| 573 | if((other = mvc_rollback(m, 0, NULL, false)) != MAL_SUCCEED) { |
| 574 | freeException(other); |
| 575 | return NULL; |
| 576 | } |
| 577 | return schema; |
| 578 | } |
| 579 | |