extensions/sqlite/sqlite-source/auth.c
author David Anderson <dvander@alliedmods.net>
Sun Oct 28 05:48:06 2007 +0000 (2007-10-28)
changeset 1645 27307df4d711
parent 1203 633c25ce6405
permissions -rw-r--r--
updated to sqlite-3.5.1 now that it's stable
used new shared cache functionality (yay)
dvander@1203
     1
/*
dvander@1203
     2
** 2003 January 11
dvander@1203
     3
**
dvander@1203
     4
** The author disclaims copyright to this source code.  In place of
dvander@1203
     5
** a legal notice, here is a blessing:
dvander@1203
     6
**
dvander@1203
     7
**    May you do good and not evil.
dvander@1203
     8
**    May you find forgiveness for yourself and forgive others.
dvander@1203
     9
**    May you share freely, never taking more than you give.
dvander@1203
    10
**
dvander@1203
    11
*************************************************************************
dvander@1203
    12
** This file contains code used to implement the sqlite3_set_authorizer()
dvander@1203
    13
** API.  This facility is an optional feature of the library.  Embedded
dvander@1203
    14
** systems that do not need this facility may omit it by recompiling
dvander@1203
    15
** the library with -DSQLITE_OMIT_AUTHORIZATION=1
dvander@1203
    16
**
dvander@1203
    17
** $Id$
dvander@1203
    18
*/
dvander@1203
    19
#include "sqliteInt.h"
dvander@1203
    20
dvander@1203
    21
/*
dvander@1203
    22
** All of the code in this file may be omitted by defining a single
dvander@1203
    23
** macro.
dvander@1203
    24
*/
dvander@1203
    25
#ifndef SQLITE_OMIT_AUTHORIZATION
dvander@1203
    26
dvander@1203
    27
/*
dvander@1203
    28
** Set or clear the access authorization function.
dvander@1203
    29
**
dvander@1203
    30
** The access authorization function is be called during the compilation
dvander@1203
    31
** phase to verify that the user has read and/or write access permission on
dvander@1203
    32
** various fields of the database.  The first argument to the auth function
dvander@1203
    33
** is a copy of the 3rd argument to this routine.  The second argument
dvander@1203
    34
** to the auth function is one of these constants:
dvander@1203
    35
**
dvander@1203
    36
**       SQLITE_CREATE_INDEX
dvander@1203
    37
**       SQLITE_CREATE_TABLE
dvander@1203
    38
**       SQLITE_CREATE_TEMP_INDEX
dvander@1203
    39
**       SQLITE_CREATE_TEMP_TABLE
dvander@1203
    40
**       SQLITE_CREATE_TEMP_TRIGGER
dvander@1203
    41
**       SQLITE_CREATE_TEMP_VIEW
dvander@1203
    42
**       SQLITE_CREATE_TRIGGER
dvander@1203
    43
**       SQLITE_CREATE_VIEW
dvander@1203
    44
**       SQLITE_DELETE
dvander@1203
    45
**       SQLITE_DROP_INDEX
dvander@1203
    46
**       SQLITE_DROP_TABLE
dvander@1203
    47
**       SQLITE_DROP_TEMP_INDEX
dvander@1203
    48
**       SQLITE_DROP_TEMP_TABLE
dvander@1203
    49
**       SQLITE_DROP_TEMP_TRIGGER
dvander@1203
    50
**       SQLITE_DROP_TEMP_VIEW
dvander@1203
    51
**       SQLITE_DROP_TRIGGER
dvander@1203
    52
**       SQLITE_DROP_VIEW
dvander@1203
    53
**       SQLITE_INSERT
dvander@1203
    54
**       SQLITE_PRAGMA
dvander@1203
    55
**       SQLITE_READ
dvander@1203
    56
**       SQLITE_SELECT
dvander@1203
    57
**       SQLITE_TRANSACTION
dvander@1203
    58
**       SQLITE_UPDATE
dvander@1203
    59
**
dvander@1203
    60
** The third and fourth arguments to the auth function are the name of
dvander@1203
    61
** the table and the column that are being accessed.  The auth function
dvander@1203
    62
** should return either SQLITE_OK, SQLITE_DENY, or SQLITE_IGNORE.  If
dvander@1203
    63
** SQLITE_OK is returned, it means that access is allowed.  SQLITE_DENY
dvander@1203
    64
** means that the SQL statement will never-run - the sqlite3_exec() call
dvander@1203
    65
** will return with an error.  SQLITE_IGNORE means that the SQL statement
dvander@1203
    66
** should run but attempts to read the specified column will return NULL
dvander@1203
    67
** and attempts to write the column will be ignored.
dvander@1203
    68
**
dvander@1203
    69
** Setting the auth function to NULL disables this hook.  The default
dvander@1203
    70
** setting of the auth function is NULL.
dvander@1203
    71
*/
dvander@1203
    72
