diff --git a/manifest b/manifest index 138821de3e..6d1310ea58 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Initial\scheck-in\sof\sthe\scode\sfor\sthe\snew\ssqlite_set_authorizer()\sAPI\sfunction.\nThe\scode\sis\smostly\suntested\sat\sthis\spoint.\s(CVS\s827) -D 2003-01-12T18:02:17 +C Forgot\sto\sinclude\sthe\snew\s"auth.c"\ssource\sfile\sin\sthe\sprevious\scheckin.\s(CVS\s828) +D 2003-01-12T18:07:49 F Makefile.in 6606854b1512f185b8e8c779b8d7fc2750463d64 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -18,6 +18,7 @@ F main.mk 8b10c5df8a21cdd343986a90c75247bafaebb3aa F publish.sh e5b83867d14708ed58cec8cba0a4f201e969474d F spec.template 238f7db425a78dc1bb7682e56e3834c7270a3f5e F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea +F src/auth.c 1ba84533dedc0aff1697bdea0bd63844bed49c48 F src/btree.c 131b5903f66e148f0f9af0cedd1c6654932c4e04 F src/btree.h 17710339f7a8f46e3c7d6d0d4648ef19c584ffda F src/build.c 3136d7fc765cc2feee2ad987bac1c1696fdc0f0e @@ -152,7 +153,7 @@ F www/speed.tcl a20a792738475b68756ea7a19321600f23d1d803 F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P 0deaf563fd9784bf0795107cd10e6b3269dfecea -R 0161ffe233937639f6afc181720e6e82 +P 52d5007f64d0af5286b2a0e1f0b9e53c86bece3f +R 1a3038845af2798949c6e7c2b6282e0e U drh -Z 0354e92c05e165e223123b5629b1da94 +Z ce72280da87725f92833f0d83598931c diff --git a/manifest.uuid b/manifest.uuid index 5d2e3fb99a..8456bf254c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -52d5007f64d0af5286b2a0e1f0b9e53c86bece3f \ No newline at end of file +7601916419489879fe963c83010b452c49ef063f \ No newline at end of file diff --git a/src/auth.c b/src/auth.c new file mode 100644 index 0000000000..92782b85a5 --- /dev/null +++ b/src/auth.c @@ -0,0 +1,215 @@ +/* +** 2003 January 11 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains code used to implement the sqlite_set_authorizer() +** API. This facility is an optional feature of the library. Embedded +** systems that do not need this facility may omit it by recompiling +** the library with -DSQLITE_OMIT_AUTHORIZATION=1 +** +** $Id: auth.c,v 1.1 2003/01/12 18:07:49 drh Exp $ +*/ +#include "sqliteInt.h" + +/* +** All of the code in this file may be omitted by defining a single +** macro. +*/ +#ifndef SQLITE_OMIT_AUTHORIZATION + +/* +** Set or clear the access authorization function. +** +** The access authorization function is be called during the compilation +** phase to verify that the user has read and/or write access permission +** various fields of the database. The first argument to the auth function +** is a copy of the 3rd argument to this routine. The second argument +** to the auth function is one of these constants: +** +** SQLITE_READ_COLUMN +** SQLITE_WRITE_COLUMN +** SQLITE_DELETE_ROW +** SQLITE_INSERT_ROW +** +** The third and fourth arguments to the auth function are the name of +** the table and the column that are being accessed. The auth function +** should return either SQLITE_OK, SQLITE_DENY, or SQLITE_IGNORE. If +** SQLITE_OK is returned, it means that access is allowed. SQLITE_DENY +** means that the SQL statement will never-run - the sqlite_exec() call +** will return with an error. SQLITE_IGNORE means that the SQL statement +** should run but attempts to read the specified column will return NULL +** and attempts to write the column will be ignored. +** +** Setting the auth function to NULL disables this hook. The default +** setting of the auth function is NULL. +*/ +int sqlite_set_authorizer( + sqlite *db, + int (*xAuth)(void*,int,const char*,const char*), + void *pArg +){ + db->xAuth = xAuth; + db->pAuthArg = pArg; + return SQLITE_OK; +} + +/* +** Write an error message into pParse->zErrMsg that explains that the +** user-supplied authorization function returned an illegal value. +*/ +static void sqliteAuthBadReturnCode(Parse *pParse, int rc){ + char zBuf[20]; + sprintf(zBuf, "(%d)", rc); + sqliteSetString(&pParse->zErrMsg, "illegal return value ", zBuf, + " from the authorization function - should to be SQLITE_OK, " + "SQLITE_IGNORE, or SQLITE_DENY", 0); + pParse->nErr++; +} + +/* +** The pExpr should be a TK_COLUMN expression. The table referred to +** is in pTabList with an offset of base. Check to see if it is OK to read +** this particular column. +** +** If the auth function returns SQLITE_IGNORE, change the TK_COLUMN +** instruction into a TK_NULL. If the auth function returns SQLITE_DENY, +** then generate an error. +*/ +void sqliteAuthRead( + Parse *pParse, /* The parser context */ + Expr *pExpr, /* The expression to check authorization on */ + SrcList *pTabList, /* All table that pExpr might refer to */ + int base /* Offset of pTabList relative to pExpr */ +){ + sqlite *db = pParse->db; + int rc; + Table *pTab; + const char *zCol; + if( db->xAuth==0 ) return; + assert( pExpr->op==TK_COLUMN ); + assert( pExpr->iTable>=base && pExpr->iTablenSrc ); + pTab = pTabList->a[pExpr->iTable-base].pTab; + if( pTab==0 ) return; + if( pExpr->iColumn>=0 ){ + assert( pExpr->iColumnnCol ); + zCol = pTab->aCol[pExpr->iColumn].zName; + }else if( pTab->iPKey>=0 ){ + assert( pTab->iPKeynCol ); + zCol = pTab->aCol[pTab->iPKey].zName; + }else{ + zCol = "ROWID"; + } + rc = db->xAuth(db->pAuthArg, SQLITE_READ_COLUMN, pTab->zName, zCol); + if( rc==SQLITE_IGNORE ){ + pExpr->op = TK_NULL; + }else if( rc==SQLITE_DENY ){ + sqliteSetString(&pParse->zErrMsg,"access to ", + pTab->zName, ".", zCol, " is prohibited", 0); + pParse->nErr++; + }else if( rc!=SQLITE_OK ){ + sqliteAuthBadReturnCode(pParse, rc); + } +} + +/* +** Check the user-supplied authorization function to see if it is ok to +** delete rows from the table pTab. Return SQLITE_OK if it is. Return +** SQLITE_IGNORE if deletions should be silently omitted. Return SQLITE_DENY +** if an error is to be reported. In the last case, write the text of +** the error into pParse->zErrMsg. +*/ +int sqliteAuthDelete(Parse *pParse, const char *zName, int forceError){ + sqlite *db = pParse->db; + int rc; + if( db->xAuth==0 ){ + return SQLITE_OK; + } + rc = db->xAuth(db->pAuthArg, SQLITE_DELETE_ROW, zName, ""); + if( rc==SQLITE_DENY || (rc==SQLITE_IGNORE && forceError) ){ + sqliteSetString(&pParse->zErrMsg,"deletion of rows from table ", + zName, " is prohibited", 0); + pParse->nErr++; + }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){ + rc = SQLITE_DENY; + sqliteAuthBadReturnCode(pParse, rc); + } + return rc; +} + +/* +** Check the user-supplied authorization function to see if it is ok to +** insert rows from the table pTab. Return SQLITE_OK if it is. Return +** SQLITE_IGNORE if deletions should be silently omitted. Return SQLITE_DENY +** if an error is to be reported. In the last case, write the text of +** the error into pParse->zErrMsg. +*/ +int sqliteAuthInsert(Parse *pParse, const char *zName, int forceError){ + sqlite *db = pParse->db; + int rc; + if( db->xAuth==0 ){ + return SQLITE_OK; + } + rc = db->xAuth(db->pAuthArg, SQLITE_INSERT_ROW, zName, ""); + if( rc==SQLITE_DENY || (rc==SQLITE_IGNORE && forceError) ){ + sqliteSetString(&pParse->zErrMsg,"insertion of rows from table ", + zName, " is prohibited", 0); + pParse->nErr++; + }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){ + rc = SQLITE_DENY; + sqliteAuthBadReturnCode(pParse, rc); + } + return rc; +} + +/* +** Check to see if it is ok to modify column "j" of table pTab. +** Return SQLITE_OK, SQLITE_IGNORE, or SQLITE_DENY. +*/ +int sqliteAuthWrite(Parse *pParse, Table *pTab, int j){ + sqlite *db = pParse->db; + int rc; + if( db->xAuth==0 ) return SQLITE_OK; + rc = db->xAuth(db->pAuthArg, SQLITE_WRITE_COLUMN, + pTab->zName, pTab->aCol[j].zName); + if( rc==SQLITE_DENY ){ + sqliteSetString(&pParse->zErrMsg, "changes to ", pTab->zName, + ".", pTab->aCol[j].zName, " are prohibited", 0); + pParse->nErr++; + }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){ + sqliteAuthBadReturnCode(pParse, rc); + } + return rc; +} + +/* +** Check to see if it is ok to execute a special command such as +** COPY or VACUUM or ROLLBACK. +*/ +int sqliteAuthCommand(Parse *pParse, const char *zCmd, const char *zArg1){ + sqlite *db = pParse->db; + int rc; + if( db->xAuth==0 ) return SQLITE_OK; + rc = db->xAuth(db->pAuthArg, SQLITE_COMMAND, zCmd, zArg1); + if( rc==SQLITE_DENY ){ + if( zArg1 && zArg1[0] ){ + sqliteSetString(&pParse->zErrMsg, "execution of the ", zCmd, " ", zArg1, + " command is prohibited", 0); + }else{ + sqliteSetString(&pParse->zErrMsg, "execution of the ", zCmd, + " command is prohibited", 0); + } + pParse->nErr++; + }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){ + sqliteAuthBadReturnCode(pParse, rc); + } + return rc; +} + +#endif /* SQLITE_OMIT_AUTHORIZATION */