/ Check-in [45de93f9]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Revise the sqlite_set_authorizer API to provide more detailed information about the SQL statement being authorized. Only partially tested so far. (CVS 830)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 45de93f913a18026a45de6254963dbcd1b0f1a19
User & Date: drh 2003-01-13 23:27:32
References
2013-05-06
13:03 New ticket [0eb70d77] Invalid pointer passed to the authorizer callback. artifact: 6ec5e901 user: drh
Context
2003-01-14
00:44
Make the GLOB work write with upper-case characters. Ticket #226. (CVS 831) check-in: 7ea46e70 user: drh tags: trunk
2003-01-13
23:27
Revise the sqlite_set_authorizer API to provide more detailed information about the SQL statement being authorized. Only partially tested so far. (CVS 830) check-in: 45de93f9 user: drh tags: trunk
2003-01-12
19:33
The initial round of tests for the sqlite_set_authorizer() API. More are needed before release. Ticket #215. (CVS 829) check-in: 5707b3d5 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/auth.c.

    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains code used to implement the sqlite_set_authorizer()
    13     13   ** API.  This facility is an optional feature of the library.  Embedded
    14     14   ** systems that do not need this facility may omit it by recompiling
    15     15   ** the library with -DSQLITE_OMIT_AUTHORIZATION=1
    16     16   **
    17         -** $Id: auth.c,v 1.2 2003/01/12 19:33:53 drh Exp $
           17  +** $Id: auth.c,v 1.3 2003/01/13 23:27:32 drh Exp $
    18     18   */
    19     19   #include "sqliteInt.h"
    20     20   
    21     21   /*
    22     22   ** All of the code in this file may be omitted by defining a single
    23     23   ** macro.
    24     24   */
................................................................................
   102    102       zCol = pTab->aCol[pExpr->iColumn].zName;
   103    103     }else if( pTab->iPKey>=0 ){
   104    104       assert( pTab->iPKey<pTab->nCol );
   105    105       zCol = pTab->aCol[pTab->iPKey].zName;
   106    106     }else{
   107    107       zCol = "ROWID";
   108    108     }
   109         -  rc = db->xAuth(db->pAuthArg, SQLITE_READ_COLUMN, pTab->zName, zCol);
          109  +  rc = db->xAuth(db->pAuthArg, SQLITE_READ, pTab->zName, zCol);
   110    110     if( rc==SQLITE_IGNORE ){
   111    111       pExpr->op = TK_NULL;
   112    112     }else if( rc==SQLITE_DENY ){
   113    113       sqliteSetString(&pParse->zErrMsg,"access to ",
   114    114           pTab->zName, ".", zCol, " is prohibited", 0);
   115    115       pParse->nErr++;
   116    116     }else if( rc!=SQLITE_OK ){
   117    117       sqliteAuthBadReturnCode(pParse, rc);
   118    118     }
   119    119   }
   120    120   
   121    121   /*
   122         -** Check the user-supplied authorization function to see if it is ok to
   123         -** delete rows from the table pTab.  Return SQLITE_OK if it is.  Return
   124         -** SQLITE_IGNORE if deletions should be silently omitted.  Return SQLITE_DENY
   125         -** if an error is to be reported.  In the last case, write the text of
   126         -** the error into pParse->zErrMsg.
          122  +** Do an authorization check using the code and arguments given.  Return
          123  +** either SQLITE_OK (zero) or SQLITE_IGNORE or SQLITE_DENY.  If SQLITE_DENY
          124  +** is returned, then the error count and error message in pParse are
          125  +** modified appropriately.
   127    126   */
   128         -int sqliteAuthDelete(Parse *pParse, const char *zName, int forceError){
   129         -  sqlite *db = pParse->db;
   130         -  int rc;
   131         -  if( db->xAuth==0 ){
   132         -    return SQLITE_OK;
   133         -  }
   134         -  rc = db->xAuth(db->pAuthArg, SQLITE_DELETE_ROW, zName, "");
   135         -  if( rc==SQLITE_DENY  || (rc==SQLITE_IGNORE && forceError) ){
   136         -    sqliteSetString(&pParse->zErrMsg,"deletion from table ",
   137         -        zName, " is prohibited", 0);
   138         -    pParse->nErr++;
   139         -  }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){
   140         -    rc = SQLITE_DENY;
   141         -    sqliteAuthBadReturnCode(pParse, rc);
   142         -  }
   143         -  return rc;
   144         -}
   145         -
   146         -/*
   147         -** Check the user-supplied authorization function to see if it is ok to
   148         -** insert rows from the table pTab.  Return SQLITE_OK if it is.  Return
   149         -** SQLITE_IGNORE if deletions should be silently omitted.  Return SQLITE_DENY
   150         -** if an error is to be reported.  In the last case, write the text of
   151         -** the error into pParse->zErrMsg.
   152         -*/
   153         -int sqliteAuthInsert(Parse *pParse, const char *zName, int forceError){
          127  +int sqliteAuthCheck(
          128  +  Parse *pParse,
          129  +  int code,
          130  +  const char *zArg1,
          131  +  const char *zArg2
          132  +){
   154    133     sqlite *db = pParse->db;
   155    134     int rc;
   156    135     if( db->xAuth==0 ){
   157    136       return SQLITE_OK;
   158    137     }
   159         -  rc = db->xAuth(db->pAuthArg, SQLITE_INSERT_ROW, zName, "");
   160         -  if( rc==SQLITE_DENY || (rc==SQLITE_IGNORE && forceError) ){
   161         -    sqliteSetString(&pParse->zErrMsg,"insertion into table ",
   162         -        zName, " is prohibited", 0);
          138  +  rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2);
          139  +  if( rc==SQLITE_DENY ){
          140  +    sqliteSetString(&pParse->zErrMsg, "not authorized", 0);
   163    141       pParse->nErr++;
   164    142     }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){
   165    143       rc = SQLITE_DENY;
   166    144       sqliteAuthBadReturnCode(pParse, rc);
   167    145     }
   168         -  return rc;
   169         -}
   170         -
   171         -/*
   172         -** Check to see if it is ok to modify column "j" of table pTab.
   173         -** Return SQLITE_OK, SQLITE_IGNORE, or SQLITE_DENY.
   174         -*/
   175         -int sqliteAuthWrite(Parse *pParse, Table *pTab, int j){
   176         -  sqlite *db = pParse->db;
   177         -  int rc;
   178         -  if( db->xAuth==0 ) return SQLITE_OK;
   179         -  rc = db->xAuth(db->pAuthArg, SQLITE_WRITE_COLUMN,
   180         -                    pTab->zName, pTab->aCol[j].zName);
   181         -  if( rc==SQLITE_DENY ){
   182         -      sqliteSetString(&pParse->zErrMsg, "changes to ", pTab->zName,
   183         -          ".", pTab->aCol[j].zName, " are prohibited", 0);
   184         -      pParse->nErr++;
   185         -  }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){
   186         -    sqliteAuthBadReturnCode(pParse, rc);
   187         -  }
   188         -  return rc;
   189         -}
   190         -
   191         -/*
   192         -** Check to see if it is ok to execute a special command such as
   193         -** COPY or VACUUM or ROLLBACK.
   194         -*/
   195         -int sqliteAuthCommand(Parse *pParse, const char *zCmd, const char *zArg1){
   196         -  sqlite *db = pParse->db;
   197         -  int rc;
   198         -  if( db->xAuth==0 ) return SQLITE_OK;
   199         -  rc = db->xAuth(db->pAuthArg, SQLITE_COMMAND, zCmd, zArg1);
   200         -  if( rc==SQLITE_DENY ){
   201         -    if( zArg1 && zArg1[0] ){
   202         -      sqliteSetString(&pParse->zErrMsg, "execution of the ", zCmd, " ", zArg1,
   203         -          " command is prohibited", 0);
   204         -    }else{
   205         -      sqliteSetString(&pParse->zErrMsg, "execution of the ", zCmd,
   206         -          " command is prohibited", 0);
   207         -    }
   208         -    pParse->nErr++;
   209         -  }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){
   210         -    sqliteAuthBadReturnCode(pParse, rc);
   211         -  }
   212    146     return rc;
   213    147   }
   214    148   
   215    149   #endif /* SQLITE_OMIT_AUTHORIZATION */

