⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mal_authorize.c

📁 一个内存数据库的源代码这是服务器端还有客户端
💻 C
📖 第 1 页 / 共 2 页
字号:
#line 83 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB5/src/mal/mal_authorize.mx"#include "mal_config.h"#include "mal_authorize.h"#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#ifdef HAVE_CRYPT_H#include <crypt.h>#else#if defined(HAVE_CRYPT) && defined(__MINGW32__)_CRTIMP char * __cdecl crypt(const char *key, const char *salt);#endif#endif#ifdef HAVE_OPENSSL#include <openssl/sha.h>#include <openssl/md5.h>#endifstatic str AUTHdecypherValue(str *ret, str *value);static str AUTHcypherValue(str *ret, str *value);static str AUTHhashPassword(str *ret, str *algo, str *passwd, str *challenge);static BAT *user = NULL;static BAT *pass = NULL;static BAT *scen = NULL;/** * Requires the current client to be the admin user.  If not the case, * this function returns an InvalidCredentialsException. */strAUTHrequireAdmin() {	oid id = MCgetClient()->user;	if (id != 0) {		char u[BUFSIZ]="";		str user = u;		str tmp;				rethrow("requireAdmin", tmp, AUTHresolveUser(&user, &id));		throw(INVCRED, "requireAdmin", "Access denied for user '%s'", user);	}	return(MAL_SUCCEED);}/** * Requires the current client to be the admin user, or the user with * the given username.  If not the case, this function returns an * InvalidCredentialsException. */strAUTHrequireAdminOrUser(str *username) {	oid id = MCgetClient()->user;	char u[BUFSIZ]= "";	str user = u;	str tmp= MAL_SUCCEED;	/* root?  then all is well */	if (id == 0) return(MAL_SUCCEED);	rethrow("requireAdminOrUser", tmp, AUTHresolveUser(&user, &id));	if (username == NULL || *username == NULL || strcmp(*username, user) != 0) {		throw(INVCRED, "requireAdminOrUser", "Access denied for user '%s'", user);	}	return(MAL_SUCCEED);}#line 160 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB5/src/mal/mal_authorize.mx"voidAUTHcommit() {	BAT *b = BATnew(TYPE_oid, TYPE_str, 3);	assert(b);	assert(user);	BUNappend(b, BATgetId(user), FALSE);	assert(pass);	BUNappend(b, BATgetId(pass), FALSE);	assert(pass);	BUNappend(b, BATgetId(scen), FALSE);	TMsubcommit(b);	BBPreclaim(b);}strAUTHinitTables() {	bat bid;	BAT *b;	int isNew = 1;	/* skip loading if already loaded */	if (user != NULL && pass != NULL && scen != NULL)		return(MAL_SUCCEED);	/* if one is not NULL here, something is seriously screwed up */	assert (user == NULL);	assert (pass == NULL);	assert (scen == NULL);	/* load/create users BAT */	bid = BBPindex("M5system_auth_user");	if (!bid) {		b = BATnew(TYPE_oid, TYPE_str, 256);		if (b == NULL)			throw(MAL, "initTables", "could not allocate user table");		BATkey(BATmirror(b), TRUE);		BBPrename(BBPcacheid(b), "M5system_auth_user");		BATmode(b, PERSISTENT);	} else {		b = BATdescriptor(bid);		isNew = 0;	}		assert(b);	user = b;	/* load/create password BAT */	bid = BBPindex("M5system_auth_passwd");	if (!bid) {		b = BATnew(TYPE_oid, TYPE_str, 256);		if (b == NULL)			throw(MAL, "initTables", "could not allocate password table");		BBPrename(BBPcacheid(b), "M5system_auth_passwd");		BATmode(b, PERSISTENT);	} else {		b = BATdescriptor(bid);		isNew = 0;	}	assert(b);	pass = b;	/* load/create scenario BAT */	bid = BBPindex("M5system_auth_scen");	if (!bid) {		b = BATnew(TYPE_oid, TYPE_str, 256);		if (b == NULL)			throw(MAL, "initTables", "could not allocate scenario table");		BATkey(b, TRUE);		BBPrename(BBPcacheid(b), "M5system_auth_scen");		BATmode(b, PERSISTENT);	} else {		b = BATdescriptor(bid);		isNew = 0;	}	assert(b);	scen = b;	if (isNew == 1) {		/* insert the monetdb/monetdb administrator account on a		 * complete fresh and new auth tables system */		str user = "monetdb";		str pass = "monetdb";		bat b = bat_nil;		str tmp;		oid uid;		rethrow("initTables", tmp, AUTHaddUser(&uid, &user, &pass, &b));		if (uid != 0)			throw(MAL, "initTables", "authorisation BATs not empty, but they were just created !?!?!?");		AUTHcommit();	}	return(MAL_SUCCEED);}/** * Check if the user/password combination aligns with * a given uid.*/strAUTHcheckUser(	int *ret,	str *username,	str *passwd){	/* to be filled */	(void) username; (void) passwd;	*ret =1;	return MAL_SUCCEED;}/** * Checks the credentials supplied and throws an exception if invalid. * The user id of the authenticated user is returned upon success. */strAUTHcheckCredentials(		oid *uid,		str *username,		str *passwd,		str *challenge,		str *algo,		str *scenario){	str tmp;	str pwd;	str hash;	BAT *b;	BUN p, q;	oid *id;	rethrow("checkCredentials", tmp, AUTHrequireAdminOrUser(username));	assert(user);	assert(pass);	assert(scen);	if (*username == NULL || strNil(*username))		throw(INVCRED, "checkCredentials", "Invalid credentials for unknown user");	p = BUNfnd(BATmirror(user), *username);	if (p == NULL) {		/* DO NOT reveal that the user doesn't exist here! */		throw(INVCRED, "checkCredentials", "Invalid credentials for user '%s'",				*username);	}	id = (oid*)(BUNhead(user, p));	/* a NULL password is impossible (since we should be dealing with	 * hashes here) so we can bail out immediately	 */	if (*passwd == NULL || strNil(*passwd)) {		/* DO NOT reveal that the password is NULL here! */		throw(INVCRED, "checkCredentials", "Invalid credentials for user '%s'",				*username);	}	/* find the corresponding password to the user */	q = BUNfnd(pass, id);	assert (q != NULL);	tmp = (str)BUNtail(pass, q);	assert (tmp != NULL);	/* decypher the password (we lose the original tmp here) */	rethrow("checkCredentials", tmp, AUTHdecypherValue(&pwd, &tmp));	/* generate the hash as the client should have done */	rethrow("checkCredentials", tmp, AUTHhashPassword(&hash, algo, &pwd, challenge));	/* and now we have it, compare it to what was given to us */	if (strcmp(*passwd, hash) != 0) {		/* of course we DO NOT print the password here */		throw(INVCRED, "checkCredentials", "Invalid credentials for user '%s'",				*username);	}	/* now see if the scenario is permitted (if restrictions for that	 * apply)	 */	b = BATselect(scen, id, id);	if (b && BATcount(b) > 0) {		if (*scenario == NULL || strNil(*scenario)) {			/* of course we DO NOT tell the exact reason here again */			throw(INVCRED, "checkCredentials", "Invalid credentials for user '%s'",					*username);		}		/* ok, there are some tuples that we have to consider */		BATloop(b, p, q) {			tmp = (str)BUNtail(b, p);			assert (tmp != NULL);			if (strcmp(*scenario, tmp) == 0) {				/* YAY!  fun!  party!  We are granted access! */				*uid = *id;				return(MAL_SUCCEED);			}		}		/* uh oh... that we made it till here means it's wrong */		throw(INVCRED, "checkCredentials", "Invalid credentials for user '%s'",				*username);	} else {		/* no scenario restriction applies, so everything is good */		*uid = *id;		return(MAL_SUCCEED);	}}/** * Adds the given user with password to the administration.  The scens * BAT contains all scenarios allowed for the user.  If NULL or empty, * no restrictions for a scenario applies.  The return value of this * function is the user id of the added user. */strAUTHaddUser(oid *uid, str *username, str *passwd, bat *scenarios) {	BUN p, q;	BAT *b;	oid *id;	str tmp;	str hash;	rethrow("addUser", tmp, AUTHrequireAdmin());	assert(user);	assert(pass);	assert(scen);		/* some pre-condition checks */	if (*username == NULL || strNil(*username))		throw(ILLARG, "addUser", "username cannot be nil");	if (*passwd == NULL || strNil(*passwd))		throw(ILLARG, "addUser", "password cannot be nil");	/* ensure that the username is not already there */	p = BUNfnd(BATmirror(user), *username);	if (p != NULL)		throw(MAL, "addUser", "user '%s' already exists", *username);		/* we assume the BATs are still aligned */	rethrow("addUser", tmp, AUTHcypherValue(&hash, passwd));	/* needs force, as SQL makes a view over user */	BUNappend(user, *username, TRUE);	BUNappend(pass, hash, FALSE);	/* should always be private! */	/* retrieve the oid of the just inserted user */	p = BUNfnd(BATmirror(user), *username);	assert (p != NULL);	id = (oid*)(BUNhead(user, p));	if (*scenarios != bat_nil) {		b = BATdescriptor(*scenarios);		if (b == NULL) {			BATundo(user);			BATundo(pass);			throw(ILLARG, "addUser", "invalid BAT!");		}		if (b->htype != TYPE_str) {			BATundo(user);			BATundo(pass);			throw(ILLARG, "addUser", "BAT should have str head");		}		/* associate scenarios given in the BAT with the user */		if (BATcount(b) > 0) {			BATloop(b, p, q) {				/* needs force, as sql makes a view over it */				BUNins(scen, id, BUNhead(b, p), TRUE);			}		}	}	/* make the stuff persistent */	AUTHcommit();	*uid = *id;	return(MAL_SUCCEED);}/** * Removes the given user from the administration.  All scenarios (if * any) and the password are removed as well. */strAUTHremoveUser(str *username) {	BUN p;	BAT *b;	oid id;	str tmp;	rethrow("removeUser", tmp, AUTHrequireAdmin());	assert(user);	assert(pass);	assert(scen);	/* pre-condition check */	if (*username == NULL || strNil(*username))		throw(ILLARG, "removeUser", "username cannot be nil");	/* ensure that the username exists */	p = BUNfnd(BATmirror(user), *username);	if (p == NULL)		throw(MAL, "removeUser", "no such user: '%s'", *username);	id = *(oid*)(BUNhead(user, p));	/* find the name of the administrator and see if it equals username */	if (id == MCgetClient()->user)		throw(MAL, "removeUser", "cannot remove yourself");	/* now, we got the oid, start removing the related tuples */	b = BATmirror(BATselect(BATmirror(user), &id, &id));	assert(BATcount(b) != 0);	BATdel(user, b, TRUE);	b = BATmirror(BATselect(BATmirror(pass), &id, &id));	assert(BATcount(b) != 0);	BATdel(pass, b, FALSE);	b = BATmirror(BATselect(BATmirror(scen), &id, &id));	BATdel(scen, b, TRUE);	/* make the stuff persistent */	AUTHcommit();	return(MAL_SUCCEED);}/** * Changes the username of the user indicated by olduser into newuser. * If the username is already in use, an exception is thrown and nothing * is modified. */strAUTHchangeUsername(str *olduser, str *newuser) {	BUN p, q;	str tmp;	rethrow("addUser", tmp, AUTHrequireAdminOrUser(olduser));	/* precondition checks */	if (*olduser == NULL || strNil(*olduser))		throw(ILLARG, "changeUsername", "old username should not be nil");	if (*newuser == NULL || strNil(*newuser))		throw(ILLARG, "changeUsername", "new username should not be nil");	/* see if the olduser is valid */	p = BUNfnd(BATmirror(user), *olduser);	if (p == NULL)		throw(MAL, "changeUsername", "user '%s' does not exist", *olduser);	/* ... and if the newuser is not there yet */	q = BUNfnd(BATmirror(user), *newuser);	if (q != NULL)		throw(MAL, "changeUsername", "user '%s' already exists", *newuser);	/* ok, just do it! (with force, because sql makes view over it) */	BUNinplace(BATmirror(user), p, *newuser, BUNhead(user, p), TRUE);	AUTHcommit();	return(MAL_SUCCEED);}/** * Changes the password of the current user to the given password.  The * old password must match the one stored before the new password is * set. */strAUTHchangePassword(str *oldpass, str *passwd) {	BUN p;	str tmp;	str hash;	oid id;	/* precondition checks */	if (*oldpass == NULL || strNil(*oldpass))		throw(ILLARG, "changePassword", "old password should not be nil");	if (*passwd == NULL || strNil(*passwd))		throw(ILLARG, "changePassword", "password should not be nil");	/* check the old password */	id = MCgetClient()->user;	p = BUNfnd(pass, &id);	assert(p != NULL);	tmp = BUNtail(pass, p);	assert (tmp != NULL);	if (strcmp(tmp, *oldpass) != 0)		throw(INVCRED, "changePassword", "Access denied");	/* cypher the password */	rethrow("setPassword", tmp, AUTHcypherValue(&hash, passwd));	/* ok, just overwrite the password field for this user */	BUNinplace(pass, p, BUNhead(pass, p), &hash, FALSE);	AUTHcommit();	return(MAL_SUCCEED);}/** * Changes the password of the given user to the given password.  This * function can be used by the administrator to reset the password for a * user.  Note that for the administrator to change its own password, it * cannot use this function for obvious reasons. */strAUTHsetPassword(str *username, str *passwd) {	BUN p;	str tmp;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -