Changeset: 7b380d84f5ee for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/7b380d84f5ee
Modified Files:
monetdb5/mal/mal_authorize.c
Branch: default
Log Message:
Use locks to protect concurrent access to remote table credentials bats.
diffs (truncated from 502 to 300 lines):
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
@@ -31,8 +31,6 @@
#include <unistd.h>
#endif
-static BUN lookupRemoteTableKey(const char *key);
-
/* Remote table bats */
static BAT *rt_key = NULL;
static BAT *rt_uri = NULL;
@@ -42,16 +40,23 @@ static BAT *rt_deleted = NULL;
/* yep, the vault key is just stored in memory */
static str vaultKey = NULL;
static str master_password = NULL;
+/* lock to protect the above */
+static MT_RWLock rt_lock = MT_RWLOCK_INITIALIZER(rt_lock);
static AUTHCallbackCntx authCallbackCntx = {
.get_user_name = NULL,
.get_user_password = NULL,
.get_user_oid = NULL
};
+static str AUTHdeleteRemoteTableCredentialsLocked(const char *local_table);
+static str AUTHdecypherValueLocked(str *ret, const char *value);
+
void AUTHreset(void)
{
+ MT_rwlock_wrlock(&rt_lock);
GDKfree(vaultKey);
vaultKey = NULL;
+ MT_rwlock_wrunlock(&rt_lock);
}
/**
@@ -67,7 +72,7 @@ AUTHrequireAdmin(Client cntxt) {
return(MAL_SUCCEED);
}
-static void
+static str
AUTHcommit(void)
{
bat blist[6];
@@ -104,9 +109,13 @@ AUTHinitTables(void) {
int isNew = 1;
str msg = MAL_SUCCEED;
+ MT_rwlock_wrlock(&rt_lock);
+
/* skip loading if already loaded */
- if (rt_key != NULL && rt_deleted != NULL)
+ if (rt_key != NULL && rt_deleted != NULL) {
+ MT_rwlock_wrunlock(&rt_lock);
return(MAL_SUCCEED);
+ }
/* Remote table authorization table.
*
@@ -117,12 +126,16 @@ AUTHinitTables(void) {
bid = BBPindex("M5system_auth_rt_key");
if (!bid) {
rt_key = COLnew(0, TYPE_str, 256, PERSISTENT);
- if (rt_key == NULL)
+ if (rt_key == NULL) {
+ MT_rwlock_wrunlock(&rt_lock);
throw(MAL, "initTables.rt_key", SQLSTATE(HY013)
MAL_MALLOC_FAIL " remote table key bat");
+ }
if (BBPrename(rt_key, "M5system_auth_rt_key") != 0 ||
- BATmode(rt_key, false) != GDK_SUCCEED)
+ BATmode(rt_key, false) != GDK_SUCCEED) {
+ MT_rwlock_wrunlock(&rt_lock);
throw(MAL, "initTables.rt_key", GDK_EXCEPTION);
+ }
}
else {
int dbg = GDKdebug;
@@ -131,6 +144,7 @@ AUTHinitTables(void) {
rt_key = BATdescriptor(bid);
GDKdebug = dbg;
if (rt_key == NULL) {
+ MT_rwlock_wrunlock(&rt_lock);
throw(MAL, "initTables.rt_key", SQLSTATE(HY002)
RUNTIME_OBJECT_MISSING);
}
isNew = 0;
@@ -141,12 +155,16 @@ AUTHinitTables(void) {
bid = BBPindex("M5system_auth_rt_uri");
if (!bid) {
rt_uri = COLnew(0, TYPE_str, 256, PERSISTENT);
- if (rt_uri == NULL)
+ if (rt_uri == NULL) {
+ MT_rwlock_wrunlock(&rt_lock);
throw(MAL, "initTables.rt_uri", SQLSTATE(HY013)
MAL_MALLOC_FAIL " remote table uri bat");
+ }
if (BBPrename(rt_uri, "M5system_auth_rt_uri") != 0 ||
- BATmode(rt_uri, false) != GDK_SUCCEED)
+ BATmode(rt_uri, false) != GDK_SUCCEED) {
+ MT_rwlock_wrunlock(&rt_lock);
throw(MAL, "initTables.rt_uri", GDK_EXCEPTION);
+ }
}
else {
int dbg = GDKdebug;
@@ -155,6 +173,7 @@ AUTHinitTables(void) {
rt_uri = BATdescriptor(bid);
GDKdebug = dbg;
if (rt_uri == NULL) {
+ MT_rwlock_wrunlock(&rt_lock);
throw(MAL, "initTables.rt_uri", SQLSTATE(HY002)
RUNTIME_OBJECT_MISSING);
}
isNew = 0;
@@ -165,12 +184,16 @@ AUTHinitTables(void) {
bid = BBPindex("M5system_auth_rt_remoteuser");
if (!bid) {
rt_remoteuser = COLnew(0, TYPE_str, 256, PERSISTENT);
- if (rt_remoteuser == NULL)
+ if (rt_remoteuser == NULL) {
+ MT_rwlock_wrunlock(&rt_lock);
throw(MAL, "initTables.rt_remoteuser", SQLSTATE(HY013)
MAL_MALLOC_FAIL " remote table local user bat");
+ }
if (BBPrename(rt_remoteuser, "M5system_auth_rt_remoteuser") !=
0 ||
- BATmode(rt_remoteuser, false) != GDK_SUCCEED)
+ BATmode(rt_remoteuser, false) != GDK_SUCCEED) {
+ MT_rwlock_wrunlock(&rt_lock);
throw(MAL, "initTables.rt_remoteuser", GDK_EXCEPTION);
+ }
}
else {
int dbg = GDKdebug;
@@ -179,6 +202,7 @@ AUTHinitTables(void) {
rt_remoteuser = BATdescriptor(bid);
GDKdebug = dbg;
if (rt_remoteuser == NULL) {
+ MT_rwlock_wrunlock(&rt_lock);
throw(MAL, "initTables.rt_remoteuser", SQLSTATE(HY002)
RUNTIME_OBJECT_MISSING);
}
isNew = 0;
@@ -189,12 +213,16 @@ AUTHinitTables(void) {
bid = BBPindex("M5system_auth_rt_hashedpwd");
if (!bid) {
rt_hashedpwd = COLnew(0, TYPE_str, 256, PERSISTENT);
- if (rt_hashedpwd == NULL)
+ if (rt_hashedpwd == NULL) {
+ MT_rwlock_wrunlock(&rt_lock);
throw(MAL, "initTables.rt_hashedpwd", SQLSTATE(HY013)
MAL_MALLOC_FAIL " remote table local user bat");
+ }
if (BBPrename(rt_hashedpwd, "M5system_auth_rt_hashedpwd") != 0
||
- BATmode(rt_hashedpwd, false) != GDK_SUCCEED)
+ BATmode(rt_hashedpwd, false) != GDK_SUCCEED) {
+ MT_rwlock_wrunlock(&rt_lock);
throw(MAL, "initTables.rt_hashedpwd", GDK_EXCEPTION);
+ }
}
else {
int dbg = GDKdebug;
@@ -203,6 +231,7 @@ AUTHinitTables(void) {
rt_hashedpwd = BATdescriptor(bid);
GDKdebug = dbg;
if (rt_hashedpwd == NULL) {
+ MT_rwlock_wrunlock(&rt_lock);
throw(MAL, "initTables.rt_hashedpwd", SQLSTATE(HY002)
RUNTIME_OBJECT_MISSING);
}
isNew = 0;
@@ -213,22 +242,29 @@ AUTHinitTables(void) {
bid = BBPindex("M5system_auth_rt_deleted");
if (!bid) {
rt_deleted = COLnew(0, TYPE_oid, 256, PERSISTENT);
- if (rt_deleted == NULL)
+ if (rt_deleted == NULL) {
+ MT_rwlock_wrunlock(&rt_lock);
throw(MAL, "initTables.rt_deleted", SQLSTATE(HY013)
MAL_MALLOC_FAIL " remote table local user bat");
+ }
if (BBPrename(rt_deleted, "M5system_auth_rt_deleted") != 0 ||
- BATmode(rt_deleted, false) != GDK_SUCCEED)
+ BATmode(rt_deleted, false) != GDK_SUCCEED) {
+ MT_rwlock_wrunlock(&rt_lock);
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();
+ if (!isNew && (msg = AUTHcommit()) != MAL_SUCCEED) {
+ MT_rwlock_wrunlock(&rt_lock);
+ return msg;
+ }
}
else {
rt_deleted = BATdescriptor(bid);
if (rt_deleted == NULL) {
+ MT_rwlock_wrunlock(&rt_lock);
throw(MAL, "initTables.rt_deleted", SQLSTATE(HY002)
RUNTIME_OBJECT_MISSING);
}
isNew = 0;
@@ -242,10 +278,13 @@ AUTHinitTables(void) {
if (msg != NULL) {
char *nmsg = createException(MAL, "initTables", "%s",
msg);
free(msg);
+ MT_rwlock_wrunlock(&rt_lock);
return nmsg;
}
}
+ MT_rwlock_wrunlock(&rt_lock);
+
return(MAL_SUCCEED);
}
@@ -321,7 +360,9 @@ AUTHcheckCredentials(
/* special case: users whose name starts with '.' can authenticate using
* the temporary master password.
*/
+ MT_rwlock_rdlock(&rt_lock);
if (username[0] == '.' && master_password != NULL && master_password[0]
!= '\0') {
+ MT_rwlock_rdunlock(&rt_lock);
// first encrypt the master password as if we've just found it
// in the password store
str encrypted = mcrypt_BackendSum(master_password,
strlen(master_password));
@@ -335,7 +376,8 @@ AUTHcheckCredentials(
return(MAL_SUCCEED);
}
free(hash);
- }
+ } else
+ MT_rwlock_rdunlock(&rt_lock);
/* of course we DO NOT print the password here */
throw(INVCRED, "checkCredentials", INVCRED_INVALID_USER " '%s'",
username);
@@ -363,14 +405,14 @@ AUTHgetUsername(str *username, Client cn
* Returns the password hash as used by the backend for the given
* username. Throws an exception if called by a non-superuser.
*/
-str
-AUTHgetPasswordHash(str *ret, Client cntxt, const char *username)
+static str
+AUTHgetPasswordHashLocked(str *ret, Client cntxt, const char *username)
{
str tmp;
str msg;
str passwd = NULL;
- rethrow("getPasswordHash", tmp, AUTHrequireAdmin(cntxt));
+ rethrow("getPasswordHash", msg, AUTHrequireAdmin(cntxt));
if (strNil(username))
throw(ILLARG, "getPasswordHash", "username should not be nil");
@@ -383,18 +425,26 @@ AUTHgetPasswordHash(str *ret, Client cnt
throw(MAL, "getPasswordHash", "user '%s' does not exist",
username);
}
/* decypher the password */
- if ((msg = AUTHdecypherValue(&passwd, tmp)) != MAL_SUCCEED) {
+ if ((msg = AUTHdecypherValueLocked(&passwd, tmp)) != MAL_SUCCEED) {
GDKfree(tmp);
return msg;
}
- if(tmp)
+ if (tmp)
GDKfree(tmp);
*ret = passwd;
return(MAL_SUCCEED);
}
+str
+AUTHgetPasswordHash(str *ret, Client cntxt, const char *username)
+{
+ MT_rwlock_rdlock(&rt_lock);
+ str err = AUTHgetPasswordHashLocked(ret, cntxt, username);
+ MT_rwlock_rdunlock(&rt_lock);
+ return err;
+}
/*=== the vault ===*/
@@ -415,10 +465,15 @@ AUTHunlockVault(const char *password)
/* even though I think this function should be called only once, it
* is not of real extra efforts to avoid a mem-leak if it is used
* multiple times */
+ MT_rwlock_wrlock(&rt_lock);
GDKfree(vaultKey);
- if ((vaultKey = GDKstrdup(password)) == NULL)
+ vaultKey = GDKstrdup(password);
+ if (vaultKey == NULL) {
+ MT_rwlock_wrunlock(&rt_lock);
throw(MAL, "unlockVault", SQLSTATE(HY013) MAL_MALLOC_FAIL "
vault key");
+ }
+ MT_rwlock_wrunlock(&rt_lock);
return(MAL_SUCCEED);
}
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]