Changes to src/build.c.

    21     21   **     COPY
    22     22   **     VACUUM
    23     23   **     BEGIN TRANSACTION
    24     24   **     COMMIT
    25     25   **     ROLLBACK
    26     26   **     PRAGMA
    27     27   **
    28         -** $Id: build.c,v 1.120 2003/01/12 18:02:17 drh Exp $
           28  +** $Id: build.c,v 1.121 2003/01/13 23:27:32 drh Exp $
    29     29   */
    30     30   #include "sqliteInt.h"
    31     31   #include <ctype.h>
    32     32   
    33     33   /*
    34     34   ** This routine is called when a new SQL statement is beginning to
    35     35   ** be parsed.  Check to see if the schema for the database needs
................................................................................
   311    311   **
   312    312   ** The new table record is initialized and put in pParse->pNewTable.
   313    313   ** As more of the CREATE TABLE statement is parsed, additional action
   314    314   ** routines will be called to add more information to this record.
   315    315   ** At the end of the CREATE TABLE statement, the sqliteEndTable() routine
   316    316   ** is called to complete the construction of the new table record.
   317    317   */
   318         -void sqliteStartTable(Parse *pParse, Token *pStart, Token *pName, int isTemp){
          318  +void sqliteStartTable(
          319  +  Parse *pParse,   /* Parser context */
          320  +  Token *pStart,   /* The "CREATE" token */
          321  +  Token *pName,    /* Name of table or view to create */
          322  +  int isTemp,      /* True if this is a TEMP table */
          323  +  int isView       /* True if this is a VIEW */
          324  +){
   319    325     Table *pTable;
   320    326     Index *pIdx;
   321    327     char *zName;
   322    328     sqlite *db = pParse->db;
   323    329     Vdbe *v;
   324    330   
   325    331     pParse->sFirstToken = *pStart;
   326    332     zName = sqliteTableNameFromToken(pName);
   327    333     if( zName==0 ) return;
   328         -  if( sqliteAuthInsert(pParse, SCHEMA_TABLE(isTemp), 1) ){
          334  +#ifndef SQLITE_OMIT_AUTHORIZATION
          335  +  if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0) ){
   329    336       return;
   330    337     }
          338  +  {
          339  +    int code;
          340  +    if( isView ){
          341  +      if( isTemp ){
          342  +        code = SQLITE_CREATE_TEMP_VIEW;
          343  +      }else{
          344  +        code = SQLITE_CREATE_VIEW;
          345  +      }
          346  +    }else{
          347  +      if( isTemp ){
          348  +        code = SQLITE_CREATE_TEMP_TABLE;
          349  +      }else{
          350  +        code = SQLITE_CREATE_TABLE;
          351  +      }
          352  +    }
          353  +    if( sqliteAuthCheck(pParse, code, zName, 0) ){
          354  +      return;
          355  +    }
          356  +  }
          357  +#endif
          358  + 
   331    359   
   332    360     /* Before trying to create a temporary table, make sure the Btree for
   333    361     ** holding temporary tables is open.
   334    362     */
   335    363     if( isTemp && db->pBeTemp==0 ){
   336    364       int rc = sqliteBtreeOpen(0, 0, MAX_PAGES, &db->pBeTemp);
   337    365       if( rc!=SQLITE_OK ){
................................................................................
   891    919     int isTemp         /* TRUE for a TEMPORARY view */
   892    920   ){
   893    921     Table *p;
   894    922     int n;
   895    923     const char *z;
   896    924     Token sEnd;
   897    925   
   898         -  sqliteStartTable(pParse, pBegin, pName, isTemp);
          926  +  sqliteStartTable(pParse, pBegin, pName, isTemp, 1);
   899    927     p = pParse->pNewTable;
   900    928     if( p==0 || pParse->nErr ){
   901    929       sqliteSelectDelete(pSelect);
   902    930       return;
   903    931     }
   904    932   
   905    933     /* Make a copy of the entire SELECT statement that defines the view.
................................................................................
  1068   1096     Vdbe *v;
  1069   1097     int base;
  1070   1098     sqlite *db = pParse->db;
  1071   1099   
  1072   1100     if( pParse->nErr || sqlite_malloc_failed ) return;
  1073   1101     pTable = sqliteTableFromToken(pParse, pName);
  1074   1102     if( pTable==0 ) return;
  1075         -  if( sqliteAuthDelete(pParse, SCHEMA_TABLE(pTable->isTemp), 1) ){
         1103  +#ifndef SQLITE_OMIT_AUTHORIZATION
         1104  +  if( sqliteAuthCheck(pParse, SQLITE_DELETE, SCHEMA_TABLE(pTable->isTemp),0)){
  1076   1105       return;
  1077   1106     }
         1107  +  {
         1108  +    int code;
         1109  +    if( isView ){
         1110  +      if( pTable->isTemp ){
         1111  +        code = SQLITE_DROP_TEMP_VIEW;
         1112  +      }else{
         1113  +        code = SQLITE_DROP_VIEW;
         1114  +      }
         1115  +    }else{
         1116  +      if( pTable->isTemp ){
         1117  +        code = SQLITE_DROP_TEMP_TABLE;
         1118  +      }else{
         1119  +        code = SQLITE_DROP_TABLE;
         1120  +      }
         1121  +    }
         1122  +    if( sqliteAuthCheck(pParse, code, pTable->zName, 0) ){
         1123  +      return;
         1124  +    }
         1125  +  }
         1126  +#endif
  1078   1127     if( pTable->readOnly ){
  1079   1128       sqliteSetString(&pParse->zErrMsg, "table ", pTable->zName, 
  1080   1129          " may not be dropped", 0);
  1081   1130       pParse->nErr++;
  1082   1131       return;
  1083   1132     }
  1084   1133     if( isView && pTable->pSelect==0 ){
................................................................................
  1089   1138     }
  1090   1139     if( !isView && pTable->pSelect ){
  1091   1140       sqliteSetString(&pParse->zErrMsg, "use DROP VIEW to delete view ",
  1092   1141         pTable->zName, 0);
  1093   1142       pParse->nErr++;
  1094   1143       return;
  1095   1144     }
  1096         -  if( sqliteAuthDelete(pParse, pTable->zName, 1) ){
  1097         -    return;
  1098         -  }
  1099   1145   
  1100   1146     /* Generate code to remove the table from the master table
  1101   1147     ** on disk.
  1102   1148     */
  1103   1149     v = sqliteGetVdbe(pParse);
  1104   1150     if( v ){
  1105   1151       static VdbeOp dropTable[] = {
................................................................................
  1370   1416       goto exit_create_index;
  1371   1417     }
  1372   1418     if( pTab->pSelect ){
  1373   1419       sqliteSetString(&pParse->zErrMsg, "views may not be indexed", 0);
  1374   1420       pParse->nErr++;
  1375   1421       goto exit_create_index;
  1376   1422     }
  1377         -  if( sqliteAuthInsert(pParse, SCHEMA_TABLE(pTab->isTemp), 1) ){
  1378         -    goto exit_create_index;
  1379         -  }
  1380   1423   
  1381   1424     /* If this index is created while re-reading the schema from sqlite_master
  1382   1425     ** but the table associated with this index is a temporary table, it can
  1383   1426     ** only mean that the table that this index is really associated with is
  1384   1427     ** one whose name is hidden behind a temporary table with the same name.
  1385   1428     ** Since its table has been suppressed, we need to also suppress the
  1386   1429     ** index.
................................................................................
  1436   1479       for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){}
  1437   1480       sprintf(zBuf,"%d)",n);
  1438   1481       zName = 0;
  1439   1482       sqliteSetString(&zName, "(", pTab->zName, " autoindex ", zBuf, 0);
  1440   1483       if( zName==0 ) goto exit_create_index;
  1441   1484       hideName = sqliteFindIndex(db, zName)!=0;
  1442   1485     }
         1486  +
         1487  +  /* Check for authorization to create an index.
         1488  +  */
         1489  +#ifndef SQLITE_OMIT_AUTHORIZATION
         1490  +  if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(pTab->isTemp), 0) ){
         1491  +    goto exit_create_index;
         1492  +  }
         1493  +  i = SQLITE_CREATE_INDEX;
         1494  +  if( pTab->isTemp ) i = SQLITE_CREATE_TEMP_INDEX;
         1495  +  if( sqliteAuthCheck(pParse, i, zName, pTab->zName) ){
         1496  +    goto exit_create_index;
         1497  +  }
         1498  +#endif
  1443   1499   
  1444   1500     /* If pList==0, it means this routine was called to make a primary
  1445   1501     ** key out of the last column added to the table under construction.
  1446   1502     ** So create a fake list to simulate this.
  1447   1503     */
  1448   1504     if( pList==0 ){
  1449   1505       nullId.z = pTab->aCol[pTab->nCol-1].zName;
................................................................................
  1634   1690     }
  1635   1691     if( pIndex->autoIndex ){
  1636   1692       sqliteSetString(&pParse->zErrMsg, "index associated with UNIQUE "
  1637   1693         "or PRIMARY KEY constraint cannot be dropped", 0);
  1638   1694       pParse->nErr++;
  1639   1695       return;
  1640   1696     }
  1641         -  if( sqliteAuthDelete(pParse, SCHEMA_TABLE(pIndex->pTable->isTemp), 1) ){
  1642         -    return;
         1697  +#ifndef SQLITE_OMIT_AUTHORIZATION
         1698  +  {
         1699  +    int code = SQLITE_DROP_INDEX;
         1700  +    Table *pTab = pIndex->pTable;
         1701  +    if( sqliteAuthCheck(pParse, SQLITE_DELETE, SCHEMA_TABLE(pTab->isTemp), 0) ){
         1702  +      return;
         1703  +    }
         1704  +    if( pTab->isTemp ) code = SQLITE_DROP_TEMP_INDEX;
         1705  +    if( sqliteAuthCheck(pParse, code, pIndex->zName, 0) ){
         1706  +      return;
         1707  +    }
  1643   1708     }
         1709  +#endif
  1644   1710   
  1645   1711     /* Generate code to remove the index and from the master table */
  1646   1712     v = sqliteGetVdbe(pParse);
  1647   1713     if( v ){
  1648   1714       static VdbeOp dropIndex[] = {
  1649   1715         { OP_Rewind,     0, ADDR(9), 0}, 
  1650   1716         { OP_String,     0, 0,       0}, /* 1 */
................................................................................
  1833   1899     sqlite *db = pParse->db;
  1834   1900   
  1835   1901     zTab = sqliteTableNameFromToken(pTableName);
  1836   1902     if( sqlite_malloc_failed || zTab==0 ) goto copy_cleanup;
  1837   1903     pTab = sqliteTableNameToTable(pParse, zTab);
  1838   1904     sqliteFree(zTab);
  1839   1905     if( pTab==0 ) goto copy_cleanup;
  1840         -  if( sqliteAuthInsert(pParse, zTab, 0) ){
  1841         -    goto copy_cleanup;
  1842         -  }
  1843         -  if( sqliteAuthCommand(pParse, "COPY", zTab) ){
         1906  +  if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0)
         1907  +      || sqliteAuthCheck(pParse, SQLITE_COPY, pTab->zName, 0) ){
  1844   1908       goto copy_cleanup;
  1845   1909     }
  1846   1910     v = sqliteGetVdbe(pParse);
  1847   1911     if( v ){
  1848   1912       int openOp;
  1849   1913       sqliteBeginWriteOperation(pParse, 1, pTab->isTemp);
  1850   1914       addr = sqliteVdbeAddOp(v, OP_FileOpen, 0, 0);
................................................................................
  1921   1985   ** Begin a transaction
  1922   1986   */
  1923   1987   void sqliteBeginTransaction(Parse *pParse, int onError){
  1924   1988     sqlite *db;
  1925   1989   
  1926   1990     if( pParse==0 || (db=pParse->db)==0 || db->pBe==0 ) return;
  1927   1991     if( pParse->nErr || sqlite_malloc_failed ) return;
  1928         -  if( sqliteAuthCommand(pParse, "BEGIN", "") ) return;
         1992  +  if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0) ) return;
  1929   1993     if( db->flags & SQLITE_InTrans ){
  1930   1994       pParse->nErr++;
  1931   1995       sqliteSetString(&pParse->zErrMsg, "cannot start a transaction "
  1932   1996          "within a transaction", 0);
  1933   1997       return;
  1934   1998     }
  1935   1999     sqliteBeginWriteOperation(pParse, 0, 0);
................................................................................
  1941   2005   ** Commit a transaction
  1942   2006   */
  1943   2007   void sqliteCommitTransaction(Parse *pParse){
  1944   2008     sqlite *db;
  1945   2009   
  1946   2010     if( pParse==0 || (db=pParse->db)==0 || db->pBe==0 ) return;
  1947   2011     if( pParse->nErr || sqlite_malloc_failed ) return;
  1948         -  if( sqliteAuthCommand(pParse, "COMMIT", "") ) return;
         2012  +  if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0) ) return;
  1949   2013     if( (db->flags & SQLITE_InTrans)==0 ){
  1950   2014       pParse->nErr++;
  1951   2015       sqliteSetString(&pParse->zErrMsg, 
  1952   2016          "cannot commit - no transaction is active", 0);
  1953   2017       return;
  1954   2018     }
  1955   2019     db->flags &= ~SQLITE_InTrans;
................................................................................
  1962   2026   */
  1963   2027   void sqliteRollbackTransaction(Parse *pParse){
  1964   2028     sqlite *db;
  1965   2029     Vdbe *v;
  1966   2030   
  1967   2031     if( pParse==0 || (db=pParse->db)==0 || db->pBe==0 ) return;
  1968   2032     if( pParse->nErr || sqlite_malloc_failed ) return;
  1969         -  if( sqliteAuthCommand(pParse, "ROLLBACK", "") ) return;
         2033  +  if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0) ) return;
  1970   2034     if( (db->flags & SQLITE_InTrans)==0 ){
  1971   2035       pParse->nErr++;
  1972   2036       sqliteSetString(&pParse->zErrMsg,
  1973   2037          "cannot rollback - no transaction is active", 0);
  1974   2038       return; 
  1975   2039     }
  1976   2040     v = sqliteGetVdbe(pParse);
................................................................................
  2071   2135     if( minusFlag ){
  2072   2136       zRight = 0;
  2073   2137       sqliteSetNString(&zRight, "-", 1, pRight->z, pRight->n, 0);
  2074   2138     }else{
  2075   2139       zRight = sqliteStrNDup(pRight->z, pRight->n);
  2076   2140       sqliteDequote(zRight);
  2077   2141     }
  2078         -  if( sqliteAuthCommand(pParse, "PRAGMA", zLeft) ) return;
         2142  +  if( sqliteAuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight) ) return;
  2079   2143    
  2080   2144     /*
  2081   2145     **  PRAGMA default_cache_size
  2082   2146     **  PRAGMA default_cache_size=N
  2083   2147     **
  2084   2148     ** The first form reports the current persistent setting for the
  2085   2149     ** page cache size.  The value returned is the maximum number of

Changes to src/delete.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains C code routines that are called by the parser
    13     13   ** to handle DELETE FROM statements.
    14     14   **
    15         -** $Id: delete.c,v 1.44 2003/01/12 18:02:18 drh Exp $
           15  +** $Id: delete.c,v 1.45 2003/01/13 23:27:33 drh Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   
    19     19   
    20     20   /*
    21     21   ** Given a table name, find the corresponding table and make sure the
    22     22   ** table is writeable.  Generate an error and return NULL if not.  If
................................................................................
    84     84     int base;              /* Index of the first available table cursor */
    85     85     sqlite *db;            /* Main database structure */
    86     86     int openOp;            /* Opcode used to open a cursor to the table */
    87     87   
    88     88     int row_triggers_exist = 0;
    89     89     int oldIdx = -1;
    90     90   
    91         -  if( pParse->nErr || sqlite_malloc_failed
    92         -          || sqliteAuthCommand(pParse,"DELETE",0) ){
           91  +  if( pParse->nErr || sqlite_malloc_failed ){
    93     92       pTabList = 0;
    94     93       goto delete_from_cleanup;
    95     94     }
    96     95     db = pParse->db;
    97     96   
    98     97     /* Check for the special case of a VIEW with one or more ON DELETE triggers 
    99     98     ** defined 
................................................................................
   122    121     ** an SrcList* parameter instead of just a Table* parameter.
   123    122     */
   124    123     pTabList = sqliteTableTokenToSrcList(pParse, pTableName);
   125    124     if( pTabList==0 ) goto delete_from_cleanup;
   126    125     assert( pTabList->nSrc==1 );
   127    126     pTab = pTabList->a[0].pTab;
   128    127     assert( pTab->pSelect==0 );  /* This table is not a view */
   129         -  if( sqliteAuthDelete(pParse, pTab->zName, 0) ) goto delete_from_cleanup;
          128  +  if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0) ){
          129  +    goto delete_from_cleanup;
          130  +  }
   130    131   
   131    132     /* Allocate a cursor used to store the old.* data for a trigger.
   132    133     */
   133    134     if( row_triggers_exist ){ 
   134    135       oldIdx = pParse->nTab++;
   135    136     }
   136    137   

