1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-29 08:01:23 +03:00

Update the authorizer API so that it reports the database that table and

indices belong to and so that it reports when actions are taken in response
to a trigger. (CVS 928)

FossilOrigin-Name: c675a5504138f34cae6def782b5d3add2c67d2bc
This commit is contained in:
drh
2003-04-22 20:30:37 +00:00
parent 3837237959
commit e22a334b78
18 changed files with 541 additions and 453 deletions

View File

@ -14,7 +14,7 @@
** systems that do not need this facility may omit it by recompiling
** the library with -DSQLITE_OMIT_AUTHORIZATION=1
**
** $Id: auth.c,v 1.5 2003/04/16 20:24:52 drh Exp $
** $Id: auth.c,v 1.6 2003/04/22 20:30:38 drh Exp $
*/
#include "sqliteInt.h"
@ -52,7 +52,7 @@
*/
int sqlite_set_authorizer(
sqlite *db,
int (*xAuth)(void*,int,const char*,const char*),
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
void *pArg
){
db->xAuth = xAuth;
@ -94,7 +94,12 @@ void sqliteAuthRead(
Table *pTab; /* The table being read */
const char *zCol; /* Name of the column of the table */
int iSrc; /* Index in pTabList->a[] of table being read */
const char *zDBase; /* Name of database being accessed */
const char *zTrig; /* Name of the trigger doing the accessing */
TriggerStack *pStack; /* The stack of current triggers */
pStack = pParse->trigStack;
zTrig = pStack ? pStack->pTrigger->name : 0;
if( db->xAuth==0 ) return;
assert( pExpr->op==TK_COLUMN );
iSrc = pExpr->iTable - base;
@ -104,7 +109,6 @@ void sqliteAuthRead(
/* This must be an attempt to read the NEW or OLD pseudo-tables
** of a trigger.
*/
TriggerStack *pStack = pParse->trigStack;
assert( pStack!=0 );
assert( pExpr->iTable==pStack->newIdx || pExpr->iTable==pStack->oldIdx );
pTab = pStack->pTab;
@ -119,12 +123,19 @@ void sqliteAuthRead(
}else{
zCol = "ROWID";
}
rc = db->xAuth(db->pAuthArg, SQLITE_READ, pTab->zName, zCol);
assert( pExpr->iDb>=0 && pExpr->iDb<db->nDb );
zDBase = db->aDb[pExpr->iDb].zName;
rc = db->xAuth(db->pAuthArg, SQLITE_READ, pTab->zName, zCol, zDBase, zTrig);
if( rc==SQLITE_IGNORE ){
pExpr->op = TK_NULL;
}else if( rc==SQLITE_DENY ){
sqliteSetString(&pParse->zErrMsg,"access to ",
pTab->zName, ".", zCol, " is prohibited", 0);
if( db->nDb>2 || pExpr->iDb!=0 ){
sqliteSetString(&pParse->zErrMsg,"access to ", zDBase, ".",
pTab->zName, ".", zCol, " is prohibited", 0);
}else{
sqliteSetString(&pParse->zErrMsg,"access to ", pTab->zName, ".",
zCol, " is prohibited", 0);
}
pParse->nErr++;
pParse->rc = SQLITE_AUTH;
}else if( rc!=SQLITE_OK ){
@ -142,14 +153,18 @@ int sqliteAuthCheck(
Parse *pParse,
int code,
const char *zArg1,
const char *zArg2
const char *zArg2,
const char *zArg3
){
sqlite *db = pParse->db;
int rc;
const char *zTrigName;
if( db->xAuth==0 ){
return SQLITE_OK;
}
rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2);
zTrigName = pParse->trigStack ? pParse->trigStack->pTrigger->name : 0;
rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, zTrigName);
if( rc==SQLITE_DENY ){
sqliteSetString(&pParse->zErrMsg, "not authorized", 0);
pParse->rc = SQLITE_AUTH;

View File

@ -23,7 +23,7 @@
** ROLLBACK
** PRAGMA
**
** $Id: build.c,v 1.148 2003/04/21 18:48:46 drh Exp $
** $Id: build.c,v 1.149 2003/04/22 20:30:38 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -453,12 +453,13 @@ void sqliteStartTable(
if( pParse->iDb==1 ) isTemp = 1;
#ifndef SQLITE_OMIT_AUTHORIZATION
assert( (isTemp & 1)==isTemp );
if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0) ){
sqliteFree(zName);
return;
}
{
int code;
char *zDb = isTemp ? "temp" : "main";
if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
sqliteFree(zName);
return;
}
if( isView ){
if( isTemp ){
code = SQLITE_CREATE_TEMP_VIEW;
@ -472,7 +473,7 @@ void sqliteStartTable(
code = SQLITE_CREATE_TABLE;
}
}
if( sqliteAuthCheck(pParse, code, zName, 0) ){
if( sqliteAuthCheck(pParse, code, zName, 0, zDb) ){
sqliteFree(zName);
return;
}
@ -1218,12 +1219,15 @@ void sqliteDropTable(Parse *pParse, Token *pName, int isView){
pTable = sqliteTableFromToken(pParse, pName);
if( pTable==0 ) return;
iDb = pTable->iDb;
assert( iDb>=0 && iDb<db->nDb );
#ifndef SQLITE_OMIT_AUTHORIZATION
if( sqliteAuthCheck(pParse, SQLITE_DELETE, SCHEMA_TABLE(pTable->iDb),0)){
return;
}
{
int code;
const char *zTab = SCHEMA_TABLE(pTable->iDb);
const char *zDb = db->aDb[pTable->iDb].zName;
if( sqliteAuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){
return;
}
if( isView ){
if( iDb==1 ){
code = SQLITE_DROP_TEMP_VIEW;
@ -1237,10 +1241,10 @@ void sqliteDropTable(Parse *pParse, Token *pName, int isView){
code = SQLITE_DROP_TABLE;
}
}
if( sqliteAuthCheck(pParse, code, pTable->zName, 0) ){
if( sqliteAuthCheck(pParse, code, pTable->zName, 0, zDb) ){
return;
}
if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTable->zName, 0) ){
if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTable->zName, 0, zDb) ){
return;
}
}
@ -1600,15 +1604,19 @@ void sqliteCreateIndex(
/* Check for authorization to create an index.
*/
#ifndef SQLITE_OMIT_AUTHORIZATION
assert( isTemp==0 || isTemp==1 );
assert( pTab->iDb==pParse->iDb || isTemp==1 );
if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0) ){
goto exit_create_index;
}
i = SQLITE_CREATE_INDEX;
if( isTemp ) i = SQLITE_CREATE_TEMP_INDEX;
if( sqliteAuthCheck(pParse, i, zName, pTab->zName) ){
goto exit_create_index;
{
const char *zDb = db->aDb[pTab->iDb].zName;
assert( isTemp==0 || isTemp==1 );
assert( pTab->iDb==pParse->iDb || isTemp==1 );
if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
goto exit_create_index;
}
i = SQLITE_CREATE_INDEX;
if( isTemp ) i = SQLITE_CREATE_TEMP_INDEX;
if( sqliteAuthCheck(pParse, i, zName, pTab->zName, zDb) ){
goto exit_create_index;
}
}
#endif
@ -1813,11 +1821,13 @@ void sqliteDropIndex(Parse *pParse, SrcList *pName){
{
int code = SQLITE_DROP_INDEX;
Table *pTab = pIndex->pTable;
if( sqliteAuthCheck(pParse, SQLITE_DELETE, SCHEMA_TABLE(pIndex->iDb), 0) ){
const char *zDb = db->aDb[pIndex->iDb].zName;
const char *zTab = SCHEMA_TABLE(pIndex->iDb);
if( sqliteAuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
goto exit_drop_index;
}
if( pIndex->iDb ) code = SQLITE_DROP_TEMP_INDEX;
if( sqliteAuthCheck(pParse, code, pIndex->zName, pTab->zName) ){
if( sqliteAuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){
goto exit_drop_index;
}
}
@ -2035,7 +2045,7 @@ void sqliteBeginTransaction(Parse *pParse, int onError){
if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
if( pParse->nErr || sqlite_malloc_failed ) return;
if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0) ) return;
if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ) return;
if( db->flags & SQLITE_InTrans ){
sqliteErrorMsg(pParse, "cannot start a transaction within a transaction");
return;
@ -2053,7 +2063,7 @@ void sqliteCommitTransaction(Parse *pParse){
if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
if( pParse->nErr || sqlite_malloc_failed ) return;
if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0) ) return;
if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ) return;
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteErrorMsg(pParse, "cannot commit - no transaction is active");
return;
@ -2072,7 +2082,7 @@ void sqliteRollbackTransaction(Parse *pParse){
if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
if( pParse->nErr || sqlite_malloc_failed ) return;
if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0) ) return;
if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ) return;
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteErrorMsg(pParse, "cannot rollback - no transaction is active");
return;

View File

@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to implement the COPY command.
**
** $Id: copy.c,v 1.2 2003/04/15 19:22:23 drh Exp $
** $Id: copy.c,v 1.3 2003/04/22 20:30:39 drh Exp $
*/
#include "sqliteInt.h"
@ -39,6 +39,7 @@ void sqliteCopy(
int addr, end;
Index *pIdx;
char *zFile = 0;
const char *zDb;
sqlite *db = pParse->db;
@ -48,8 +49,10 @@ void sqliteCopy(
if( pTab==0 || sqliteIsReadOnly(pParse, pTab) ) goto copy_cleanup;
zFile = sqliteStrNDup(pFilename->z, pFilename->n);
sqliteDequote(zFile);
if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, zFile)
|| sqliteAuthCheck(pParse, SQLITE_COPY, pTab->zName, zFile) ){
assert( pTab->iDb>=0 && pTab->iDb<db->nDb );
zDb = db->aDb[pTab->iDb].zName;
if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb)
|| sqliteAuthCheck(pParse, SQLITE_COPY, pTab->zName, zFile, zDb) ){
goto copy_cleanup;
}
v = sqliteGetVdbe(pParse);

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements.
**
** $Id: delete.c,v 1.52 2003/04/17 22:57:53 drh Exp $
** $Id: delete.c,v 1.53 2003/04/22 20:30:39 drh Exp $
*/
#include "sqliteInt.h"
@ -58,6 +58,7 @@ void sqliteDeleteFrom(
){
Vdbe *v; /* The virtual database engine */
Table *pTab; /* The table from which records will be deleted */
const char *zDb; /* Name of database holding pTab */
int end, addr; /* A couple addresses of generated code */
int i; /* Loop counter */
WhereInfo *pWInfo; /* Information about the WHERE clause */
@ -97,7 +98,9 @@ void sqliteDeleteFrom(
}
if( sqliteIsReadOnly(pParse, pTab) ) goto delete_from_cleanup;
assert( pTab->pSelect==0 ); /* This table is not a view */
if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0) ){
assert( pTab->iDb<db->nDb );
zDb = db->aDb[pTab->iDb].zName;
if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
goto delete_from_cleanup;
}