int sqlite3_set_authorizer(
dvander@1203
    73
  sqlite3 *db,
dvander@1203
    74
  int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
dvander@1203
    75
  void *pArg
dvander@1203
    76
){
dvander@1645
    77
  sqlite3_mutex_enter(db->mutex);
dvander@1203
    78
  db->xAuth = xAuth;
dvander@1203
    79
  db->pAuthArg = pArg;
dvander@1203
    80
  sqlite3ExpirePreparedStatements(db);
dvander@1645
    81
  sqlite3_mutex_leave(db->mutex);
dvander@1203
    82
  return SQLITE_OK;
dvander@1203
    83
}
dvander@1203
    84
dvander@1203
    85
/*
dvander@1203
    86
** Write an error message into pParse->zErrMsg that explains that the
dvander@1203
    87
** user-supplied authorization function returned an illegal value.
dvander@1203
    88
*/
dvander@1203
    89
static void sqliteAuthBadReturnCode(Parse *pParse, int rc){
dvander@1203
    90
  sqlite3ErrorMsg(pParse, "illegal return value (%d) from the "
dvander@1203
    91
    "authorization function - should be SQLITE_OK, SQLITE_IGNORE, "
dvander@1203
    92
    "or SQLITE_DENY", rc);
dvander@1203
    93
  pParse->rc = SQLITE_ERROR;
dvander@1203
    94
}
dvander@1203
    95
dvander@1203
    96
/*
dvander@1203
    97
** The pExpr should be a TK_COLUMN expression.  The table referred to
dvander@1203
    98
** is in pTabList or else it is the NEW or OLD table of a trigger.  
dvander@1203
    99
** Check to see if it is OK to read this particular column.
dvander@1203
   100
**
dvander@1203
   101
** If the auth function returns SQLITE_IGNORE, change the TK_COLUMN 
dvander@1203
   102
** instruction into a TK_NULL.  If the auth function returns SQLITE_DENY,
dvander@1203
   103
** then generate an error.
dvander@1203
   104
*/
dvander@1203
   105
void sqlite3AuthRead(
dvander@1203
   106
  Parse *pParse,        /* The parser context */
dvander@1203
   107
  Expr *pExpr,          /* The expression to check authorization on */
dvander@1645
   108
  Schema *pSchema,      /* The schema of the expression */
dvander@1203
   109
  SrcList *pTabList     /* All table that pExpr might refer to */
dvander@1203
   110
){
dvander@1203
   111
  sqlite3 *db = pParse->db;
dvander@1203
   112
  int rc;
dvander@1645
   113
  Table *pTab = 0;      /* The table being read */
dvander@1203
   114
  const char *zCol;     /* Name of the column of the table */
dvander@1203
   115
  int iSrc;             /* Index in pTabList->a[] of table being read */
dvander@1203
   116
  const char *zDBase;   /* Name of database being accessed */
dvander@1203
   117
  TriggerStack *pStack; /* The stack of current triggers */
dvander@1203
   118
  int iDb;              /* The index of the database the expression refers to */
dvander@1203
   119
dvander@1203
   120
  if( db->xAuth==0 ) return;
dvander@1203
   121
  if( pExpr->op!=TK_COLUMN ) return;
dvander@1645
   122
  iDb = sqlite3SchemaToIndex(pParse->db, pSchema);
dvander@1203
   123
  if( iDb<0 ){
dvander@1203
   124
    /* An attempt to read a column out of a subquery or other
dvander@1203
   125
    ** temporary table. */
dvander@1203
   126
    return;
dvander@1203
   127
  }
dvander@1203
   128
  for(iSrc=0; pTabList && iSrc<pTabList->nSrc; iSrc++){
dvander@1203
   129
    if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break;
dvander@1203
   130
  }
dvander@1203
   131
  if( iSrc>=0 && pTabList && iSrc<pTabList->nSrc ){
dvander@1203
   132
    pTab = pTabList->a[iSrc].pTab;
dvander@1203
   133
  }else if( (pStack = pParse->trigStack)!=0 ){
dvander@1203
   134
    /* This must be an attempt to read the NEW or OLD pseudo-tables
dvander@1203
   135
    ** of a trigger.
dvander@1203
   136
    */
dvander@1203
   137
    assert( pExpr->iTable==pStack->newIdx || pExpr->iTable==pStack->oldIdx );
dvander@1203
   138
    pTab = pStack->pTab;
dvander@1203
   139
  }
dvander@1203
   140
  if( pTab==0 ) return;
dvander@1203
   141
  if( pExpr->iColumn>=0 ){
dvander@1203
   142
    assert( pExpr->iColumn<pTab->nCol );
dvander@1203
   143
    zCol = pTab->aCol[pExpr->iColumn].zName;
dvander@1203
   144
  }else if( pTab->iPKey>=0 ){
dvander@1203
   145
    assert( pTab->iPKey<pTab->nCol );
dvander@1203
   146
    zCol = pTab->aCol[pTab->iPKey].zName;
dvander@1203
   147
  }else{
dvander@1203
   148
    zCol = "ROWID";
dvander@1203
   149
  }
dvander@1203
   150
  assert( iDb>=0 && iDb<db->nDb );
dvander@1203
   151
  zDBase = db->aDb[iDb].zName;
dvander@1203
   152
  rc = db->xAuth(db->pAuthArg, SQLITE_READ, pTab->zName, zCol, zDBase, 
dvander@1203
   153
                 pParse->zAuthContext);
dvander@1203
   154
  if( rc==SQLITE_IGNORE ){
dvander@1203
   155
    pExpr->op = TK_NULL;
dvander@1203
   156
  }else if( rc==SQLITE_DENY ){
dvander@1203
   157
    if( db->nDb>2 || iDb!=0 ){
dvander@1203
   158
      sqlite3ErrorMsg(pParse, "access to %s.%s.%s is prohibited", 
dvander@1203
   159
         zDBase, pTab->zName, zCol);
dvander@1203
   160
    }else{
dvander@1203
   161
      sqlite3ErrorMsg(pParse, "access to %s.%s is prohibited",pTab->zName,zCol);
dvander@1203
   162
    }
dvander@1203
   163
    pParse->rc = SQLITE_AUTH;
dvander@1203
   164
  }else if( rc!=SQLITE_OK ){
dvander@1203
   165
    sqliteAuthBadReturnCode(pParse, rc);
dvander@1203
   166
  }
dvander@1203
   167
}
dvander@1203
   168
