Changeset: fba25b4e2d46 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=fba25b4e2d46 Added Files: sql/test/remote/Tests/creds.SQL.py.in sql/test/remote/Tests/creds.stable.err sql/test/remote/Tests/creds.stable.out sql/test/remote/Tests/different_user.SQL.py.in sql/test/remote/Tests/different_user.stable.err sql/test/remote/Tests/different_user.stable.out sql/test/remote/Tests/invalid_creds.SQL.py.in sql/test/remote/Tests/invalid_creds.stable.err sql/test/remote/Tests/invalid_creds.stable.out Modified Files: clients/Tests/MAL-signatures.stable.out clients/Tests/MAL-signatures.stable.out.int128 clients/Tests/exports.stable.out clients/mapiclient/dump.c monetdb5/mal/mal_authorize.c monetdb5/mal/mal_authorize.h monetdb5/modules/mal/remote.c monetdb5/modules/mal/remote.h monetdb5/modules/mal/remote.mal sql/backends/monet5/sql.c sql/backends/monet5/sql.h sql/backends/monet5/sql.mal sql/backends/monet5/sql_gencode.c sql/backends/monet5/sql_upgrades.c sql/scripts/22_clients.sql sql/server/rel_distribute.c sql/server/rel_psm.c sql/server/rel_schema.c sql/server/rel_schema.h sql/server/sql_mvc.c sql/server/sql_parser.y sql/server/sql_semantic.c sql/test/BugTracker-2015/Tests/msqldump-merge-and-remote-tables.Bug-3774.stable.out sql/test/BugTracker-2015/Tests/schemadiff.Bug-3778.stable.out sql/test/emptydb-upgrade-chain-hge/Tests/upgrade.stable.out.int128 sql/test/emptydb-upgrade-chain/Tests/upgrade.stable.out sql/test/emptydb-upgrade-chain/Tests/upgrade.stable.out.32bit sql/test/emptydb-upgrade-chain/Tests/upgrade.stable.out.int128 sql/test/emptydb-upgrade-chain/Tests/upgrade.stable.out.powerpc64.int128 sql/test/emptydb-upgrade-hge/Tests/upgrade.stable.out.int128 sql/test/emptydb-upgrade/Tests/upgrade.stable.out.32bit sql/test/emptydb-upgrade/Tests/upgrade.stable.out.int128 sql/test/emptydb/Tests/check.stable.out sql/test/emptydb/Tests/check.stable.out.32bit sql/test/emptydb/Tests/check.stable.out.int128 sql/test/remote/Tests/All sql/test/remote/Tests/ssbm.SQL.py sql/test/testdb-upgrade-chain-hge/Tests/upgrade.stable.out.int128 sql/test/testdb-upgrade-chain/Tests/upgrade.stable.out sql/test/testdb-upgrade-chain/Tests/upgrade.stable.out.32bit sql/test/testdb-upgrade-chain/Tests/upgrade.stable.out.int128 sql/test/testdb-upgrade-hge/Tests/upgrade.stable.out.int128 sql/test/testdb-upgrade/Tests/upgrade.stable.out sql/test/testdb-upgrade/Tests/upgrade.stable.out.32bit sql/test/testdb-upgrade/Tests/upgrade.stable.out.int128 Branch: default Log Message:
Merge remote_auth into default branch diffs (truncated from 2537 to 300 lines): diff --git a/clients/Tests/MAL-signatures.stable.out b/clients/Tests/MAL-signatures.stable.out --- a/clients/Tests/MAL-signatures.stable.out +++ b/clients/Tests/MAL-signatures.stable.out @@ -10760,6 +10760,7 @@ Ready. [ "remote", "bintype", "pattern remote.bintype():void ", "RMTbintype;", "print the binary type of this mserver5" ] [ "remote", "connect", "command remote.connect(uri:str, user:str, passwd:str):str ", "RMTconnect;", "returns a newly created connection for uri, using user name and password" ] [ "remote", "connect", "command remote.connect(uri:str, user:str, passwd:str, scen:str):str ", "RMTconnectScen;", "returns a newly created connection for uri, using user name, password and scenario" ] +[ "remote", "connect", "pattern remote.connect(table:str, schen:str):str ", "RMTconnectTable;", "return a newly created connection for a table. username and password should be in the vault" ] [ "remote", "disconnect", "command remote.disconnect(conn:str):void ", "RMTdisconnect;", "disconnects the connection pointed to by handle (received from a call to connect()" ] [ "remote", "epilogue", "command remote.epilogue():void ", "RMTepilogue;", "release the resources held by the remote module" ] [ "remote", "exec", "pattern remote.exec(conn:str, mod:str, func:str):str ", "RMTexec;", "remotely executes <mod>.<func> and returns the handle to its result" ] @@ -10895,6 +10896,7 @@ Ready. [ "sql", "round", "command sql.round(v:lng, d:int, s:int, r:bte):lng ", "lng_round_wrap;", "round off the decimal v(d,s) to r digits behind the dot (if r < 0, before the dot)" ] [ "sql", "round", "command sql.round(v:sht, d:int, s:int, r:bte):sht ", "sht_round_wrap;", "round off the decimal v(d,s) to r digits behind the dot (if r < 0, before the dot)" ] [ "sql", "row_number", "pattern sql.row_number(b:any_1, p:bit, o:bit):int ", "SQLrow_number;", "return the row_numer-ed groups" ] +[ "sql", "rt_credentials", "pattern sql.rt_credentials(tablename:str) (uri:bat[:str], username:bat[:str], hash:bat[:str]) ", "sql_rt_credentials_wrap;", "Return the remote table credentials for the given table" ] [ "sql", "sessions", "pattern sql.sessions() (user:bat[:str], start:bat[:timestamp], stimeout:bat[:lng], lastcmd:bat[:timestamp], qtimeout:bat[:lng], idle:bat[:bit]) ", "sql_sessions_wrap;", "SQL export table of active sessions, their timeouts and idle status" ] [ "sql", "setVariable", "pattern sql.setVariable(mvc:int, varname:str, value:any_1):int ", "setVariable;", "Set the value of a session variable" ] [ "sql", "shrink", "pattern sql.shrink(sch:str, tbl:str):void ", "SQLshrink;", "Consolidate the deletion table over all columns using shrinking" ] diff --git a/clients/Tests/MAL-signatures.stable.out.int128 b/clients/Tests/MAL-signatures.stable.out.int128 --- a/clients/Tests/MAL-signatures.stable.out.int128 +++ b/clients/Tests/MAL-signatures.stable.out.int128 @@ -14971,6 +14971,7 @@ Ready. [ "remote", "bintype", "pattern remote.bintype():void ", "RMTbintype;", "print the binary type of this mserver5" ] [ "remote", "connect", "command remote.connect(uri:str, user:str, passwd:str):str ", "RMTconnect;", "returns a newly created connection for uri, using user name and password" ] [ "remote", "connect", "command remote.connect(uri:str, user:str, passwd:str, scen:str):str ", "RMTconnectScen;", "returns a newly created connection for uri, using user name, password and scenario" ] +[ "remote", "connect", "pattern remote.connect(table:str, schen:str):str ", "RMTconnectTable;", "return a newly created connection for a table. username and password should be in the vault" ] [ "remote", "disconnect", "command remote.disconnect(conn:str):void ", "RMTdisconnect;", "disconnects the connection pointed to by handle (received from a call to connect()" ] [ "remote", "epilogue", "command remote.epilogue():void ", "RMTepilogue;", "release the resources held by the remote module" ] [ "remote", "exec", "pattern remote.exec(conn:str, mod:str, func:str):str ", "RMTexec;", "remotely executes <mod>.<func> and returns the handle to its result" ] @@ -15108,6 +15109,7 @@ Ready. [ "sql", "round", "command sql.round(v:lng, d:int, s:int, r:bte):lng ", "lng_round_wrap;", "round off the decimal v(d,s) to r digits behind the dot (if r < 0, before the dot)" ] [ "sql", "round", "command sql.round(v:sht, d:int, s:int, r:bte):sht ", "sht_round_wrap;", "round off the decimal v(d,s) to r digits behind the dot (if r < 0, before the dot)" ] [ "sql", "row_number", "pattern sql.row_number(b:any_1, p:bit, o:bit):int ", "SQLrow_number;", "return the row_numer-ed groups" ] +[ "sql", "rt_credentials", "pattern sql.rt_credentials(tablename:str) (uri:bat[:str], username:bat[:str], hash:bat[:str]) ", "sql_rt_credentials_wrap;", "Return the remote table credentials for the given table" ] [ "sql", "sessions", "pattern sql.sessions() (user:bat[:str], start:bat[:timestamp], stimeout:bat[:lng], lastcmd:bat[:timestamp], qtimeout:bat[:lng], idle:bat[:bit]) ", "sql_sessions_wrap;", "SQL export table of active sessions, their timeouts and idle status" ] [ "sql", "setVariable", "pattern sql.setVariable(mvc:int, varname:str, value:any_1):int ", "setVariable;", "Set the value of a session variable" ] [ "sql", "shrink", "pattern sql.shrink(sch:str, tbl:str):void ", "SQLshrink;", "Consolidate the deletion table over all columns using shrinking" ] diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out --- a/clients/Tests/exports.stable.out +++ b/clients/Tests/exports.stable.out @@ -739,11 +739,14 @@ str ALGunique1(bat *result, const bat *b str ALGunique2(bat *result, const bat *bid, const bat *sid); str ALGvariance(dbl *res, const bat *bid); str ALGvariancep(dbl *res, const bat *bid); +str AUTHaddRemoteTableCredentials(const char *local_table, const char *localuser, const char *uri, const char *remoteuser, const char *pass, bool pw_encrypted); str AUTHaddUser(oid *ret, Client c, const char *user, const char *pass); str AUTHchangePassword(Client c, const char *oldpass, const char *passwd); str AUTHchangeUsername(Client c, const char *olduser, const char *newuser); str AUTHcheckCredentials(oid *ret, Client c, const char *user, const char *passwd, const char *challenge, const char *algo); +str AUTHdeleteRemoteTableCredentials(const char *local_table); str AUTHgetPasswordHash(str *ret, Client c, const char *username); +str AUTHgetRemoteTableCredentials(const char *local_table, str *uri, str *username, str *password); str AUTHgetUsername(str *ret, Client c); str AUTHgetUsers(BAT **ret1, BAT **ret2, Client c); str AUTHinitTables(const char *passwd); @@ -1645,6 +1648,7 @@ str RMTbincopyto(Client cntxt, MalBlkPtr str RMTbintype(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); str RMTconnect(str *ret, str *uri, str *user, str *passwd); str RMTconnectScen(str *ret, str *ouri, str *user, str *passwd, str *scen); +str RMTconnectTable(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); str RMTdisconnect(void *ret, str *conn); str RMTepilogue(void *ret); str RMTexec(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); diff --git a/clients/mapiclient/dump.c b/clients/mapiclient/dump.c --- a/clients/mapiclient/dump.c +++ b/clients/mapiclient/dump.c @@ -870,8 +870,21 @@ describe_table(Mapi mid, const char *sch if (dump_column_definition(mid, toConsole, schema, tname, NULL, foreign, hashge)) goto bailout; - if (type == 5) - mnstr_printf(toConsole, " ON '%s'", view); + if (type == 5) { /* remote table */ + char *rt_user = NULL; + char *rt_hash = NULL; + snprintf(query, maxquerylen, + "SELECT username, hash FROM sys.remote_table_credentials('%s.%s')", + schema, tname); + if ((hdl = mapi_query(mid, query)) == NULL || mapi_error(mid)) + goto bailout; + cnt = 0; + while(mapi_fetch_row(hdl) != 0) { + rt_user = mapi_fetch_field(hdl, 0); + rt_hash = mapi_fetch_field(hdl, 1); + } + mnstr_printf(toConsole, " ON '%s' WITH USER '%s' ENCRYPTED PASSWORD '%s'", view, rt_user, rt_hash); + } mnstr_printf(toConsole, ";\n"); comment_on(toConsole, "TABLE", schema, tname, NULL, remark); diff --git a/monetdb5/mal/mal_authorize.c b/monetdb5/mal/mal_authorize.c --- a/monetdb5/mal/mal_authorize.c +++ b/monetdb5/mal/mal_authorize.c @@ -42,10 +42,18 @@ static str AUTHdecypherValue(str *ret, const char *value); static str AUTHcypherValue(str *ret, const char *value); static str AUTHverifyPassword(const char *passwd); +static BUN lookupRemoteTableKey(const char *key); static BAT *user = NULL; static BAT *pass = NULL; static BAT *duser = NULL; + +/* Remote table bats */ +static BAT *rt_key = NULL; +static BAT *rt_uri = NULL; +static BAT *rt_remoteuser = NULL; +static BAT *rt_hashedpwd = NULL; +static BAT *rt_deleted = NULL; /* yep, the vault key is just stored in memory */ static str vaultKey = NULL; @@ -130,7 +138,7 @@ AUTHrequireAdminOrUser(Client cntxt, con static void AUTHcommit(void) { - bat blist[4]; + bat blist[9]; blist[0] = 0; @@ -140,7 +148,17 @@ AUTHcommit(void) blist[2] = pass->batCacheid; assert(duser); blist[3] = duser->batCacheid; - TMsubcommit_list(blist, 4); + assert(rt_key); + blist[4] = rt_key->batCacheid; + assert(rt_uri); + blist[5] = rt_uri->batCacheid; + assert(rt_remoteuser); + blist[6] = rt_remoteuser->batCacheid; + assert(rt_hashedpwd); + blist[7] = rt_hashedpwd->batCacheid; + assert(rt_deleted); + blist[8] = rt_deleted->batCacheid; + TMsubcommit_list(blist, 9); } /* @@ -224,8 +242,6 @@ AUTHinitTables(const char *passwd) { BATmode(duser, PERSISTENT) != GDK_SUCCEED) { throw(MAL, "initTables.user", GDK_EXCEPTION); } - if (!isNew) - AUTHcommit(); } else { duser = BATdescriptor(bid); if (duser == NULL) @@ -234,6 +250,133 @@ AUTHinitTables(const char *passwd) { } assert(duser); + /* Remote table authorization table. + * + * This table holds the remote tabe authorization credentials + * (uri, username and hashed password). + */ + /* load/create remote table URI BAT */ + bid = BBPindex("M5system_auth_rt_key"); + if (!bid) { + rt_key = COLnew(0, TYPE_str, 256, PERSISTENT); + if (rt_key == NULL) + throw(MAL, "initTables.rt_key", SQLSTATE(HY001) MAL_MALLOC_FAIL " remote table key bat"); + + if (BBPrename(BBPcacheid(rt_key), "M5system_auth_rt_key") != 0 || + BATmode(rt_key, PERSISTENT) != GDK_SUCCEED) + throw(MAL, "initTables.rt_key", GDK_EXCEPTION); + } + else { + int dbg = GDKdebug; + /* don't check this bat since we'll fix it below */ + GDKdebug &= ~CHECKMASK; + rt_key = BATdescriptor(bid); + GDKdebug = dbg; + if (rt_key == NULL) { + throw(MAL, "initTables.rt_key", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); + } + isNew = 0; + } + assert(rt_key); + + /* load/create remote table URI BAT */ + bid = BBPindex("M5system_auth_rt_uri"); + if (!bid) { + rt_uri = COLnew(0, TYPE_str, 256, PERSISTENT); + if (rt_uri == NULL) + throw(MAL, "initTables.rt_uri", SQLSTATE(HY001) MAL_MALLOC_FAIL " remote table uri bat"); + + if (BBPrename(BBPcacheid(rt_uri), "M5system_auth_rt_uri") != 0 || + BATmode(rt_uri, PERSISTENT) != GDK_SUCCEED) + throw(MAL, "initTables.rt_uri", GDK_EXCEPTION); + } + else { + int dbg = GDKdebug; + /* don't check this bat since we'll fix it below */ + GDKdebug &= ~CHECKMASK; + rt_uri = BATdescriptor(bid); + GDKdebug = dbg; + if (rt_uri == NULL) { + throw(MAL, "initTables.rt_uri", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); + } + isNew = 0; + } + assert(rt_uri); + + /* load/create remote table remote user name BAT */ + bid = BBPindex("M5system_auth_rt_remoteuser"); + if (!bid) { + rt_remoteuser = COLnew(0, TYPE_str, 256, PERSISTENT); + if (rt_remoteuser == NULL) + throw(MAL, "initTables.rt_remoteuser", SQLSTATE(HY001) MAL_MALLOC_FAIL " remote table local user bat"); + + if (BBPrename(BBPcacheid(rt_remoteuser), "M5system_auth_rt_remoteuser") != 0 || + BATmode(rt_remoteuser, PERSISTENT) != GDK_SUCCEED) + throw(MAL, "initTables.rt_remoteuser", GDK_EXCEPTION); + } + else { + int dbg = GDKdebug; + /* don't check this bat since we'll fix it below */ + GDKdebug &= ~CHECKMASK; + rt_remoteuser = BATdescriptor(bid); + GDKdebug = dbg; + if (rt_remoteuser == NULL) { + throw(MAL, "initTables.rt_remoteuser", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); + } + isNew = 0; + } + assert(rt_remoteuser); + + /* load/create remote table password BAT */ + bid = BBPindex("M5system_auth_rt_hashedpwd"); + if (!bid) { + rt_hashedpwd = COLnew(0, TYPE_str, 256, PERSISTENT); + if (rt_hashedpwd == NULL) + throw(MAL, "initTables.rt_hashedpwd", SQLSTATE(HY001) MAL_MALLOC_FAIL " remote table local user bat"); + + if (BBPrename(BBPcacheid(rt_hashedpwd), "M5system_auth_rt_hashedpwd") != 0 || + BATmode(rt_hashedpwd, PERSISTENT) != GDK_SUCCEED) + throw(MAL, "initTables.rt_hashedpwd", GDK_EXCEPTION); + } + else { + int dbg = GDKdebug; + /* don't check this bat since we'll fix it below */ + GDKdebug &= ~CHECKMASK; + rt_hashedpwd = BATdescriptor(bid); + GDKdebug = dbg; + if (rt_hashedpwd == NULL) { + throw(MAL, "initTables.rt_hashedpwd", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); + } + isNew = 0; + } + assert(rt_hashedpwd); + + /* load/create remote table deleted entries BAT */ + bid = BBPindex("M5system_auth_rt_deleted"); + if (!bid) { + rt_deleted = COLnew(0, TYPE_oid, 256, PERSISTENT); + if (rt_deleted == NULL) + throw(MAL, "initTables.rt_deleted", SQLSTATE(HY001) MAL_MALLOC_FAIL " remote table local user bat"); + + if (BBPrename(BBPcacheid(rt_deleted), "M5system_auth_rt_deleted") != 0 || + BATmode(rt_deleted, PERSISTENT) != GDK_SUCCEED) + throw(MAL, "initTables.rt_deleted", GDK_EXCEPTION); + /* If the database is not new, but we just created this BAT, + * write everything to disc. This needs to happen only after + * the last BAT of the vault has been created. + */ + if (!isNew) + AUTHcommit(); + } + else { + rt_deleted = BATdescriptor(bid); + if (rt_deleted == NULL) { + throw(MAL, "initTables.rt_deleted", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); + } + isNew = 0; + } + assert(rt_deleted); + if (isNew == 1) { /* insert the monetdb/monetdb administrator account on a * complete fresh and new auth tables system */ @@ -822,3 +965,208 @@ AUTHverifyPassword(const char *passwd) MONETDB5_PASSWDHASH); #endif } + +static BUN +lookupRemoteTableKey(const char *key) +{ + BATiter cni = bat_iterator(rt_key); + BUN p = BUN_NONE; + + assert(rt_key); + assert(rt_deleted); + + if (BAThash(rt_key, 0) == GDK_SUCCEED) { + HASHloop_str(cni, cni.b->thash, p, key) { _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list