Changes to src/insert.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains C code routines that are called by the parser
    13     13   ** to handle INSERT statements in SQLite.
    14     14   **
    15         -** $Id: insert.c,v 1.70 2003/01/12 19:33:53 drh Exp $
           15  +** $Id: insert.c,v 1.71 2003/01/13 23:27:33 drh Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   
    19     19   /*
    20     20   ** This routine is call to handle SQL of the following forms:
    21     21   **
    22     22   **    insert into TABLE (IDLIST) values(EXPRLIST)
................................................................................
   110    110     int iInsertBlock;     /* Address of the subroutine used to insert data */
   111    111     int iCntMem;          /* Memory cell used for the row counter */
   112    112   
   113    113     int row_triggers_exist = 0; /* True if there are FOR EACH ROW triggers */
   114    114     int newIdx = -1;
   115    115   
   116    116     if( pParse->nErr || sqlite_malloc_failed ) goto insert_cleanup;
   117         -  if( sqliteAuthCommand(pParse, "INSERT", 0) ) goto insert_cleanup;
   118    117     db = pParse->db;
   119    118   
   120    119     /* Locate the table into which we will be inserting new information.
   121    120     */
   122    121     zTab = sqliteTableNameFromToken(pTableName);
   123    122     if( zTab==0 ) goto insert_cleanup;
   124    123     pTab = sqliteFindTable(pParse->db, zTab);
   125    124     if( pTab==0 ){
   126    125       sqliteSetString(&pParse->zErrMsg, "no such table: ", zTab, 0);
   127    126       pParse->nErr++;
   128    127       goto insert_cleanup;
   129    128     }
   130         -  if( sqliteAuthInsert(pParse, zTab, 0) ){
          129  +  if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0) ){
   131    130       goto insert_cleanup;
   132    131     }
   133    132   
   134    133     /* Ensure that:
   135    134     *  (a) the table is not read-only, 
   136    135     *  (b) that if it is a view then ON INSERT triggers exist
   137    136     */

