#include "sqliteInt.h"
#ifndef SQLITE_OMIT_AUTHORIZATION
int sqlite3_set_authorizer(
sqlite3 *db,
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
void *pArg
){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif
sqlite3_mutex_enter(db->mutex);
db->xAuth = (sqlite3_xauth)xAuth;
db->pAuthArg = pArg;
if( db->xAuth ) sqlite3ExpirePreparedStatements(db, 1);
sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
}
static void sqliteAuthBadReturnCode(Parse *pParse){
sqlite3ErrorMsg(pParse, "authorizer malfunction");
pParse->rc = SQLITE_ERROR;
}
int sqlite3AuthReadCol(
Parse *pParse,
const char *zTab,
const char *zCol,
int iDb
){
sqlite3 *db = pParse->db;
char *zDb = db->aDb[iDb].zDbSName;
int rc;
if( db->init.busy ) return SQLITE_OK;
rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext
#ifdef SQLITE_USER_AUTHENTICATION
,db->auth.zAuthUser
#endif
);
if( rc==SQLITE_DENY ){
char *z = sqlite3_mprintf("%s.%s", zTab, zCol);
if( db->nDb>2 || iDb!=0 ) z = sqlite3_mprintf("%s.%z", zDb, z);
sqlite3ErrorMsg(pParse, "access to %z is prohibited", z);
pParse->rc = SQLITE_AUTH;
}else if( rc!=SQLITE_IGNORE && rc!=SQLITE_OK ){
sqliteAuthBadReturnCode(pParse);
}
return rc;
}
void sqlite3AuthRead(
Parse *pParse,
Expr *pExpr,
Schema *pSchema,
SrcList *pTabList
){
Table *pTab = 0;
const char *zCol;
int iSrc;
int iDb;
int iCol;
assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER );
assert( !IN_RENAME_OBJECT );
assert( pParse->db->xAuth!=0 );
iDb = sqlite3SchemaToIndex(pParse->db, pSchema);
if( iDb<0 ){
return;
}
if( pExpr->op==TK_TRIGGER ){
pTab = pParse->pTriggerTab;
}else{
assert( pTabList );
for(iSrc=0; iSrc<pTabList->nSrc; iSrc++){
if( pExpr->iTable==pTabList->a[iSrc].iCursor ){
pTab = pTabList->a[iSrc].pTab;
break;
}
}
}
iCol = pExpr->iColumn;
if( pTab==0 ) return;
if( iCol>=0 ){
assert( iCol<pTab->nCol );
zCol = pTab->aCol[iCol].zCnName;
}else if( pTab->iPKey>=0 ){
assert( pTab->iPKey<pTab->nCol );
zCol = pTab->aCol[pTab->iPKey].zCnName;
}else{
zCol = "ROWID";
}
assert( iDb>=0 && iDb<pParse->db->nDb );
if( SQLITE_IGNORE==sqlite3AuthReadCol(pParse, pTab->zName, zCol, iDb) ){
pExpr->op = TK_NULL;
}
}
int sqlite3AuthCheck(
Parse *pParse,
int code,
const char *zArg1,
const char *zArg2,
const char *zArg3
){
sqlite3 *db = pParse->db;
int rc;
assert( !IN_RENAME_OBJECT || db->xAuth==0 );
if( db->xAuth==0 || db->init.busy || IN_SPECIAL_PARSE ){
return SQLITE_OK;
}
testcase( zArg1==0 );
testcase( zArg2==0 );
testcase( zArg3==0 );
testcase( pParse->zAuthContext==0 );
rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext
#ifdef SQLITE_USER_AUTHENTICATION
,db->auth.zAuthUser
#endif
);
if( rc==SQLITE_DENY ){
sqlite3ErrorMsg(pParse, "not authorized");
pParse->rc = SQLITE_AUTH;
}else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){
rc = SQLITE_DENY;
sqliteAuthBadReturnCode(pParse);
}
return rc;
}
void sqlite3AuthContextPush(
Parse *pParse,
AuthContext *pContext,
const char *zContext
){
assert( pParse );
pContext->pParse = pParse;
pContext->zAuthContext = pParse->zAuthContext;
pParse->zAuthContext = zContext;
}
void sqlite3AuthContextPop(AuthContext *pContext){
if( pContext->pParse ){
pContext->pParse->zAuthContext = pContext->zAuthContext;
pContext->pParse = 0;
}
}
#endif