dvander@1203
   169
/*
dvander@1203
   170
** Do an authorization check using the code and arguments given.  Return
dvander@1203
   171
** either SQLITE_OK (zero) or SQLITE_IGNORE or SQLITE_DENY.  If SQLITE_DENY
dvander@1203
   172
** is returned, then the error count and error message in pParse are
dvander@1203
   173
** modified appropriately.
dvander@1203
   174
*/
dvander@1203
   175
int sqlite3AuthCheck(
dvander@1203
   176
  Parse *pParse,
dvander@1203
   177
  int code,
dvander@1203
   178
  const char *zArg1,
dvander@1203
   179
  const char *zArg2,
dvander@1203
   180
  const char *zArg3
dvander@1203
   181
){
dvander@1203
   182
  sqlite3 *db = pParse->db;
dvander@1203
   183
  int rc;
dvander@1203
   184
dvander@1203
   185
  /* Don't do any authorization checks if the database is initialising
dvander@1203
   186
  ** or if the parser is being invoked from within sqlite3_declare_vtab.
dvander@1203
   187
  */
dvander@1203
   188
  if( db->init.busy || IN_DECLARE_VTAB ){
dvander@1203
   189
    return SQLITE_OK;
dvander@1203
   190
  }
dvander@1203
   191
dvander@1203
   192
  if( db->xAuth==0 ){
dvander@1203
   193
    return SQLITE_OK;
dvander@1203
   194
  }
dvander@1203
   195
  rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext);
dvander@1203
   196
  if( rc==SQLITE_DENY ){
dvander@1203
   197
    sqlite3ErrorMsg(pParse, "not authorized");
dvander@1203
   198
    pParse->rc = SQLITE_AUTH;
dvander@1203
   199
  }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){
dvander@1203
   200
    rc = SQLITE_DENY;
dvander@1203
   201
    sqliteAuthBadReturnCode(pParse, rc);
dvander@1203
   202
  }
dvander@1203
   203
  return rc;
dvander@1203
   204
}
dvander@1203
   205
dvander@1203
   206
/*
dvander@1203
   207
** Push an authorization context.  After this routine is called, the
dvander@1203
   208
** zArg3 argument to authorization callbacks will be zContext until
dvander@1203
   209
** popped.  Or if pParse==0, this routine is a no-op.
dvander@1203
   210
*/
dvander@1203
   211
void sqlite3AuthContextPush(
dvander@1203
   212
  Parse *pParse,
dvander@1203
   213
  AuthContext *pContext, 
dvander@1203
   214
  const char *zContext
dvander@1203
   215
){
dvander@1203
   216
  pContext->pParse = pParse;
dvander@1203
   217
  if( pParse ){
dvander@1203
   218
    pContext->zAuthContext = pParse->zAuthContext;
dvander@1203
   219
    pParse->zAuthContext = zContext;
dvander@1203
   220
  }
dvander@1203
   221
}
dvander@1203
   222
dvander@1203
   223
/*
dvander@1203
   224
** Pop an authorization context that was previously pushed
dvander@1203
   225
** by sqlite3AuthContextPush
dvander@1203
   226
*/
dvander@1203
   227
void sqlite3AuthContextPop(AuthContext *pContext){
dvander@1203
   228
  if( pContext->pParse ){
dvander@1203
   229
    pContext->pParse->zAuthContext = pContext->zAuthContext;
dvander@1203
   230
    pContext->pParse = 0;
dvander@1203
   231
  }
dvander@1203
   232
}
dvander@1203
   233
dvander@1203
   234
#endif /* SQLITE_OMIT_AUTHORIZATION */