View File

@ -12,7 +12,7 @@
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.93 2003/04/19 17:27:25 drh Exp $
** $Id: expr.c,v 1.94 2003/04/22 20:30:39 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -432,6 +432,8 @@ int sqliteExprResolveIds(
int cnt = 0; /* Number of matches */
int i; /* Loop counter */
char *z;
int iDb = -1;
assert( pExpr->token.z );
z = sqliteStrNDup(pExpr->token.z, pExpr->token.n);
sqliteDequote(z);
@ -440,11 +442,13 @@ int sqliteExprResolveIds(
int j;
Table *pTab = pTabList->a[i].pTab;
if( pTab==0 ) continue;
iDb = pTab->iDb;
assert( pTab->nCol>0 );
for(j=0; j<pTab->nCol; j++){
if( sqliteStrICmp(pTab->aCol[j].zName, z)==0 ){
cnt++;
pExpr->iTable = i + base;
pExpr->iDb = pTab->iDb;
if( j==pTab->iPKey ){
/* Substitute the record number for the INTEGER PRIMARY KEY */
pExpr->iColumn = -1;
@ -470,9 +474,10 @@ int sqliteExprResolveIds(
}
}
}
if( cnt==0 && sqliteIsRowid(z) ){
if( cnt==0 && iDb>=0 && sqliteIsRowid(z) ){
pExpr->iColumn = -1;
pExpr->iTable = base;
pExpr->iDb = iDb;
cnt = 1 + (pTabList->nSrc>1);
pExpr->op = TK_COLUMN;
pExpr->dataType = SQLITE_SO_NUM;
@ -544,11 +549,15 @@ int sqliteExprResolveIds(
continue;
}
}
if( 0==(cntTab++) ) pExpr->iTable = i + base;
if( 0==(cntTab++) ){
pExpr->iTable = i + base;
pExpr->iDb = pTab->iDb;
}
for(j=0; j<pTab->nCol; j++){
if( sqliteStrICmp(pTab->aCol[j].zName, zRight)==0 ){
cnt++;
pExpr->iTable = i + base;
pExpr->iDb = pTab->iDb;
/* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
pExpr->iColumn = j==pTab->iPKey ? -1 : j;
pExpr->dataType = pTab->aCol[j].sortOrder & SQLITE_SO_TYPEMASK;
@ -563,11 +572,15 @@ int sqliteExprResolveIds(
int t = 0;
if( pTriggerStack->newIdx != -1 && sqliteStrICmp("new", zLeft) == 0 ){
pExpr->iTable = pTriggerStack->newIdx;
assert( pTriggerStack->pTab );
pExpr->iDb = pTriggerStack->pTab->iDb;
cntTab++;
t = 1;
}
if( pTriggerStack->oldIdx != -1 && sqliteStrICmp("old", zLeft) == 0 ){
pExpr->iTable = pTriggerStack->oldIdx;
assert( pTriggerStack->pTab );
pExpr->iDb = pTriggerStack->pTab->iDb;
cntTab++;
t = 1;
}

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.80 2003/04/20 17:29:24 drh Exp $
** $Id: insert.c,v 1.81 2003/04/22 20:30:39 drh Exp $
*/
#include "sqliteInt.h"
@ -93,6 +93,7 @@ void sqliteInsert(
){
Table *pTab; /* The table to insert into */
char *zTab; /* Name of the table into which we are inserting */
const char *zDb; /* Name of the database holding this table */
int i, j, idx; /* Loop counters */
Vdbe *v; /* Generate code into this virtual machine */
Index *pIdx; /* For looping over indices of the table */
@ -126,7 +127,9 @@ void sqliteInsert(
if( pTab==0 ){
goto insert_cleanup;
}
if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0) ){
assert( pTab->iDb<db->nDb );
zDb = db->aDb[pTab->iDb].zName;
if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){
goto insert_cleanup;
}

View File

@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
** $Id: pragma.c,v 1.3 2003/04/15 01:19:49 drh Exp $
** $Id: pragma.c,v 1.4 2003/04/22 20:30:39 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -107,7 +107,7 @@ void sqlitePragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){
zRight = sqliteStrNDup(pRight->z, pRight->n);
sqliteDequote(zRight);
}
if( sqliteAuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight) ){
if( sqliteAuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, 0) ){
sqliteFree(zLeft);
sqliteFree(zRight);
return;

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.132 2003/04/17 22:57:54 drh Exp $
** $Id: select.c,v 1.133 2003/04/22 20:30:39 drh Exp $
*/
#include "sqliteInt.h"
@ -1917,7 +1917,7 @@ int sqliteSelect(
int rc = 1; /* Value to return from this function */
if( sqlite_malloc_failed || pParse->nErr || p==0 ) return 1;
if( sqliteAuthCheck(pParse, SQLITE_SELECT, 0, 0) ) return 1;
if( sqliteAuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
/* If there is are a sequence of queries, do the earlier ones first.
*/

View File

@ -12,7 +12,7 @@
** This header file defines the interface that the SQLite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.44 2003/04/03 15:46:04 drh Exp $
** @(#) $Id: sqlite.h.in,v 1.45 2003/04/22 20:30:39 drh Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
@ -513,7 +513,7 @@ int sqlite_aggregate_count(sqlite_func*);
*/
int sqlite_set_authorizer(
sqlite*,
int (*xAuth)(void*,int,const char*,const char*),
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
void *pUserData
);
@ -522,7 +522,10 @@ int sqlite_set_authorizer(
** be one of the values below. These values signify what kind of operation
** is to be authorized. The 3rd and 4th parameters to the authorization
** function will be parameters or NULL depending on which of the following
** codes is used as the second parameter.
** codes is used as the second parameter. The 5th parameter is the name
** of the database ("main", "temp", etc.) if applicable. The 6th parameter
** is the name of the trigger that is responsible for the access attempt,
** or NULL if this access attempt is directly from input SQL code.
**
** Arg-3 Arg-4
*/

View File

@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.177 2003/04/21 18:48:47 drh Exp $
** @(#) $Id: sqliteInt.h,v 1.178 2003/04/22 20:30:39 drh Exp $
*/
#include "config.h"
#include "sqlite.h"
@ -105,6 +105,9 @@
#ifndef UINT8_TYPE
# define UINT8_TYPE unsigned char
#endif
#ifndef INT8_TYPE
# define INT8_TYPE signed char
#endif
#ifndef INTPTR_TYPE
# if SQLITE_PTR_SZ==4
# define INTPTR_TYPE int
@ -115,6 +118,7 @@
typedef UINT32_TYPE u32; /* 4-byte unsigned integer */
typedef UINT16_TYPE u16; /* 2-byte unsigned integer */
typedef UINT8_TYPE u8; /* 1-byte unsigned integer */
typedef INT8_TYPE i8; /* 1-byte signed integer */
typedef INTPTR_TYPE ptr; /* Big enough to hold a pointer */
typedef unsigned INTPTR_TYPE uptr; /* Big enough to hold a pointer */
@ -290,7 +294,8 @@ struct sqlite {
void *pTraceArg; /* Argument to the trace function */
#endif
#ifndef SQLITE_OMIT_AUTHORIZATION
int (*xAuth)(void*,int,const char*,const char*); /* Access Auth function */
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
/* Access authorization function */
void *pAuthArg; /* 1st argument to the access auth function */
#endif
};
@ -580,7 +585,8 @@ struct Token {
struct Expr {
u8 op; /* Operation performed by this node */
u8 dataType; /* Either SQLITE_SO_TEXT or SQLITE_SO_NUM */
u16 flags; /* Various flags. See below */
i8 iDb; /* Database referenced by this expression */
u8 flags; /* Various flags. See below */
Expr *pLeft, *pRight; /* Left and right subnodes */
ExprList *pList; /* A list of expressions used as function arguments
** or in "<expr> IN (<expr-list)" */
@ -953,9 +959,8 @@ struct TriggerStack {
int oldIdx; /* Index of vdbe cursor to "old" temp table */
int orconf; /* Current orconf policy */
int ignoreJump; /* where to jump to for a RAISE(IGNORE) */
Trigger *pTrigger;
TriggerStack *pNext;
Trigger *pTrigger; /* The trigger currently being coded */
TriggerStack *pNext; /* Next trigger down on the trigger stack */
};
/*
@ -1113,7 +1118,7 @@ void sqliteCreateForeignKey(Parse*, IdList*, Token*, IdList*, int);
void sqliteDeferForeignKey(Parse*, int);
#ifndef SQLITE_OMIT_AUTHORIZATION
void sqliteAuthRead(Parse*,Expr*,SrcList*,int);
int sqliteAuthCheck(Parse*,int, const char*, const char*);
int sqliteAuthCheck(Parse*,int, const char*, const char*, const char*);
#else
# define sqliteAuthRead(a,b,c,d)
# define sqliteAuthCheck(a,b,c,d) SQLITE_OK

View File

@ -11,7 +11,7 @@
*************************************************************************
** A TCL Interface to SQLite
**
** $Id: tclsqlite.c,v 1.46 2003/04/03 15:46:04 drh Exp $
** $Id: tclsqlite.c,v 1.47 2003/04/22 20:30:39 drh Exp $
*/
#ifndef NO_TCL /* Omit this whole file if TCL is unavailable */
@ -53,6 +53,7 @@ struct SqliteDb {
char *zBusy; /* The busy callback routine */
char *zBegin; /* The begin-transaction callback routine */
char *zCommit; /* The commit-transaction callback routine */
char *zAuth; /* The authorization callback routine */
SqlFunc *pFunc; /* List of SQL functions */
int rc; /* Return code of most recent sqlite_exec() */
};
@ -268,6 +269,9 @@ static void DbDeleteCmd(void *db){
if( pDb->zCommit ){
Tcl_Free(pDb->zCommit);
}
if( pDb->zAuth ){
Tcl_Free(pDb->zAuth);
}
Tcl_Free((char*)pDb);
}
@ -351,6 +355,76 @@ static void tclSqlFunc(sqlite_func *context, int argc, const char **argv){
sqlite_set_result_string(context, Tcl_GetStringResult(p->interp), -1);
}
}
#ifndef SQLITE_OMIT_AUTHORIZATION
/*
** This is the authentication function. It appends the authentication
** type code and the two arguments to zCmd[] then invokes the result
** on the interpreter. The reply is examined to determine if the
** authentication fails or succeeds.
*/
static int auth_callback(
void *pArg,
int code,
const char *zArg1,
const char *zArg2,
const char *zArg3,
const char *zArg4
){
char *zCode;
Tcl_DString str;
int rc;
const char *zReply;
SqliteDb *pDb = (SqliteDb*)pArg;
switch( code ){
case SQLITE_COPY : zCode="SQLITE_COPY"; break;
case SQLITE_CREATE_INDEX : zCode="SQLITE_CREATE_INDEX"; break;
case SQLITE_CREATE_TABLE : zCode="SQLITE_CREATE_TABLE"; break;
case SQLITE_CREATE_TEMP_INDEX : zCode="SQLITE_CREATE_TEMP_INDEX"; break;
case SQLITE_CREATE_TEMP_TABLE : zCode="SQLITE_CREATE_TEMP_TABLE"; break;
case SQLITE_CREATE_TEMP_TRIGGER: zCode="SQLITE_CREATE_TEMP_TRIGGER"; break;
case SQLITE_CREATE_TEMP_VIEW : zCode="SQLITE_CREATE_TEMP_VIEW"; break;
case SQLITE_CREATE_TRIGGER : zCode="SQLITE_CREATE_TRIGGER"; break;
case SQLITE_CREATE_VIEW : zCode="SQLITE_CREATE_VIEW"; break;
case SQLITE_DELETE : zCode="SQLITE_DELETE"; break;
case SQLITE_DROP_INDEX : zCode="SQLITE_DROP_INDEX"; break;
case SQLITE_DROP_TABLE : zCode="SQLITE_DROP_TABLE"; break;
case SQLITE_DROP_TEMP_INDEX : zCode="SQLITE_DROP_TEMP_INDEX"; break;
case SQLITE_DROP_TEMP_TABLE : zCode="SQLITE_DROP_TEMP_TABLE"; break;
case SQLITE_DROP_TEMP_TRIGGER : zCode="SQLITE_DROP_TEMP_TRIGGER"; break;
case SQLITE_DROP_TEMP_VIEW : zCode="SQLITE_DROP_TEMP_VIEW"; break;
case SQLITE_DROP_TRIGGER : zCode="SQLITE_DROP_TRIGGER"; break;
case SQLITE_DROP_VIEW : zCode="SQLITE_DROP_VIEW"; break;
case SQLITE_INSERT : zCode="SQLITE_INSERT"; break;
case SQLITE_PRAGMA : zCode="SQLITE_PRAGMA"; break;
case SQLITE_READ : zCode="SQLITE_READ"; break;
case SQLITE_SELECT : zCode="SQLITE_SELECT"; break;
case SQLITE_TRANSACTION : zCode="SQLITE_TRANSACTION"; break;
case SQLITE_UPDATE : zCode="SQLITE_UPDATE"; break;
default : zCode="????"; break;
}
Tcl_DStringInit(&str);
Tcl_DStringAppend(&str, pDb->zAuth, -1);
Tcl_DStringAppendElement(&str, zCode);
Tcl_DStringAppendElement(&str, zArg1 ? zArg1 : "");
Tcl_DStringAppendElement(&str, zArg2 ? zArg2 : "");
Tcl_DStringAppendElement(&str, zArg3 ? zArg3 : "");
Tcl_DStringAppendElement(&str, zArg4 ? zArg4 : "");
rc = Tcl_GlobalEval(pDb->interp, Tcl_DStringValue(&str));
Tcl_DStringFree(&str);
zReply = Tcl_GetStringResult(pDb->interp);
if( strcmp(zReply,"SQLITE_OK")==0 ){
rc = SQLITE_OK;
}else if( strcmp(zReply,"SQLITE_DENY")==0 ){
rc = SQLITE_DENY;
}else if( strcmp(zReply,"SQLITE_IGNORE")==0 ){
rc = SQLITE_IGNORE;
}else{
rc = 999;
}
return rc;
}
#endif /* SQLITE_OMIT_AUTHORIZATION */
/*
** The "sqlite" command below creates a new Tcl command for each
@ -369,16 +443,17 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
SqliteDb *pDb = (SqliteDb*)cd;
int choice;
static const char *DB_strs[] = {
"begin_hook", "busy", "changes",
"close", "commit_hook", "complete",
"errorcode", "eval", "function",
"last_insert_rowid", "timeout", 0
"authorizer", "begin_hook", "busy",
"changes", "close", "commit_hook",
"complete", "errorcode", "eval",
"function", "last_insert_rowid", "timeout",
0
};
enum DB_enum {
DB_BEGIN_HOOK, DB_BUSY, DB_CHANGES,
DB_CLOSE, DB_COMMIT_HOOK, DB_COMPLETE,
DB_ERRORCODE, DB_EVAL, DB_FUNCTION,
DB_LAST_INSERT_ROWID, DB_TIMEOUT,
DB_AUTHORIZER, DB_BEGIN_HOOK, DB_BUSY,
DB_CHANGES, DB_CLOSE, DB_COMMIT_HOOK,
DB_COMPLETE, DB_ERRORCODE, DB_EVAL,
DB_FUNCTION, DB_LAST_INSERT_ROWID,DB_TIMEOUT,
};
if( objc<2 ){
@ -391,6 +466,57 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
switch( (enum DB_enum)choice ){
/* $db authorizer ?CALLBACK?
**
** Invoke the given callback to authorize each SQL operation as it is
** compiled. 5 arguments are appended to the callback before it is
** invoked:
**
** (1) The authorization type (ex: SQLITE_CREATE_TABLE, SQLITE_INSERT, ...)
** (2) First descriptive name (depends on authorization type)
** (3) Second descriptive name
** (4) Name of the database (ex: "main", "temp")
** (5) Name of trigger that is doing the access
**
** The callback should return on of the following strings: SQLITE_OK,
** SQLITE_IGNORE, or SQLITE_DENY. Any other return value is an error.
**
** If this method is invoked with no arguments, the current authorization
** callback string is returned.
*/
case DB_AUTHORIZER: {
if( objc>3 ){
Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?");
}else if( objc==2 ){
if( pDb->zBegin ){
Tcl_AppendResult(interp, pDb->zAuth, 0);
}
}else{
char *zAuth;
int len;
if( pDb->zAuth ){
Tcl_Free(pDb->zAuth);
}
zAuth = Tcl_GetStringFromObj(objv[2], &len);
if( zAuth && len>0 ){
pDb->zAuth = Tcl_Alloc( len + 1 );
strcpy(pDb->zAuth, zAuth);
}else{
pDb->zAuth = 0;
}
#ifndef SQLITE_OMIT_AUTHORIZATION
if( pDb->zAuth ){
pDb->interp = interp;
sqlite_set_authorizer(pDb->db, auth_callback, pDb);
}else{
sqlite_set_authorizer(pDb->db, 0, 0);
}
#endif
}
break;
}
/* $db begin_callback ?CALLBACK?
**
** Invoke the given callback at the beginning of every SQL transaction.

View File

@ -13,7 +13,7 @@
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.22 2003/02/16 22:21:32 drh Exp $
** $Id: test1.c,v 1.23 2003/04/22 20:30:40 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
@ -588,125 +588,6 @@ static int sqlite_datatypes(
return TCL_OK;
}
#ifndef SQLITE_OMIT_AUTHORIZATION
/*
** Information used by the authentication function.
*/
typedef struct AuthInfo AuthInfo;
struct AuthInfo {
Tcl_Interp *interp; /* Interpreter to use */
int nCmd; /* Number of characters in zCmd[] */
char zCmd[500]; /* Command to invoke */
};
/*
** We create a single static authenticator. This won't work in a
** multi-threaded environment, but the test fixture is not multithreaded.
** And be making it static, we don't have to worry about deallocating
** after a test in order to void memory leaks.
*/
static AuthInfo authInfo;
/*
** This is the authentication function. It appends the authentication
** type code and the two arguments to zCmd[] then invokes the result
** on the interpreter. The reply is examined to determine if the
** authentication fails or succeeds.
*/
static int auth_callback(
void *NotUsed,
int code,
const char *zArg1,
const char *zArg2
){
char *zCode;
Tcl_DString str;
int rc;
const char *zReply;
switch( code ){
case SQLITE_COPY : zCode="SQLITE_COPY"; break;
case SQLITE_CREATE_INDEX : zCode="SQLITE_CREATE_INDEX"; break;
case SQLITE_CREATE_TABLE : zCode="SQLITE_CREATE_TABLE"; break;
case SQLITE_CREATE_TEMP_INDEX : zCode="SQLITE_CREATE_TEMP_INDEX"; break;
case SQLITE_CREATE_TEMP_TABLE : zCode="SQLITE_CREATE_TEMP_TABLE"; break;
case SQLITE_CREATE_TEMP_TRIGGER: zCode="SQLITE_CREATE_TEMP_TRIGGER"; break;
case SQLITE_CREATE_TEMP_VIEW : zCode="SQLITE_CREATE_TEMP_VIEW"; break;
case SQLITE_CREATE_TRIGGER : zCode="SQLITE_CREATE_TRIGGER"; break;
case SQLITE_CREATE_VIEW : zCode="SQLITE_CREATE_VIEW"; break;
case SQLITE_DELETE : zCode="SQLITE_DELETE"; break;
case SQLITE_DROP_INDEX : zCode="SQLITE_DROP_INDEX"; break;
case SQLITE_DROP_TABLE : zCode="SQLITE_DROP_TABLE"; break;
case SQLITE_DROP_TEMP_INDEX : zCode="SQLITE_DROP_TEMP_INDEX"; break;
case SQLITE_DROP_TEMP_TABLE : zCode="SQLITE_DROP_TEMP_TABLE"; break;
case SQLITE_DROP_TEMP_TRIGGER : zCode="SQLITE_DROP_TEMP_TRIGGER"; break;
case SQLITE_DROP_TEMP_VIEW : zCode="SQLITE_DROP_TEMP_VIEW"; break;
case SQLITE_DROP_TRIGGER : zCode="SQLITE_DROP_TRIGGER"; break;
case SQLITE_DROP_VIEW : zCode="SQLITE_DROP_VIEW"; break;
case SQLITE_INSERT : zCode="SQLITE_INSERT"; break;
case SQLITE_PRAGMA : zCode="SQLITE_PRAGMA"; break;
case SQLITE_READ : zCode="SQLITE_READ"; break;
case SQLITE_SELECT : zCode="SQLITE_SELECT"; break;
case SQLITE_TRANSACTION : zCode="SQLITE_TRANSACTION"; break;
case SQLITE_UPDATE : zCode="SQLITE_UPDATE"; break;
default : zCode="????"; break;
}
Tcl_DStringInit(&str);
Tcl_DStringAppend(&str, authInfo.zCmd, -1);
Tcl_DStringAppendElement(&str, zCode);
Tcl_DStringAppendElement(&str, zArg1 ? zArg1 : "");
Tcl_DStringAppendElement(&str, zArg2 ? zArg2 : "");
rc = Tcl_GlobalEval(authInfo.interp, Tcl_DStringValue(&str));
Tcl_DStringFree(&str);
zReply = Tcl_GetStringResult(authInfo.interp);
if( strcmp(zReply,"SQLITE_OK")==0 ){
rc = SQLITE_OK;
}else if( strcmp(zReply,"SQLITE_DENY")==0 ){
rc = SQLITE_DENY;
}else if( strcmp(zReply,"SQLITE_IGNORE")==0 ){
rc = SQLITE_IGNORE;
}else{
rc = 999;
}
return rc;
}
/*
** This routine creates a new authenticator. It fills in the zCmd[]
** field of the authentication function state variable and then registers
** the authentication function with the SQLite library.
*/
static int test_set_authorizer(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
sqlite *db;
char *zCmd;
if( argc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" DB CALLBACK\"", 0);
return TCL_ERROR;
}
if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
zCmd = argv[2];
if( zCmd[0]==0 ){
sqlite_set_authorizer(db, 0, 0);
return TCL_OK;
}
if( strlen(zCmd)>sizeof(authInfo.zCmd) ){
Tcl_AppendResult(interp, "command too big", 0);
return TCL_ERROR;
}
authInfo.interp = interp;
authInfo.nCmd = strlen(zCmd);
strcpy(authInfo.zCmd, zCmd);
sqlite_set_authorizer(db, auth_callback, 0);
return TCL_OK;
}
#endif /* SQLITE_OMIT_AUTHORIZATION */
/*
** Usage: sqlite_compile DB SQL TAILVAR
**
@ -878,9 +759,6 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func },
{ "sqlite_abort", (Tcl_CmdProc*)sqlite_abort },
{ "sqlite_datatypes", (Tcl_CmdProc*)sqlite_datatypes },
#ifndef SQLITE_OMIT_AUTHORIZATION
{ "sqlite_set_authorizer", (Tcl_CmdProc*)test_set_authorizer },
#endif
#ifdef MEMORY_DEBUG
{ "sqlite_malloc_fail", (Tcl_CmdProc*)sqlite_malloc_fail },
{ "sqlite_malloc_stat", (Tcl_CmdProc*)sqlite_malloc_stat },

View File

@ -98,11 +98,13 @@ void sqliteBeginTrigger(
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int code = SQLITE_CREATE_TRIGGER;
const char *zDb = db->aDb[tab->iDb].zName;
const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb;
if( tab->iDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER;
if( sqliteAuthCheck(pParse, code, zName, tab->zName) ){
if( sqliteAuthCheck(pParse, code, zName, tab->zName, zDbTrig) ){
goto trigger_cleanup;
}
if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(tab->iDb), 0)){
if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(tab->iDb), 0, zDb)){
goto trigger_cleanup;
}
}
@ -397,9 +399,11 @@ void sqliteDropTrigger(Parse *pParse, SrcList *pName, int nested){
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int code = SQLITE_DROP_TRIGGER;
const char *zDb = db->aDb[pTrigger->iDb].zName;
const char *zTab = SCHEMA_TABLE(pTrigger->iDb);
if( pTrigger->iDb ) code = SQLITE_DROP_TEMP_TRIGGER;
if( sqliteAuthCheck(pParse, code, pTrigger->name, pTable->zName) ||
sqliteAuthCheck(pParse, SQLITE_DELETE, SCHEMA_TABLE(pTrigger->iDb),0) ){
if( sqliteAuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) ||
sqliteAuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
goto drop_trigger_cleanup;
}
}

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.61 2003/04/20 17:29:24 drh Exp $
** $Id: update.c,v 1.62 2003/04/22 20:30:40 drh Exp $
*/
#include "sqliteInt.h"
@ -139,7 +139,7 @@ void sqliteUpdate(
{
int rc;
rc = sqliteAuthCheck(pParse, SQLITE_UPDATE, pTab->zName,
pTab->aCol[j].zName);
pTab->aCol[j].zName, db->aDb[pTab->iDb].zName);
if( rc==SQLITE_DENY ){
goto update_cleanup;
}else if( rc==SQLITE_IGNORE ){