1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/extensions/sqlite/sqlite-source/auth.c Sun Jul 29 01:15:31 2007 +0000
1.3 @@ -0,0 +1,233 @@
1.4 +/*
1.5 +** 2003 January 11
1.6 +**
1.7 +** The author disclaims copyright to this source code. In place of
1.8 +** a legal notice, here is a blessing:
1.9 +**
1.10 +** May you do good and not evil.
1.11 +** May you find forgiveness for yourself and forgive others.
1.12 +** May you share freely, never taking more than you give.
1.13 +**
1.14 +*************************************************************************
1.15 +** This file contains code used to implement the sqlite3_set_authorizer()
1.16 +** API. This facility is an optional feature of the library. Embedded
1.17 +** systems that do not need this facility may omit it by recompiling
1.18 +** the library with -DSQLITE_OMIT_AUTHORIZATION=1
1.19 +**
1.20 +** $Id$
1.21 +*/
1.22 +#include "sqliteInt.h"
1.23 +
1.24 +/*
1.25 +** All of the code in this file may be omitted by defining a single
1.26 +** macro.
1.27 +*/
1.28 +#ifndef SQLITE_OMIT_AUTHORIZATION
1.29 +
1.30 +/*
1.31 +** Set or clear the access authorization function.
1.32 +**
1.33 +** The access authorization function is be called during the compilation
1.34 +** phase to verify that the user has read and/or write access permission on
1.35 +** various fields of the database. The first argument to the auth function
1.36 +** is a copy of the 3rd argument to this routine. The second argument
1.37 +** to the auth function is one of these constants:
1.38 +**
1.39 +** SQLITE_CREATE_INDEX
1.40 +** SQLITE_CREATE_TABLE
1.41 +** SQLITE_CREATE_TEMP_INDEX
1.42 +** SQLITE_CREATE_TEMP_TABLE
1.43 +** SQLITE_CREATE_TEMP_TRIGGER
1.44 +** SQLITE_CREATE_TEMP_VIEW
1.45 +** SQLITE_CREATE_TRIGGER
1.46 +** SQLITE_CREATE_VIEW
1.47 +** SQLITE_DELETE
1.48 +** SQLITE_DROP_INDEX
1.49 +** SQLITE_DROP_TABLE
1.50 +** SQLITE_DROP_TEMP_INDEX
1.51 +** SQLITE_DROP_TEMP_TABLE
1.52 +** SQLITE_DROP_TEMP_TRIGGER
1.53 +** SQLITE_DROP_TEMP_VIEW
1.54 +** SQLITE_DROP_TRIGGER
1.55 +** SQLITE_DROP_VIEW
1.56 +** SQLITE_INSERT
1.57 +** SQLITE_PRAGMA
1.58 +** SQLITE_READ
1.59 +** SQLITE_SELECT
1.60 +** SQLITE_TRANSACTION
1.61 +** SQLITE_UPDATE
1.62 +**
1.63 +** The third and fourth arguments to the auth function are the name of
1.64 +** the table and the column that are being accessed. The auth function
1.65 +** should return either SQLITE_OK, SQLITE_DENY, or SQLITE_IGNORE. If
1.66 +** SQLITE_OK is returned, it means that access is allowed. SQLITE_DENY
1.67 +** means that the SQL statement will never-run - the sqlite3_exec() call
1.68 +** will return with an error. SQLITE_IGNORE means that the SQL statement
1.69 +** should run but attempts to read the specified column will return NULL
1.70 +** and attempts to write the column will be ignored.
1.71 +**
1.72 +** Setting the auth function to NULL disables this hook. The default
1.73 +** setting of the auth function is NULL.
1.74 +*/
1.75 +int sqlite3_set_authorizer(
1.76 + sqlite3 *db,
1.77 + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
1.78 + void *pArg
1.79 +){
1.80 + db->xAuth = xAuth;
1.81 + db->pAuthArg = pArg;
1.82 + sqlite3ExpirePreparedStatements(db);
1.83 + return SQLITE_OK;
1.84 +}
1.85 +
1.86 +/*
1.87 +** Write an error message into pParse->zErrMsg that explains that the
1.88 +** user-supplied authorization function returned an illegal value.
1.89 +*/
1.90 +static void sqliteAuthBadReturnCode(Parse *pParse, int rc){
1.91 + sqlite3ErrorMsg(pParse, "illegal return value (%d) from the "
1.92 + "authorization function - should be SQLITE_OK, SQLITE_IGNORE, "
1.93 + "or SQLITE_DENY", rc);
1.94 + pParse->rc = SQLITE_ERROR;
1.95 +}
1.96 +
1.97 +/*
1.98 +** The pExpr should be a TK_COLUMN expression. The table referred to
1.99 +** is in pTabList or else it is the NEW or OLD table of a trigger.
1.100 +** Check to see if it is OK to read this particular column.
1.101 +**
1.102 +** If the auth function returns SQLITE_IGNORE, change the TK_COLUMN
1.103 +** instruction into a TK_NULL. If the auth function returns SQLITE_DENY,
1.104 +** then generate an error.
1.105 +*/
1.106 +void sqlite3AuthRead(
1.107 + Parse *pParse, /* The parser context */
1.108 + Expr *pExpr, /* The expression to check authorization on */
1.109 + SrcList *pTabList /* All table that pExpr might refer to */
1.110 +){
1.111 + sqlite3 *db = pParse->db;
1.112 + int rc;
1.113 + Table *pTab; /* The table being read */
1.114 + const char *zCol; /* Name of the column of the table */
1.115 + int iSrc; /* Index in pTabList->a[] of table being read */
1.116 + const char *zDBase; /* Name of database being accessed */
1.117 + TriggerStack *pStack; /* The stack of current triggers */
1.118 + int iDb; /* The index of the database the expression refers to */
1.119 +
1.120 + if( db->xAuth==0 ) return;
1.121 + if( pExpr->op!=TK_COLUMN ) return;
1.122 + iDb = sqlite3SchemaToIndex(pParse->db, pExpr->pSchema);
1.123 + if( iDb<0 ){
1.124 + /* An attempt to read a column out of a subquery or other
1.125 + ** temporary table. */
1.126 + return;
1.127 + }
1.128 + for(iSrc=0; pTabList && iSrc<pTabList->nSrc; iSrc++){
1.129 + if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break;
1.130 + }
1.131 + if( iSrc>=0 && pTabList && iSrc<pTabList->nSrc ){
1.132 + pTab = pTabList->a[iSrc].pTab;
1.133 + }else if( (pStack = pParse->trigStack)!=0 ){
1.134 + /* This must be an attempt to read the NEW or OLD pseudo-tables
1.135 + ** of a trigger.
1.136 + */
1.137 + assert( pExpr->iTable==pStack->newIdx || pExpr->iTable==pStack->oldIdx );
1.138 + pTab = pStack->pTab;
1.139 + }else{
1.140 + return;
1.141 + }
1.142 + if( pTab==0 ) return;
1.143 + if( pExpr->iColumn>=0 ){
1.144 + assert( pExpr->iColumn<pTab->nCol );
1.145 + zCol = pTab->aCol[pExpr->iColumn].zName;
1.146 + }else if( pTab->iPKey>=0 ){
1.147 + assert( pTab->iPKey<pTab->nCol );
1.148 + zCol = pTab->aCol[pTab->iPKey].zName;
1.149 + }else{
1.150 + zCol = "ROWID";
1.151 + }
1.152 + assert( iDb>=0 && iDb<db->nDb );
1.153 + zDBase = db->aDb[iDb].zName;
1.154 + rc = db->xAuth(db->pAuthArg, SQLITE_READ, pTab->zName, zCol, zDBase,
1.155 + pParse->zAuthContext);
1.156 + if( rc==SQLITE_IGNORE ){
1.157 + pExpr->op = TK_NULL;
1.158 + }else if( rc==SQLITE_DENY ){
1.159 + if( db->nDb>2 || iDb!=0 ){
1.160 + sqlite3ErrorMsg(pParse, "access to %s.%s.%s is prohibited",
1.161 + zDBase, pTab->zName, zCol);
1.162 + }else{
1.163 + sqlite3ErrorMsg(pParse, "access to %s.%s is prohibited",pTab->zName,zCol);
1.164 + }
1.165 + pParse->rc = SQLITE_AUTH;
1.166 + }else if( rc!=SQLITE_OK ){
1.167 + sqliteAuthBadReturnCode(pParse, rc);
1.168 + }
1.169 +}
1.170 +
1.171 +/*
1.172 +** Do an authorization check using the code and arguments given. Return
1.173 +** either SQLITE_OK (zero) or SQLITE_IGNORE or SQLITE_DENY. If SQLITE_DENY
1.174 +** is returned, then the error count and error message in pParse are
1.175 +** modified appropriately.
1.176 +*/
1.177 +int sqlite3AuthCheck(
1.178 + Parse *pParse,
1.179 + int code,
1.180 + const char *zArg1,
1.181 + const char *zArg2,
1.182 + const char *zArg3
1.183 +){
1.184 + sqlite3 *db = pParse->db;
1.185 + int rc;
1.186 +
1.187 + /* Don't do any authorization checks if the database is initialising
1.188 + ** or if the parser is being invoked from within sqlite3_declare_vtab.
1.189 + */
1.190 + if( db->init.busy || IN_DECLARE_VTAB ){
1.191 + return SQLITE_OK;
1.192 + }
1.193 +
1.194 + if( db->xAuth==0 ){
1.195 + return SQLITE_OK;
1.196 + }
1.197 + rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext);
1.198 + if( rc==SQLITE_DENY ){
1.199 + sqlite3ErrorMsg(pParse, "not authorized");
1.200 + pParse->rc = SQLITE_AUTH;
1.201 + }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){
1.202 + rc = SQLITE_DENY;
1.203 + sqliteAuthBadReturnCode(pParse, rc);
1.204 + }
1.205 + return rc;
1.206 +}
1.207 +
1.208 +/*
1.209 +** Push an authorization context. After this routine is called, the
1.210 +** zArg3 argument to authorization callbacks will be zContext until
1.211 +** popped. Or if pParse==0, this routine is a no-op.
1.212 +*/
1.213 +void sqlite3AuthContextPush(
1.214 + Parse *pParse,
1.215 + AuthContext *pContext,
1.216 + const char *zContext
1.217 +){
1.218 + pContext->pParse = pParse;
1.219 + if( pParse ){
1.220 + pContext->zAuthContext = pParse->zAuthContext;
1.221 + pParse->zAuthContext = zContext;
1.222 + }
1.223 +}
1.224 +
1.225 +/*
1.226 +** Pop an authorization context that was previously pushed
1.227 +** by sqlite3AuthContextPush
1.228 +*/
1.229 +void sqlite3AuthContextPop(AuthContext *pContext){
1.230 + if( pContext->pParse ){
1.231 + pContext->pParse->zAuthContext = pContext->zAuthContext;
1.232 + pContext->pParse = 0;
1.233 + }
1.234 +}
1.235 +
1.236 +#endif /* SQLITE_OMIT_AUTHORIZATION */