Changes to src/parse.y.

    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains SQLite's grammar for SQL.  Process this file
    13     13   ** using the lemon parser generator to generate C code that runs
    14     14   ** the parser.  Lemon will also generate a header file containing
    15     15   ** numeric codes for all of the tokens.
    16     16   **
    17         -** @(#) $Id: parse.y,v 1.86 2003/01/07 02:47:48 drh Exp $
           17  +** @(#) $Id: parse.y,v 1.87 2003/01/13 23:27:33 drh Exp $
    18     18   */
    19     19   %token_prefix TK_
    20     20   %token_type {Token}
    21     21   %default_type {Token}
    22     22   %extra_argument {Parse *pParse}
    23     23   %syntax_error {
    24     24     sqliteSetString(&pParse->zErrMsg,"syntax error",0);
................................................................................
    81     81   cmd ::= END trans_opt.         {sqliteCommitTransaction(pParse);}
    82     82   cmd ::= ROLLBACK trans_opt.    {sqliteRollbackTransaction(pParse);}
    83     83   
    84     84   ///////////////////// The CREATE TABLE statement ////////////////////////////
    85     85   //
    86     86   cmd ::= create_table create_table_args.
    87     87   create_table ::= CREATE(X) temp(T) TABLE nm(Y). {
    88         -   sqliteStartTable(pParse,&X,&Y,T);
           88  +   sqliteStartTable(pParse,&X,&Y,T,0);
    89     89   }
    90     90   %type temp {int}
    91     91   temp(A) ::= TEMP.  {A = pParse->isTemp || !pParse->initFlag;}
    92     92   temp(A) ::= .      {A = pParse->isTemp;}
    93     93   create_table_args ::= LP columnlist conslist_opt RP(X). {
    94     94     sqliteEndTable(pParse,&X,0);
    95     95   }

Changes to src/select.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains C code routines that are called by the parser
    13     13   ** to handle SELECT statements in SQLite.
    14     14   **
    15         -** $Id: select.c,v 1.120 2003/01/12 18:02:18 drh Exp $
           15  +** $Id: select.c,v 1.121 2003/01/13 23:27:33 drh Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   
    19     19   
    20     20   /*
    21     21   ** Allocate a new Select structure and return a pointer to that
    22     22   ** structure.
................................................................................
  1777   1777     Expr *pHaving;         /* The HAVING clause.  May be NULL */
  1778   1778     int isDistinct;        /* True if the DISTINCT keyword is present */
  1779   1779     int distinct;          /* Table to use for the distinct set */
  1780   1780     int base;              /* First cursor available for use */
  1781   1781     int rc = 1;            /* Value to return from this function */
  1782   1782   
  1783   1783     if( sqlite_malloc_failed || pParse->nErr || p==0 ) return 1;
  1784         -  if( sqliteAuthCommand(pParse, "SELECT", 0) ) return 1;
         1784  +  if( sqliteAuthCheck(pParse, SQLITE_SELECT, 0, 0) ) return 1;
  1785   1785   
  1786   1786     /* If there is are a sequence of queries, do the earlier ones first.
  1787   1787     */
  1788   1788     if( p->pPrior ){
  1789   1789       return multiSelect(pParse, p, eDest, iParm);
  1790   1790     }
  1791   1791   

Changes to src/sqlite.h.in.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This header file defines the interface that the SQLite library
    13     13   ** presents to client programs.
    14     14   **
    15         -** @(#) $Id: sqlite.h.in,v 1.36 2003/01/12 18:02:18 drh Exp $
           15  +** @(#) $Id: sqlite.h.in,v 1.37 2003/01/13 23:27:33 drh Exp $
    16     16   */
    17     17   #ifndef _SQLITE_H_
    18     18   #define _SQLITE_H_
    19     19   #include <stdarg.h>     /* Needed for the definition of va_list */
    20     20   
    21     21   /*
    22     22   ** The version of the SQLite library.
................................................................................
   505    505   ** in the database.  The callback returns SQLITE_OK if access is allowed,
   506    506   ** SQLITE_DENY if the entire SQL statement should be aborted with an error
   507    507   ** and SQLITE_IGNORE if the column should be treated as a NULL value.
   508    508   */
   509    509   int sqlite_set_authorizer(
   510    510     sqlite*,
   511    511     int (*xAuth)(void*,int,const char*,const char*),
   512         -  void*
          512  +  void *pUserData
   513    513   );
   514    514   
   515    515   /*
   516    516   ** The second parameter to the access authorization function above will
   517         -** be one of these values:
          517  +** be one of the values below.  These values signify what kind of operation
          518  +** is to be authorized.  The 3rd and 4th parameters to the authorization
          519  +** function will be parameters or NULL depending on which of the following
          520  +** codes is used as the second parameter.
          521  +**
          522  +**                                          Arg-3           Arg-4
   518    523   */
   519         -#define SQLITE_READ_COLUMN   1  /* Is it OK to read the specified column?     */
   520         -#define SQLITE_WRITE_COLUMN  2  /* Is it OK to update the specified column?   */
   521         -#define SQLITE_DELETE_ROW    3  /* Is it OK to delete a row from the table?   */
   522         -#define SQLITE_INSERT_ROW    4  /* Is it OK to insert a new row in the table? */
   523         -#define SQLITE_COMMAND       5  /* Is it OK to execute a particular command?  */
          524  +#define SQLITE_COPY                  0   /* Table Name      NULL            */
          525  +#define SQLITE_CREATE_INDEX          1   /* Index Name      Table Name      */
          526  +#define SQLITE_CREATE_TABLE          2   /* Table Name      NULL            */
          527  +#define SQLITE_CREATE_TEMP_INDEX     3   /* Index Name      Table Name      */
          528  +#define SQLITE_CREATE_TEMP_TABLE     4   /* Table Name      NULL            */
          529  +#define SQLITE_CREATE_TEMP_TRIGGER   5   /* Trigger Name    NULL            */
          530  +#define SQLITE_CREATE_TEMP_VIEW      6   /* View Name       NULL            */
          531  +#define SQLITE_CREATE_TRIGGER        7   /* Trigger Name    NULL            */
          532  +#define SQLITE_CREATE_VIEW           8   /* View Name       NULL            */
          533  +#define SQLITE_DELETE                9   /* Table Name      NULL            */
          534  +#define SQLITE_DROP_INDEX           10   /* Index Name      NULL            */
          535  +#define SQLITE_DROP_TABLE           11   /* Table Name      NULL            */
          536  +#define SQLITE_DROP_TEMP_INDEX      12   /* Index Name      NULL            */
          537  +#define SQLITE_DROP_TEMP_TABLE      13   /* Table Name      NULL            */
          538  +#define SQLITE_DROP_TEMP_TRIGGER    14   /* Trigger Name    NULL            */
          539  +#define SQLITE_DROP_TEMP_VIEW       15   /* View Name       NULL            */
          540  +#define SQLITE_DROP_TRIGGER         16   /* Trigger Name    NULL            */
          541  +#define SQLITE_DROP_VIEW            17   /* View Name       NULL            */
          542  +#define SQLITE_INSERT               18   /* Table Name      NULL            */
          543  +#define SQLITE_PRAGMA               19   /* Pragma Name     1st arg or NULL */
          544  +#define SQLITE_READ                 20   /* Table Name      Column Name     */
          545  +#define SQLITE_SELECT               21   /* NULL            NULL            */
          546  +#define SQLITE_TRANSACTION          22   /* NULL            NULL            */
          547  +#define SQLITE_UPDATE               23   /* Table Name      Column Name     */
   524    548   
   525    549   /*
   526    550   ** The return value of the authorization function should be one of the
   527    551   ** following constants:
   528    552   */
   529    553   /* #define SQLITE_OK  0   // Allow access (This is actually defined above) */
   530    554   #define SQLITE_DENY   1   /* Abort the SQL statement with an error */

Changes to src/sqliteInt.h.

     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Internal interface definitions for SQLite.
    13     13   **
    14         -** @(#) $Id: sqliteInt.h,v 1.153 2003/01/12 18:02:18 drh Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.154 2003/01/13 23:27:33 drh Exp $
    15     15   */
    16     16   #include "config.h"
    17     17   #include "sqlite.h"
    18     18   #include "hash.h"
    19     19   #include "vdbe.h"
    20     20   #include "parse.h"
    21     21   #include "btree.h"
................................................................................
   934    934   void sqliteResetInternalSchema(sqlite*);
   935    935   int sqliteInit(sqlite*, char**);
   936    936   void sqliteBeginParse(Parse*,int);
   937    937   void sqliteRollbackInternalChanges(sqlite*);
   938    938   void sqliteCommitInternalChanges(sqlite*);
   939    939   Table *sqliteResultSetOfSelect(Parse*,char*,Select*);
   940    940   void sqliteOpenMasterTable(Vdbe *v, int);
   941         -void sqliteStartTable(Parse*,Token*,Token*,int);
          941  +void sqliteStartTable(Parse*,Token*,Token*,int,int);
   942    942   void sqliteAddColumn(Parse*,Token*);
   943    943   void sqliteAddNotNull(Parse*, int);
   944    944   void sqliteAddPrimaryKey(Parse*, IdList*, int);
   945    945   void sqliteAddColumnType(Parse*,Token*,Token*);
   946    946   void sqliteAddDefaultValue(Parse*,Token*,int);
   947    947   int sqliteCollateType(Parse*, Token*);
   948    948   void sqliteAddCollateType(Parse*, int);
................................................................................
  1031   1031   TriggerStep *sqliteTriggerDeleteStep(Token*, Expr*);
  1032   1032   void sqliteDeleteTrigger(Trigger*);
  1033   1033   int sqliteJoinType(Parse*, Token*, Token*, Token*);
  1034   1034   void sqliteCreateForeignKey(Parse*, IdList*, Token*, IdList*, int);
  1035   1035   void sqliteDeferForeignKey(Parse*, int);
  1036   1036   #ifndef SQLITE_OMIT_AUTHORIZATION
  1037   1037     void sqliteAuthRead(Parse*,Expr*,SrcList*,int);
  1038         -  int sqliteAuthDelete(Parse*,const char*, int);
  1039         -  int sqliteAuthInsert(Parse*,const char*, int);
  1040         -  int sqliteAuthCommand(Parse*,const char*,const char*);
         1038  +  int sqliteAuthCheck(Parse*,int, const char*, const char*);
  1041   1039   #else
  1042   1040   # define sqliteAuthRead(a,b,c,d)
  1043         -# define sqliteAuthDelete(a,b,c)     SQLITE_OK
  1044         -# define sqliteAuthInsert(a,b,c)     SQLITE_OK
  1045         -# define sqliteAuthWrite(a,b,c)      SQLITE_OK
  1046         -# define sqliteAuthCommand(a,b,c)    SQLITE_OK
         1041  +# define sqliteAuthCheck(a,b,c,d)    SQLITE_OK
  1047   1042   #endif

Changes to src/test1.c.

     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Code for testing the printf() interface to SQLite.  This code
    13     13   ** is not included in the SQLite library.  It is used for automated
    14     14   ** testing of the SQLite library.
    15     15   **
    16         -** $Id: test1.c,v 1.15 2003/01/12 18:02:19 drh Exp $
           16  +** $Id: test1.c,v 1.16 2003/01/13 23:27:33 drh Exp $
    17     17   */
    18     18   #include "sqliteInt.h"
    19     19   #include "tcl.h"
    20     20   #include <stdlib.h>
    21     21   #include <string.h>
    22     22   
    23     23   /*
................................................................................
   591    591     const char *zArg2
   592    592   ){
   593    593     char *zCode;
   594    594     Tcl_DString str;
   595    595     int rc;
   596    596     const char *zReply;
   597    597     switch( code ){
   598         -    case SQLITE_READ_COLUMN:   zCode="SQLITE_READ_COLUMN";  break;
   599         -    case SQLITE_WRITE_COLUMN:  zCode="SQLITE_WRITE_COLUMN"; break;
   600         -    case SQLITE_INSERT_ROW:    zCode="SQLITE_INSERT_ROW";   break;
   601         -    case SQLITE_DELETE_ROW:    zCode="SQLITE_DELETE_ROW";   break;
   602         -    case SQLITE_COMMAND:       zCode="SQLITE_COMMAND";      break;
   603         -    default:                   zCode="unknown code";        break;
          598  +    case SQLITE_COPY              : zCode="SQLITE_COPY"; break;
          599  +    case SQLITE_CREATE_INDEX      : zCode="SQLITE_CREATE_INDEX"; break;
          600  +    case SQLITE_CREATE_TABLE      : zCode="SQLITE_CREATE_TABLE"; break;
          601  +    case SQLITE_CREATE_TEMP_INDEX : zCode="SQLITE_CREATE_TEMP_INDEX"; break;
          602  +    case SQLITE_CREATE_TEMP_TABLE : zCode="SQLITE_CREATE_TEMP_TABLE"; break;
          603  +    case SQLITE_CREATE_TEMP_TRIGGER: zCode="SQLITE_CREATE_TEMP_TRIGGER"; break;
          604  +    case SQLITE_CREATE_TEMP_VIEW  : zCode="SQLITE_CREATE_TEMP_VIEW"; break;
          605  +    case SQLITE_CREATE_TRIGGER    : zCode="SQLITE_CREATE_TRIGGER"; break;
          606  +    case SQLITE_CREATE_VIEW       : zCode="SQLITE_CREATE_VIEW"; break;
          607  +    case SQLITE_DELETE            : zCode="SQLITE_DELETE"; break;
          608  +    case SQLITE_DROP_INDEX        : zCode="SQLITE_DROP_INDEX"; break;
          609  +    case SQLITE_DROP_TABLE        : zCode="SQLITE_DROP_TABLE"; break;
          610  +    case SQLITE_DROP_TEMP_INDEX   : zCode="SQLITE_DROP_TEMP_INDEX"; break;
          611  +    case SQLITE_DROP_TEMP_TABLE   : zCode="SQLITE_DROP_TEMP_TABLE"; break;
          612  +    case SQLITE_DROP_TEMP_TRIGGER : zCode="SQLITE_DROP_TEMP_TRIGGER"; break;
          613  +    case SQLITE_DROP_TEMP_VIEW    : zCode="SQLITE_DROP_TEMP_VIEW"; break;
          614  +    case SQLITE_DROP_TRIGGER      : zCode="SQLITE_DROP_TRIGGER"; break;
          615  +    case SQLITE_DROP_VIEW         : zCode="SQLITE_DROP_VIEW"; break;
          616  +    case SQLITE_INSERT            : zCode="SQLITE_INSERT"; break;
          617  +    case SQLITE_PRAGMA            : zCode="SQLITE_PRAGMA"; break;
          618  +    case SQLITE_READ              : zCode="SQLITE_READ"; break;
          619  +    case SQLITE_SELECT            : zCode="SQLITE_SELECT"; break;
          620  +    case SQLITE_TRANSACTION       : zCode="SQLITE_TRANSACTION"; break;
          621  +    case SQLITE_UPDATE            : zCode="SQLITE_UPDATE"; break;
          622  +    default                       : zCode="????"; break;
   604    623     }
   605    624     Tcl_DStringInit(&str);
   606    625     Tcl_DStringAppend(&str, authInfo.zCmd, -1);
   607    626     Tcl_DStringAppendElement(&str, zCode);
   608         -  Tcl_DStringAppendElement(&str, zArg1);
          627  +  Tcl_DStringAppendElement(&str, zArg1 ? zArg1 : "");
   609    628     Tcl_DStringAppendElement(&str, zArg2 ? zArg2 : "");
   610    629     rc = Tcl_GlobalEval(authInfo.interp, Tcl_DStringValue(&str));
   611    630     Tcl_DStringFree(&str);
   612    631     zReply = Tcl_GetStringResult(authInfo.interp);
   613    632     if( strcmp(zReply,"SQLITE_OK")==0 ){
   614    633       rc = SQLITE_OK;
   615    634     }else if( strcmp(zReply,"SQLITE_DENY")==0 ){

Changes to src/trigger.c.

    45     45     int foreach,        /* One of TK_ROW or TK_STATEMENT */
    46     46     Expr *pWhen,        /* WHEN clause */
    47     47     TriggerStep *pStepList, /* The triggered program */
    48     48     Token *pAll             /* Token that describes the complete CREATE TRIGGER */
    49     49   ){
    50     50     Trigger *nt;
    51     51     Table   *tab;
    52         -
    53         -  if( sqliteAuthCommand(pParse, "CREATE", "TRIGGER") ) goto trigger_cleanup;
           52  +  char *zName = 0;    /* Name of the trigger */
    54     53   
    55     54     /* Check that: 
    56     55     ** 1. the trigger name does not already exist.
    57     56     ** 2. the table (or view) does exist.
    58     57     ** 3. that we are not trying to create a trigger on the sqlite_master table
    59     58     ** 4. That we are not trying to create an INSTEAD OF trigger on a table.
    60     59     ** 5. That we are not trying to create a BEFORE or AFTER trigger on a view.
    61     60     */
    62         -  {
    63         -    char *tmp_str = sqliteStrNDup(pName->z, pName->n);
    64         -    if( sqliteHashFind(&(pParse->db->trigHash), tmp_str, pName->n + 1) ){
    65         -      sqliteSetNString(&pParse->zErrMsg, "trigger ", -1,
    66         -          pName->z, pName->n, " already exists", -1, 0);
    67         -      sqliteFree(tmp_str);
    68         -      pParse->nErr++;
    69         -      goto trigger_cleanup;
    70         -    }
    71         -    sqliteFree(tmp_str);
           61  +  zName = sqliteStrNDup(pName->z, pName->n);
           62  +  if( sqliteHashFind(&(pParse->db->trigHash), zName, pName->n + 1) ){
           63  +    sqliteSetNString(&pParse->zErrMsg, "trigger ", -1,
           64  +        pName->z, pName->n, " already exists", -1, 0);
           65  +    pParse->nErr++;
           66  +    goto trigger_cleanup;
    72     67     }
    73     68     {
    74     69       char *tmp_str = sqliteStrNDup(pTableName->z, pTableName->n);
    75     70       if( tmp_str==0 ) goto trigger_cleanup;
    76     71       tab = sqliteFindTable(pParse->db, tmp_str);
    77     72       sqliteFree(tmp_str);
    78     73       if( !tab ){
................................................................................
   100     95         goto trigger_cleanup;
   101     96       }
   102     97       if( !tab->pSelect && tr_tm == TK_INSTEAD ){
   103     98         sqliteSetNString(&pParse->zErrMsg, "cannot create INSTEAD OF", -1, 
   104     99   	  " trigger on table: ", -1, pTableName->z, pTableName->n, 0);
   105    100         goto trigger_cleanup;
   106    101       }
   107         -    if( sqliteAuthInsert(pParse, SCHEMA_TABLE(tab->isTemp), 1) ){
   108         -      goto trigger_cleanup;
          102  +#ifndef SQLITE_OMIT_AUTHORIZATION
          103  +    {
          104  +      int code = SQLITE_CREATE_TRIGGER;
          105  +      if( tab->isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER;
          106  +      if( sqliteAuthCheck(pParse, code, zName, tab->zName) ){
          107  +        goto trigger_cleanup;
          108  +      }
   109    109       }
          110  +#endif
   110    111     }
   111    112   
   112    113     if (tr_tm == TK_INSTEAD){
   113    114       tr_tm = TK_BEFORE;
   114    115     }
   115    116   
   116    117     /* Build the Trigger object */
   117    118     nt = (Trigger*)sqliteMalloc(sizeof(Trigger));
   118    119     if( nt==0 ) goto trigger_cleanup;
   119         -  nt->name = sqliteStrNDup(pName->z, pName->n);
          120  +  nt->name = zName;
          121  +  zName = 0;
   120    122     nt->table = sqliteStrNDup(pTableName->z, pTableName->n);
   121    123     if( sqlite_malloc_failed ) goto trigger_cleanup;
   122    124     nt->op = op;
   123    125     nt->tr_tm = tr_tm;
   124    126     nt->pWhen = sqliteExprDup(pWhen);
   125    127     sqliteExprDelete(pWhen);
   126    128     nt->pColumns = sqliteIdListDup(pColumns);
................................................................................
   175    177       sqliteFree(nt->name);
   176    178       sqliteFree(nt->table);
   177    179       sqliteFree(nt);
   178    180     }
   179    181   
   180    182   trigger_cleanup:
   181    183   
          184  +  sqliteFree(zName);
   182    185     sqliteIdListDelete(pColumns);
   183    186     sqliteExprDelete(pWhen);
   184    187     sqliteDeleteTriggerStep(pStepList);
   185    188   }
   186    189   
   187    190   /*
   188    191   ** Make a copy of all components of the given trigger step.  This has
................................................................................
   338    341    */
   339    342   void sqliteDropTrigger(Parse *pParse, Token *pName, int nested){
   340    343     char *zName;
   341    344     Trigger *pTrigger;
   342    345     Table   *pTable;
   343    346     Vdbe *v;
   344    347   
   345         -  if( sqliteAuthCommand(pParse, "DROP", "TRIGGER") ) return;
   346    348     zName = sqliteStrNDup(pName->z, pName->n);
   347    349   
   348    350     /* ensure that the trigger being dropped exists */
   349    351     pTrigger = sqliteHashFind(&(pParse->db->trigHash), zName, pName->n + 1); 
   350    352     if( !pTrigger ){
   351    353       sqliteSetNString(&pParse->zErrMsg, "no such trigger: ", -1,
   352    354           zName, -1, 0);
   353    355       sqliteFree(zName);
   354    356       return;
   355    357     }
   356    358     pTable = sqliteFindTable(pParse->db, pTrigger->table);
   357    359     assert(pTable);
   358         -  if( sqliteAuthDelete(pParse, SCHEMA_TABLE(pTable->isTemp), 1) ){
   359         -    sqliteFree(zName);
   360         -    return;
          360  +#ifndef SQLITE_OMIT_AUTHORIZATION
          361  +  {
          362  +    int code = SQLITE_DROP_TRIGGER;
          363  +    if( pTable->isTemp ) code = SQLITE_DROP_TEMP_TRIGGER;
          364  +    if( sqliteAuthCheck(pParse, code, pTrigger->name, pTable->zName) ||
          365  +      sqliteAuthCheck(pParse, SQLITE_DELETE, SCHEMA_TABLE(pTable->isTemp),0) ){
          366  +      sqliteFree(zName);
          367  +      return;
          368  +    }
   361    369     }
   362         -
          370  +#endif
   363    371   
   364    372     /*
   365    373      * If this is not an "explain", then delete the trigger structure.
   366    374      */
   367    375     if( !pParse->explain ){
   368    376       if( pTable->pTrigger == pTrigger ){
   369    377         pTable->pTrigger = pTrigger->pNext;

Changes to src/update.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains C code routines that are called by the parser
    13     13   ** to handle UPDATE statements.
    14     14   **
    15         -** $Id: update.c,v 1.52 2003/01/12 18:02:19 drh Exp $
           15  +** $Id: update.c,v 1.53 2003/01/13 23:27:33 drh Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   
    19     19   /*
    20     20   ** Process an UPDATE statement.
    21     21   */
    22     22   void sqliteUpdate(
................................................................................
    49     49   
    50     50     int row_triggers_exist = 0;
    51     51   
    52     52     int newIdx      = -1;  /* index of trigger "new" temp table       */
    53     53     int oldIdx      = -1;  /* index of trigger "old" temp table       */
    54     54   
    55     55     if( pParse->nErr || sqlite_malloc_failed ) goto update_cleanup;
    56         -  if( sqliteAuthCommand(pParse, "UPDATE", 0) ) goto update_cleanup;
    57     56     db = pParse->db;
    58     57   
    59     58     /* Check for the special case of a VIEW with one or more ON UPDATE triggers 
    60     59      * defined 
    61     60      */
    62     61     {
    63     62       char *zTab = sqliteTableNameFromToken(pTableName);
................................................................................
   144    143       if( j>=pTab->nCol ){
   145    144         sqliteSetString(&pParse->zErrMsg, "no such column: ", 
   146    145            pChanges->a[i].zName, 0);
   147    146         pParse->nErr++;
   148    147         goto update_cleanup;
   149    148       }
   150    149   #ifndef SQLITE_OMIT_AUTHORIZATION
   151         -    if( sqliteAuthWrite(pParse, pTab, j)==SQLITE_IGNORE ){
   152         -      aXRef[j] = -1;
          150  +    {
          151  +      int rc;
          152  +      rc = sqliteAuthCheck(pParse, SQLITE_UPDATE, pTab->zName,
          153  +                           pTab->aCol[j].zName);
          154  +      if( rc==SQLITE_DENY ){
          155  +        goto update_cleanup;
          156  +      }else if( rc==SQLITE_IGNORE ){
          157  +        aXRef[j] = -1;
          158  +      }
   153    159       }
   154    160   #endif
   155    161     }
   156    162   
   157    163     /* Allocate memory for the array apIdx[] and fill it with pointers to every
   158    164     ** index that needs to be updated.  Indices only need updating if their
   159    165     ** key includes one of the columns named in pChanges or if the record

Changes to test/auth.test.

     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this script testing the sqlite_set_authorizer() API.
    13     13   #
    14         -# $Id: auth.test,v 1.1 2003/01/12 19:33:54 drh Exp $
           14  +# $Id: auth.test,v 1.2 2003/01/13 23:27:34 drh Exp $
    15     15   #
    16     16   
    17     17   set testdir [file dirname $argv0]
    18     18   source $testdir/tester.tcl
    19     19   
    20     20   if {[info command sqlite_set_authorizer]!=""} {
    21     21   
    22     22   do_test auth-1.1 {
    23     23     db close
    24     24     set ::DB [sqlite db test.db]
    25     25     proc auth {code arg1 arg2} {
    26         -    if {$code=="SQLITE_INSERT_ROW" 
           26  +    if {$code=="SQLITE_INSERT" 
    27     27             && [string compare -nocase $arg1 sqlite_master]==0} {
    28     28         return SQLITE_DENY
    29     29       }
    30     30       return SQLITE_OK
    31     31     }
    32     32     sqlite_set_authorizer $::DB ::auth
    33     33     catchsql {CREATE TABLE t1(a,b,c)}
    34         -} {1 {insertion into table sqlite_master is prohibited}}
           34  +} {1 {not authorized}}
    35     35   do_test auth-1.2 {
           36  +  execsql {SELECT name FROM sqlite_master}
           37  +} {}
           38  +do_test auth-1.3 {
           39  +  proc auth {code arg1 arg2} {
           40  +    if {$code=="SQLITE_CREATE_TABLE"} {
           41  +      return SQLITE_DENY
           42  +    }
           43  +    return SQLITE_OK
           44  +  }
           45  +  catchsql {CREATE TABLE t1(a,b,c)}
           46  +} {1 {not authorized}}
           47  +do_test auth-1.4 {
           48  +  execsql {SELECT name FROM sqlite_master}
           49  +} {}
           50  +
           51  +do_test auth-1.5 {
           52  +  proc auth {code arg1 arg2} {
           53  +    if {$code=="SQLITE_INSERT" 
           54  +          && [string compare -nocase $arg1 sqlite_temp_master]==0} {
           55  +      return SQLITE_DENY
           56  +    }
           57  +    return SQLITE_OK
           58  +  }
           59  +  catchsql {CREATE TEMP TABLE t1(a,b,c)}
           60  +} {1 {not authorized}}
           61  +do_test auth-1.6 {
           62  +  execsql {SELECT name FROM sqlite_temp_master}
           63  +} {}
           64  +do_test auth-1.7 {
           65  +  proc auth {code arg1 arg2} {
           66  +    if {$code=="SQLITE_CREATE_TEMP_TABLE"} {
           67  +      return SQLITE_DENY
           68  +    }
           69  +    return SQLITE_OK
           70  +  }
           71  +  catchsql {CREATE TEMP TABLE t1(a,b,c)}
           72  +} {1 {not authorized}}
           73  +do_test auth-1.8 {
           74  +  execsql {SELECT name FROM sqlite_temp_master}
           75  +} {}
           76  +
           77  +do_test auth-1.9 {
    36     78     proc auth {code arg1 arg2} {
    37         -    if {$code=="SQLITE_INSERT_ROW" 
           79  +    if {$code=="SQLITE_INSERT" 
    38     80             && [string compare -nocase $arg1 sqlite_master]==0} {
    39     81         return SQLITE_IGNORE
    40     82       }
    41     83       return SQLITE_OK
    42     84     }
    43     85     catchsql {CREATE TABLE t1(a,b,c)}
    44         -} {1 {insertion into table sqlite_master is prohibited}}
    45         -do_test auth-1.3 {
           86  +} {0 {}}
           87  +do_test auth-1.10 {
           88  +  execsql {SELECT name FROM sqlite_master}
           89  +} {}
           90  +do_test auth-1.11 {
    46     91     proc auth {code arg1 arg2} {
    47         -    if {$code=="SQLITE_INSERT_ROW" 
    48         -          && [string compare -nocase $arg1 sqlite_master]==0} {
    49         -      return SQLITE_OK
           92  +    if {$code=="SQLITE_CREATE_TABLE"} {
           93  +      return SQLITE_IGNORE
    50     94       }
    51     95       return SQLITE_OK
    52     96     }
    53     97     catchsql {CREATE TABLE t1(a,b,c)}
    54     98   } {0 {}}
    55         -do_test auth-1.4 {
           99  +do_test auth-1.12 {
    56    100     execsql {SELECT name FROM sqlite_master}
    57         -} {t1}
    58         -do_test auth-1.5 {
          101  +} {}
          102  +do_test auth-1.13 {
    59    103     proc auth {code arg1 arg2} {
    60         -    if {$code=="SQLITE_INSERT_ROW" 
    61         -          && [string compare -nocase $arg1 sqlite_master]==0} {
    62         -      return BOGUS
          104  +    if {$code=="SQLITE_INSERT" 
          105  +          && [string compare -nocase $arg1 sqlite_temp_master]==0} {
          106  +      return SQLITE_IGNORE
    63    107       }
    64    108       return SQLITE_OK
    65    109     }
    66         -  catchsql {CREATE TABLE t2(a,b,c)}
    67         -} {1 {illegal return value (1) from the authorization function - should be SQLITE_OK, SQLITE_IGNORE, or SQLITE_DENY}}
    68         -do_test auth-1.6 {
          110  +  catchsql {CREATE TEMP TABLE t1(a,b,c)}
          111  +} {0 {}}
          112  +do_test auth-1.14 {
          113  +  execsql {SELECT name FROM sqlite_temp_master}
          114  +} {}
          115  +do_test auth-1.15 {
    69    116     proc auth {code arg1 arg2} {
    70         -    if {$code=="SQLITE_DELETE_ROW" 
    71         -          && [string compare -nocase $arg1 sqlite_master]==0} {
    72         -      return SQLITE_DENY
    73         -    }
    74         -    return SQLITE_OK
    75         -  }
    76         -  catchsql {DROP TABLE t1}
    77         -} {1 {deletion from table sqlite_master is prohibited}}
    78         -do_test auth-1.7 {
    79         -  proc auth {code arg1 arg2} {
    80         -    if {$code=="SQLITE_DELETE_ROW" 
    81         -          && [string compare -nocase $arg1 sqlite_master]==0} {
          117  +    if {$code=="SQLITE_CREATE_TEMP_TABLE"} {
    82    118         return SQLITE_IGNORE
    83    119       }
    84    120       return SQLITE_OK
    85    121     }
    86         -  catchsql {DROP TABLE t1}
    87         -} {1 {deletion from table sqlite_master is prohibited}}
    88         -do_test auth-1.8 {
          122  +  catchsql {CREATE TEMP TABLE t1(a,b,c)}
          123  +} {0 {}}
          124  +do_test auth-1.16 {
          125  +  execsql {SELECT name FROM sqlite_temp_master}
          126  +} {}
          127  +
          128  +do_test auth-1.17 {
    89    129     proc auth {code arg1 arg2} {
    90         -    if {$code=="SQLITE_INSERT_ROW" 
    91         -          && [string compare -nocase $arg1 t1]==0} {
    92         -      return SQLITE_DENY
          130  +    if {$code=="SQLITE_CREATE_TABLE"} {
          131  +      return SQLITE_DEBY
    93    132       }
    94    133       return SQLITE_OK
    95    134     }
    96         -  catchsql {INSERT INTO t1 VALUES(1,2,3)}
    97         -} {1 {insertion into table t1 is prohibited}}
    98         -do_test auth-1.9 {
          135  +  catchsql {CREATE TEMP TABLE t1(a,b,c)}
          136  +} {0 {}}
          137  +do_test auth-1.18 {
          138  +  execsql {SELECT name FROM sqlite_temp_master}
          139  +} {t1}
          140  +do_test auth-1.19 {
    99    141     proc auth {code arg1 arg2} {
   100         -    if {$code=="SQLITE_INSERT_ROW" 
   101         -          && [string compare -nocase $arg1 t1]==0} {
   102         -      return SQLITE_IGNORE
   103         -    }
   104         -    return SQLITE_OK
   105         -  }
   106         -  catchsql {INSERT INTO t1 VALUES(1,2,3)}
   107         -} {0 {}}
   108         -do_test auth-1.10 {
   109         -  execsql {SELECT * FROM t1}
   110         -} {}
   111         -do_test auth-1.11 {
   112         -  proc auth {code arg1 arg2} {
   113         -    if {$code=="SQLITE_INSERT_ROW" 
   114         -          && [string compare -nocase $arg1 t1]==0} {
   115         -      return SQLITE_OK
          142  +    if {$code=="SQLITE_CREATE_TEMP_TABLE"} {
          143  +      return SQLITE_DEBY
   116    144       }
   117    145       return SQLITE_OK
   118    146     }
   119         -  catchsql {INSERT INTO t1 VALUES(1,2,3)}
          147  +  catchsql {CREATE TABLE t2(a,b,c)}
   120    148   } {0 {}}
   121         -do_test auth-1.12 {
   122         -  execsql {SELECT * FROM t1}
   123         -} {1 2 3}
   124         -do_test auth-1.13 {
   125         -  proc auth {code arg1 arg2} {
   126         -    if {$code=="SQLITE_DELETE_ROW" 
   127         -          && [string compare -nocase $arg1 t1]==0} {
   128         -      return SQLITE_DENY
   129         -    }
   130         -    return SQLITE_OK
   131         -  }
   132         -  catchsql {DELETE FROM t1 WHERE a=1}
   133         -} {1 {deletion from table t1 is prohibited}}
   134         -do_test auth-1.14 {
   135         -  execsql {SELECT * FROM t1}
   136         -} {1 2 3}
   137         -do_test auth-1.15 {
   138         -  proc auth {code arg1 arg2} {
   139         -    if {$code=="SQLITE_DELETE_ROW" 
   140         -          && [string compare -nocase $arg1 t1]==0} {
   141         -      return SQLITE_IGNORE
   142         -    }
   143         -    return SQLITE_OK
   144         -  }
   145         -  catchsql {DELETE FROM t1 WHERE a=1}
   146         -} {0 {}}
   147         -do_test auth-1.16 {
   148         -  execsql {SELECT * FROM t1}
   149         -} {1 2 3}
   150         -do_test auth-1.17 {
   151         -  proc auth {code arg1 arg2} {
   152         -    if {$code=="SQLITE_READ_COLUMN" 
   153         -          && [string compare -nocase $arg1 t1]==0
   154         -          && [string compare -nocase $arg2 a]==0} {
   155         -      return SQLITE_DENY
   156         -    }
   157         -    return SQLITE_OK
   158         -  }
   159         -  catchsql {SELECT * FROM t1}
   160         -} {1 {access to t1.a is prohibited}}
   161         -do_test auth-1.18 {
   162         -  proc auth {code arg1 arg2} {
   163         -    if {$code=="SQLITE_READ_COLUMN" 
   164         -          && [string compare -nocase $arg1 t1]==0
   165         -          && [string compare -nocase $arg2 a]==0} {
   166         -      return SQLITE_IGNORE
   167         -    }
   168         -    return SQLITE_OK
   169         -  }
   170         -  catchsql {SELECT * FROM t1}
   171         -} {0 {{} 2 3}}
   172         -do_test auth-1.19 {
   173         -  proc auth {code arg1 arg2} {
   174         -    if {$code=="SQLITE_WRITE_COLUMN" 
   175         -          && [string compare -nocase $arg1 t1]==0
   176         -          && [string compare -nocase $arg2 a]==0} {
   177         -      return SQLITE_DENY
   178         -    }
   179         -    return SQLITE_OK
   180         -  }
   181         -  catchsql {UPDATE t1 SET a=11 WHERE a=1}
   182         -} {1 {changes to t1.a are prohibited}}
   183    149   do_test auth-1.20 {
   184         -  execsql {SELECT * FROM t1}
   185         -} {1 2 3}
   186         -do_test auth-1.21 {
   187         -  proc auth {code arg1 arg2} {
   188         -    if {$code=="SQLITE_WRITE_COLUMN" 
   189         -          && [string compare -nocase $arg1 t1]==0
   190         -          && [string compare -nocase $arg2 a]==0} {
   191         -      return SQLITE_DENY
   192         -    }
   193         -    return SQLITE_OK
   194         -  }
   195         -  catchsql {UPDATE t1 SET b=12 WHERE a=1}
   196         -} {0 {}}
   197         -do_test auth-1.22 {
   198         -  execsql {SELECT * FROM t1}
   199         -} {1 12 3}
   200         -do_test auth-1.23 {
   201         -  proc auth {code arg1 arg2} {
   202         -    if {$code=="SQLITE_WRITE_COLUMN" 
   203         -          && [string compare -nocase $arg1 t1]==0
   204         -          && [string compare -nocase $arg2 a]==0} {
   205         -      return SQLITE_IGNORE
   206         -    }
   207         -    return SQLITE_OK
   208         -  }
   209         -  catchsql {UPDATE t1 SET a=11, b=22 WHERE a=1}
   210         -} {0 {}}
   211         -do_test auth-1.24 {
   212         -  execsql {SELECT * FROM t1}
   213         -} {1 22 3}
   214         -do_test auth-1.25 {
   215         -  proc auth {code arg1 arg2} {
   216         -    if {$code=="SQLITE_WRITE_COLUMN" 
   217         -          && [string compare -nocase $arg1 t1]==0
   218         -          && [string compare -nocase $arg2 a]==0} {
   219         -      return SQLITE_DENY
   220         -    }
   221         -    return SQLITE_OK
   222         -  }
   223         -  catchsql {UPDATE t1 SET a=11, b=33 WHERE a=1}
   224         -} {1 {changes to t1.a are prohibited}}
   225         -do_test auth-1.26 {
   226         -  execsql {SELECT * FROM t1}
   227         -} {1 22 3}
   228         -do_test auth-1.27 {
   229         -  proc auth {code arg1 arg2} {
   230         -    if {$code=="SQLITE_READ_COLUMN" 
   231         -          && [string compare -nocase $arg1 t1]==0
   232         -          && [string compare -nocase $arg2 a]==0} {
   233         -      return SQLITE_DENY
   234         -    }
   235         -    return SQLITE_OK
   236         -  }
   237         -  catchsql {UPDATE t1 SET b=33, c=44 WHERE a=1}
   238         -} {1 {access to t1.a is prohibited}}
   239         -do_test auth-1.28 {
   240         -  execsql {SELECT b, c FROM t1}
   241         -} {22 3}
   242         -do_test auth-1.29 {
   243         -  proc auth {code arg1 arg2} {
   244         -    if {$code=="SQLITE_READ_COLUMN" 
   245         -          && [string compare -nocase $arg1 t1]==0
   246         -          && [string compare -nocase $arg2 a]==0} {
   247         -      return SQLITE_IGNORE
   248         -    }
   249         -    return SQLITE_OK
   250         -  }
   251         -  catchsql {UPDATE t1 SET b=33, c=44 WHERE a=1}
   252         -} {0 {}}
   253         -do_test auth-1.30 {
   254         -  execsql {SELECT b, c FROM t1}
   255         -} {22 3}
   256         -do_test auth-1.31 {
   257         -  proc auth {code arg1 arg2} {
   258         -    if {$code=="SQLITE_READ_COLUMN" 
   259         -          && [string compare -nocase $arg1 t1]==0
   260         -          && [string compare -nocase $arg2 a]==0} {
   261         -      return SQLITE_IGNORE
   262         -    }
   263         -    return SQLITE_OK
   264         -  }
   265         -  catchsql {UPDATE t1 SET b=33, c=44 WHERE a IS NULL}
   266         -} {0 {}}
   267         -do_test auth-1.32 {
   268         -  execsql {SELECT b, c FROM t1}
   269         -} {33 44}
          150  +  execsql {SELECT name FROM sqlite_master}
          151  +} {t2}
          152  +
          153  +
   270    154   
   271         -  
          155  +
   272    156   } ;# End of the "if( db command exists )"
   273    157   
   274    158   finish_test