SQLite4
Check-in [555f0c788d]
Not logged in

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

Overview
SHA1 Hash:555f0c788da8c8ff6eee489a2e3748c076caee6d
Date: 2013-05-07 19:36:18
User: dan
Comment:Replace sqlite4_set_authorizer() with sqlite4_authorizer_push() and sqlite4_authorizer_pop().
Tags And Properties
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/auth.c

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26


27
28
29
30
31
32
33
34
35
36
37
38




39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

72
73

74



75






76


77
78


79




















80




















81
82
83
84
85
86
87
88
89
90










































91
92
93
94
95
96
97
...
100
101
102
103
104
105
106

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121

122
123
124
125
126
127
128
...
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
...
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215

216
217
218
219
220
221
222
** 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 sqlite4_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 -DSQLITE4_OMIT_AUTHORIZATION=1
*/
#include "sqliteInt.h"

/*
** All of the code in this file may be omitted by defining a single
** macro.
*/
#ifndef SQLITE4_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 on
** 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:
**
**       SQLITE4_CREATE_INDEX
**       SQLITE4_CREATE_TABLE
**       SQLITE4_CREATE_TEMP_INDEX
**       SQLITE4_CREATE_TEMP_TABLE
**       SQLITE4_CREATE_TEMP_TRIGGER




**       SQLITE4_CREATE_TEMP_VIEW
**       SQLITE4_CREATE_TRIGGER
**       SQLITE4_CREATE_VIEW
**       SQLITE4_DELETE
**       SQLITE4_DROP_INDEX
**       SQLITE4_DROP_TABLE
**       SQLITE4_DROP_TEMP_INDEX
**       SQLITE4_DROP_TEMP_TABLE
**       SQLITE4_DROP_TEMP_TRIGGER
**       SQLITE4_DROP_TEMP_VIEW
**       SQLITE4_DROP_TRIGGER
**       SQLITE4_DROP_VIEW
**       SQLITE4_INSERT
**       SQLITE4_PRAGMA
**       SQLITE4_READ
**       SQLITE4_SELECT
**       SQLITE4_TRANSACTION
**       SQLITE4_UPDATE
**
** 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 SQLITE4_OK, SQLITE4_DENY, or SQLITE4_IGNORE.  If
** SQLITE4_OK is returned, it means that access is allowed.  SQLITE4_DENY
** means that the SQL statement will never-run - the sqlite4_exec() call
** will return with an error.  SQLITE4_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 sqlite4_set_authorizer(
  sqlite4 *db,

  int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
  void *pArg

){



  sqlite4_mutex_enter(db->mutex);






  db->xAuth = xAuth;


  db->pAuthArg = pArg;
  sqlite4ExpirePreparedStatements(db);


  sqlite4_mutex_leave(db->mutex);




















  return SQLITE4_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){
  sqlite4ErrorMsg(pParse, "authorizer malfunction");
  pParse->rc = SQLITE4_ERROR;
}











































/*
** Invoke the authorization callback for permission to read column zCol from
** table zTab in database zDb. This function assumes that an authorization
** callback has been registered (i.e. that sqlite4.xAuth is not NULL).
**
** If SQLITE4_IGNORE is returned and pExpr is not NULL, then pExpr is changed
................................................................................
*/
int sqlite4AuthReadCol(
  Parse *pParse,                  /* The parser context */
  const char *zTab,               /* Table name */
  const char *zCol,               /* Column name */
  int iDb                         /* Index of containing database. */
){

  sqlite4 *db = pParse->db;       /* Database handle */
  char *zDb = db->aDb[iDb].zName; /* Name of attached database */
  int rc;                         /* Auth callback return code */

  rc = db->xAuth(db->pAuthArg, SQLITE4_READ, zTab,zCol,zDb,pParse->zAuthContext);
  if( rc==SQLITE4_DENY ){
    if( db->nDb>2 || iDb!=0 ){
      sqlite4ErrorMsg(pParse, "access to %s.%s.%s is prohibited",zDb,zTab,zCol);
    }else{
      sqlite4ErrorMsg(pParse, "access to %s.%s is prohibited", zTab, zCol);
    }
    pParse->rc = SQLITE4_AUTH;
  }else if( rc!=SQLITE4_IGNORE && rc!=SQLITE4_OK ){
    sqliteAuthBadReturnCode(pParse);
  }

  return rc;
}

/*
** The pExpr should be a TK_COLUMN expression.  The table referred to
** is in pTabList or else it is the NEW or OLD table of a trigger.  
** Check to see if it is OK to read this particular column.
................................................................................
  sqlite4 *db = pParse->db;
  Table *pTab = 0;      /* The table being read */
  const char *zCol;     /* Name of the column of the table */
  int iSrc;             /* Index in pTabList->a[] of table being read */
  int iDb;              /* The index of the database the expression refers to */
  int iCol;             /* Index of column in table */

  if( db->xAuth==0 ) return;
  iDb = sqlite4SchemaToIndex(pParse->db, pSchema);
  if( iDb<0 ){
    /* An attempt to read a column out of a subquery or other
    ** temporary table. */
    return;
  }

................................................................................
  /* Don't do any authorization checks if the database is initialising
  ** or if the parser is being invoked from within sqlite4_declare_vtab.
  */
  if( db->init.busy || IN_DECLARE_VTAB ){
    return SQLITE4_OK;
  }

  if( db->xAuth==0 ){
    return SQLITE4_OK;
  }
  rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext);
  if( rc==SQLITE4_DENY ){
    sqlite4ErrorMsg(pParse, "not authorized");
    pParse->rc = SQLITE4_AUTH;
  }else if( rc!=SQLITE4_OK && rc!=SQLITE4_IGNORE ){
    rc = SQLITE4_DENY;
    sqliteAuthBadReturnCode(pParse);
  }

  return rc;
}

/*
** Push an authorization context.  After this routine is called, the
** zArg3 argument to authorization callbacks will be zContext until
** popped.  Or if pParse==0, this routine is a no-op.







|
|
|
|










|
>
>
|
<
<
|
|
|
|
|
<
<
<
<
>
>
>
>
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|

>

<
>

>
>
>

>
>
>
>
>
>
|
>
>
|
|
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>




|
|






<
<

>







 







|







 







<
<
<
|
|


<
<
<

>







5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29


30
31
32
33
34




35
36
37
38
39





























40
41
42
43
44

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
...
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186


187
188
189
190
191
192
193
194
195
...
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
...
265
266
267
268
269
270
271



272
273
274
275



276
277
278
279
280
281
282
283
284
** 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 sqlite4_authorizer_push()
** and sqlite4_authorizer_pop() APIs. 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 -DSQLITE4_OMIT_AUTHORIZATION=1
*/
#include "sqliteInt.h"

/*
** All of the code in this file may be omitted by defining a single
** macro.
*/
#ifndef SQLITE4_OMIT_AUTHORIZATION

/*
** Each authorizer callback is stored in an instance of this structure.
** The structures themselves are stored in a linked list headed at
** sqlite4.pAuth.
*/


struct Authorizer {
  void *pCtx;
  int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
  void (*xDestroy)(void*);
  Authorizer *pNext;




};


/*
** Push an authorizer callback onto the stack.





























*/
int sqlite4_authorizer_push(
  sqlite4 *db,
  void *pCtx,
  int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),

  void (*xDestroy)(void*)
){
  int rc = SQLITE4_OK;
  Authorizer *pNew;

  sqlite4_mutex_enter(db->mutex);

  pNew = (Authorizer *)sqlite4DbMallocZero(db, sizeof(Authorizer));
  if( pNew==0 ){
    rc = SQLITE4_NOMEM;
  }else{
    pNew->pCtx = pCtx;
    pNew->xAuth = xAuth;
    pNew->xDestroy = xDestroy;
    pNew->pNext = db->pAuth;
    db->pAuth = pNew;
    sqlite4ExpirePreparedStatements(db);
  }

  sqlite4_mutex_leave(db->mutex);
  return rc;
}

/*
** Pop an authorizer callback from the stack. This version assumes that
** the stack is not empty and that the database handle mutex is held.
*/
static void authPopStack(sqlite4 *db){
  Authorizer *pAuth = db->pAuth;
  db->pAuth = pAuth->pNext;
  if( pAuth->xDestroy ){
    pAuth->xDestroy(pAuth->pCtx);
  }
  sqlite4DbFree(db, pAuth);
}

/*
** Pop an authorizer callback from the stack.
*/
int sqlite4_authorizer_pop(sqlite4 *db){
  int rc = SQLITE4_OK;
  sqlite4_mutex_enter(db->mutex);

  if( db->pAuth==0 ){
    rc = SQLITE4_ERROR;
  }else{
    authPopStack(db);
  }
  sqlite4ExpirePreparedStatements(db);
  sqlite4_mutex_leave(db->mutex);
  return rc;
}

/*
** Free the entire authorization callback stack. This function is called
** as part of closing the database handle.
*/
void sqlite4AuthFreeAll(sqlite4 *db){
  while( db->pAuth ){
    authPopStack(db);
  }
}

/*
** Write an error message into pParse->zErrMsg that explains that the
** user-supplied authorization function returned an illegal value.
*/
static void authBadReturnCode(Parse *pParse){
  sqlite4ErrorMsg(pParse, "authorizer malfunction");
  pParse->rc = SQLITE4_ERROR;
}

/*
** Invoke the authorization callback stack with the supplied parameters.
** If no error occurs, return SQLITE4_OK, SQLITE4_IGNORE or SQLITE4_DENY.
**
** If an authorizer function returns an invalid value, return SQLITE4_DENY
** and leave an error message in pParse.
*/
static int authInvokeStack(
  Parse *pParse,
  int eAuth,                      /* Action code */
  const char *z1,                 /* Third argument for auth callbacks */
  const char *z2,                 /* Fourth argument for auth callbacks */
  const char *z3,                 /* Fifth argument for auth callbacks */
  const char *z4                  /* Sixth argument for auth callbacks */
){
  int rc = SQLITE4_OK;
  Authorizer *p;
  
  for(p=pParse->db->pAuth; p; p=p->pNext){
    int rcauth = p->xAuth(p->pCtx, eAuth, z1, z2, z3, z4);
    switch( rcauth ){
      case SQLITE4_IGNORE:
        /* fall through */
      case SQLITE4_DENY:
        rc = rcauth;
        /* fall through */
      case SQLITE4_OK:
      case SQLITE4_ALLOW:
        break;

      default:
        authBadReturnCode(pParse);
        rcauth = SQLITE4_DENY;
    }

    if( rcauth!=SQLITE4_OK && rcauth!=SQLITE4_IGNORE ) break;
  }

  assert( rc==SQLITE4_OK || rc==SQLITE4_DENY || rc==SQLITE4_IGNORE );
  return rc;
}

/*
** Invoke the authorization callback for permission to read column zCol from
** table zTab in database zDb. This function assumes that an authorization
** callback has been registered (i.e. that sqlite4.xAuth is not NULL).
**
** If SQLITE4_IGNORE is returned and pExpr is not NULL, then pExpr is changed
................................................................................
*/
int sqlite4AuthReadCol(
  Parse *pParse,                  /* The parser context */
  const char *zTab,               /* Table name */
  const char *zCol,               /* Column name */
  int iDb                         /* Index of containing database. */
){
  const char *zAuthContext = pParse->zAuthContext;
  sqlite4 *db = pParse->db;       /* Database handle */
  char *zDb = db->aDb[iDb].zName; /* Name of attached database */
  int rc;                         /* Auth callback return code */

  rc = authInvokeStack(pParse, SQLITE4_READ, zTab, zCol, zDb, zAuthContext);
  if( rc==SQLITE4_DENY && pParse->rc==SQLITE4_OK ){
    if( db->nDb>2 || iDb!=0 ){
      sqlite4ErrorMsg(pParse, "access to %s.%s.%s is prohibited",zDb,zTab,zCol);
    }else{
      sqlite4ErrorMsg(pParse, "access to %s.%s is prohibited", zTab, zCol);
    }
    pParse->rc = SQLITE4_AUTH;


  }

  return rc;
}

/*
** The pExpr should be a TK_COLUMN expression.  The table referred to
** is in pTabList or else it is the NEW or OLD table of a trigger.  
** Check to see if it is OK to read this particular column.
................................................................................
  sqlite4 *db = pParse->db;
  Table *pTab = 0;      /* The table being read */
  const char *zCol;     /* Name of the column of the table */
  int iSrc;             /* Index in pTabList->a[] of table being read */
  int iDb;              /* The index of the database the expression refers to */
  int iCol;             /* Index of column in table */

  if( db->pAuth==0 ) return;
  iDb = sqlite4SchemaToIndex(pParse->db, pSchema);
  if( iDb<0 ){
    /* An attempt to read a column out of a subquery or other
    ** temporary table. */
    return;
  }

................................................................................
  /* Don't do any authorization checks if the database is initialising
  ** or if the parser is being invoked from within sqlite4_declare_vtab.
  */
  if( db->init.busy || IN_DECLARE_VTAB ){
    return SQLITE4_OK;
  }




  rc = authInvokeStack(pParse, code, zArg1, zArg2, zArg3, pParse->zAuthContext);
  if( rc==SQLITE4_DENY && pParse->rc==SQLITE4_OK ){
    sqlite4ErrorMsg(pParse, "not authorized");
    pParse->rc = SQLITE4_AUTH;



  }

  return rc;
}

/*
** Push an authorization context.  After this routine is called, the
** zArg3 argument to authorization callbacks will be zContext until
** popped.  Or if pParse==0, this routine is a no-op.

Changes to src/build.c

1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
....
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
....
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
....
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
*/
int sqlite4ViewGetColumnNames(Parse *pParse, Table *pTable){
  Table *pSelTab;   /* A fake table from which we get the result set */
  Select *pSel;     /* Copy of the SELECT that implements the view */
  int nErr = 0;     /* Number of errors encountered */
  int n;            /* Temporarily holds the number of cursors assigned */
  sqlite4 *db = pParse->db;  /* Database connection for malloc errors */
  int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);

  assert( pTable );

#ifndef SQLITE4_OMIT_VIRTUALTABLE
  if( sqlite4VtabCallConnect(pParse, pTable) ){
    return SQLITE4_ERROR;
  }
................................................................................
  if( pSel ){
    u8 enableLookaside = db->lookaside.bEnabled;
    n = pParse->nTab;
    sqlite4SrcListAssignCursors(pParse, pSel->pSrc);
    pTable->nCol = -1;
    db->lookaside.bEnabled = 0;
#ifndef SQLITE4_OMIT_AUTHORIZATION
    xAuth = db->xAuth;
    db->xAuth = 0;
    pSelTab = sqlite4ResultSetOfSelect(pParse, pSel);
    db->xAuth = xAuth;
#else
    pSelTab = sqlite4ResultSetOfSelect(pParse, pSel);
#endif
    db->lookaside.bEnabled = enableLookaside;
    pParse->nTab = n;
    if( pSelTab ){
      assert( pTable->aCol==0 );
................................................................................
){
  Index *pRet = 0;     /* Pointer to return */
  Table *pTab = 0;     /* Table to be indexed */
  Index *pIndex = 0;   /* The index to be created */
  char *zName = 0;     /* Name of the index */
  int i, j;
  Token nullId;        /* Fake token for an empty ID list */
  DbFixer sFix;        /* For assigning database names to pTable */
  sqlite4 *db = pParse->db;
  Db *pDb;             /* The specific table containing the indexed database */
  int iDb;             /* Index of the database that is being written */
  Token *pName = 0;    /* Unqualified name of the index to create */
  ExprListItem *pListItem; /* For looping over pList */
  int nExtra = 0;
  char *zExtra;

  assert( pStart==0 || pEnd!=0 ); /* pEnd must be non-NULL if pStart is */
................................................................................

    assert( pName==0 );
    assert( pStart==0 );
    pTab = pParse->pNewTable;
    if( !pTab ) goto exit_create_index;
    iDb = sqlite4SchemaToIndex(db, pTab->pSchema);
  }
  pDb = &db->aDb[iDb];

  assert( pTab!=0 );
  assert( pParse->nErr==0 );
  assert( IsVirtual(pTab)==0 && IsView(pTab)==0 );

  /* If pName==0 it means that we are dealing with a primary key or 
  ** UNIQUE constraint.  We have to invent our own name.  */







|







 







|
|

|







 







<

<







 







<







1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
....
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
....
2598
2599
2600
2601
2602
2603
2604

2605

2606
2607
2608
2609
2610
2611
2612
....
2637
2638
2639
2640
2641
2642
2643

2644
2645
2646
2647
2648
2649
2650
*/
int sqlite4ViewGetColumnNames(Parse *pParse, Table *pTable){
  Table *pSelTab;   /* A fake table from which we get the result set */
  Select *pSel;     /* Copy of the SELECT that implements the view */
  int nErr = 0;     /* Number of errors encountered */
  int n;            /* Temporarily holds the number of cursors assigned */
  sqlite4 *db = pParse->db;  /* Database connection for malloc errors */
  Authorizer *pAuth;

  assert( pTable );

#ifndef SQLITE4_OMIT_VIRTUALTABLE
  if( sqlite4VtabCallConnect(pParse, pTable) ){
    return SQLITE4_ERROR;
  }
................................................................................
  if( pSel ){
    u8 enableLookaside = db->lookaside.bEnabled;
    n = pParse->nTab;
    sqlite4SrcListAssignCursors(pParse, pSel->pSrc);
    pTable->nCol = -1;
    db->lookaside.bEnabled = 0;
#ifndef SQLITE4_OMIT_AUTHORIZATION
    pAuth = db->pAuth;
    db->pAuth = 0;
    pSelTab = sqlite4ResultSetOfSelect(pParse, pSel);
    db->pAuth = pAuth;
#else
    pSelTab = sqlite4ResultSetOfSelect(pParse, pSel);
#endif
    db->lookaside.bEnabled = enableLookaside;
    pParse->nTab = n;
    if( pSelTab ){
      assert( pTable->aCol==0 );
................................................................................
){
  Index *pRet = 0;     /* Pointer to return */
  Table *pTab = 0;     /* Table to be indexed */
  Index *pIndex = 0;   /* The index to be created */
  char *zName = 0;     /* Name of the index */
  int i, j;
  Token nullId;        /* Fake token for an empty ID list */

  sqlite4 *db = pParse->db;

  int iDb;             /* Index of the database that is being written */
  Token *pName = 0;    /* Unqualified name of the index to create */
  ExprListItem *pListItem; /* For looping over pList */
  int nExtra = 0;
  char *zExtra;

  assert( pStart==0 || pEnd!=0 ); /* pEnd must be non-NULL if pStart is */
................................................................................

    assert( pName==0 );
    assert( pStart==0 );
    pTab = pParse->pNewTable;
    if( !pTab ) goto exit_create_index;
    iDb = sqlite4SchemaToIndex(db, pTab->pSchema);
  }


  assert( pTab!=0 );
  assert( pParse->nErr==0 );
  assert( IsVirtual(pTab)==0 && IsView(pTab)==0 );

  /* If pName==0 it means that we are dealing with a primary key or 
  ** UNIQUE constraint.  We have to invent our own name.  */

Changes to src/fkey.c

716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
      aiCol = &iCol;
    }
#ifndef SQLITE4_OMIT_AUTHORIZATION
    for(i=0; i<pFKey->nCol; i++){
      /* Request permission to read the parent key columns. If the 
      ** authorization callback returns SQLITE4_IGNORE, behave as if any
      ** values read from the parent table are NULL. */
      if( db->xAuth ){
        int rcauth;
        char *zCol = pTo->aCol[pIdx->aiColumn[i]].zName;
        rcauth = sqlite4AuthReadCol(pParse, pTo->zName, zCol, iDb);
        isIgnore = (rcauth==SQLITE4_IGNORE);
      }
    }
#endif

    pParse->nTab++;
    if( regOld!=0 ){
      /* A row is being removed from the child table. Search for the parent.
      ** If the parent does not exist, removing the child row resolves an 







<
|
|
|
|
<







716
717
718
719
720
721
722

723
724
725
726

727
728
729
730
731
732
733
      aiCol = &iCol;
    }
#ifndef SQLITE4_OMIT_AUTHORIZATION
    for(i=0; i<pFKey->nCol; i++){
      /* Request permission to read the parent key columns. If the 
      ** authorization callback returns SQLITE4_IGNORE, behave as if any
      ** values read from the parent table are NULL. */

      int rcauth;
      char *zCol = pTo->aCol[pIdx->aiColumn[i]].zName;
      rcauth = sqlite4AuthReadCol(pParse, pTo->zName, zCol, iDb);
      isIgnore = (rcauth==SQLITE4_IGNORE);

    }
#endif

    pParse->nTab++;
    if( regOld!=0 ){
      /* A row is being removed from the child table. Search for the parent.
      ** If the parent does not exist, removing the child row resolves an 

Changes to src/main.c

382
383
384
385
386
387
388



389
390
391
392
393
394
395
      sqlite4KVStoreClose(pDb->pKV);
      pDb->pKV = 0;
    }
    sqlite4DbFree(db, pDb->pSchema);
    pDb->pSchema = 0;
  }
  sqlite4ResetInternalSchema(db, -1);




  /* Tell the code in notify.c that the connection no longer holds any
  ** locks and does not require any further unlock-notify callbacks.
  */
  sqlite4ConnectionClosed(db);
  
  /* Delete tokenizers */







>
>
>







382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
      sqlite4KVStoreClose(pDb->pKV);
      pDb->pKV = 0;
    }
    sqlite4DbFree(db, pDb->pSchema);
    pDb->pSchema = 0;
  }
  sqlite4ResetInternalSchema(db, -1);

  /* Free any authorizer callbacks */
  sqlite4AuthFreeAll(db);

  /* Tell the code in notify.c that the connection no longer holds any
  ** locks and does not require any further unlock-notify callbacks.
  */
  sqlite4ConnectionClosed(db);
  
  /* Delete tokenizers */

Changes to src/prepare.c

233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
  {
    char *zSql;
    zSql = sqlite4MPrintf(db, 
        "SELECT name, rootpage, sql FROM '%q'.%s ORDER BY rowid",
        db->aDb[iDb].zName, zMasterName);
#ifndef SQLITE4_OMIT_AUTHORIZATION
    {
      int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
      xAuth = db->xAuth;
      db->xAuth = 0;
#endif
      rc = sqlite4_exec(db, zSql, sqlite4InitCallback, &initData, 0);
#ifndef SQLITE4_OMIT_AUTHORIZATION
      db->xAuth = xAuth;
    }
#endif
    if( rc==SQLITE4_OK ) rc = initData.rc;
    sqlite4DbFree(db, zSql);
#ifndef SQLITE4_OMIT_ANALYZE
    if( rc==SQLITE4_OK ){
      sqlite4AnalysisLoad(db, iDb);







|
|
|



|







233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
  {
    char *zSql;
    zSql = sqlite4MPrintf(db, 
        "SELECT name, rootpage, sql FROM '%q'.%s ORDER BY rowid",
        db->aDb[iDb].zName, zMasterName);
#ifndef SQLITE4_OMIT_AUTHORIZATION
    {
      Authorizer *pAuth;
      pAuth = db->pAuth;
      db->pAuth = 0;
#endif
      rc = sqlite4_exec(db, zSql, sqlite4InitCallback, &initData, 0);
#ifndef SQLITE4_OMIT_AUTHORIZATION
      db->pAuth = pAuth;
    }
#endif
    if( rc==SQLITE4_OK ) rc = initData.rc;
    sqlite4DbFree(db, zSql);
#ifndef SQLITE4_OMIT_ANALYZE
    if( rc==SQLITE4_OK ){
      sqlite4AnalysisLoad(db, iDb);

Changes to src/sqlite.h.in

1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
....
1294
1295
1296
1297
1298
1299
1300

1301
1302
1303
1304
1305
1306
1307
** ^A call to this routine stores N bytes of pseudo-randomness into buffer P.
*/
void sqlite4_randomness(sqlite4_env*, int N, void *P);

/*
** CAPIREF: Compile-Time Authorization Callbacks
**
** ^This routine registers an authorizer callback with a particular
** [database connection], supplied in the first argument.
** ^The authorizer callback is invoked as SQL statements are being compiled
** by [sqlite4_prepare()] or its variants [sqlite4_prepare()],
** [sqlite4_prepare16()] and [sqlite4_prepare16_v2()].  ^At various
** points during the compilation process, as logic is being created
** to perform various actions, the authorizer callback is invoked to
** see if those actions are allowed.  ^The authorizer callback should
** return [SQLITE4_OK] to allow the action, [SQLITE4_IGNORE] to disallow the
** specific action but allow the SQL statement to continue to be
** compiled, or [SQLITE4_DENY] to cause the entire SQL statement to be
** rejected with an error.  ^If the authorizer callback returns
** any value other than [SQLITE4_IGNORE], [SQLITE4_OK], or [SQLITE4_DENY]
** then the [sqlite4_prepare()] or equivalent call that triggered
** the authorizer will fail with an error message.
**
** When the callback returns [SQLITE4_OK], that means the operation
** requested is ok.  ^When the callback returns [SQLITE4_DENY], the
** [sqlite4_prepare()] or equivalent call that triggered the
** authorizer will fail with an error message explaining that
** access is denied. 
**
** ^The first parameter to the authorizer callback is a copy of the third
** parameter to the sqlite4_set_authorizer() interface. ^The second parameter
** to the callback is an integer [SQLITE4_COPY | action code] that specifies
** the particular action to be authorized. ^The third through sixth parameters
** to the callback are zero-terminated strings that contain additional
** details about the action to be authorized.
**
** ^If the action code is [SQLITE4_READ]
** and the callback returns [SQLITE4_IGNORE] then the
** [prepared statement] statement is constructed to substitute
** a NULL value in place of the table column that would have
** been read if [SQLITE4_OK] had been returned.  The [SQLITE4_IGNORE]
** return can be used to deny an untrusted user access to individual
** columns of a table.
** ^If the action code is [SQLITE4_DELETE] and the callback returns
** [SQLITE4_IGNORE] then the [DELETE] operation proceeds but the
** [truncate optimization] is disabled and all rows are deleted individually.
**
** An authorizer is used when [sqlite4_prepare | preparing]
** SQL statements from an untrusted source, to ensure that the SQL statements
** do not try to access data they are not allowed to see, or that they do not
** try to execute malicious statements that damage the database.  For
** example, an application may allow a user to enter arbitrary
** SQL queries for evaluation by a database.  But the application does
** not want the user to be able to make arbitrary changes to the
** database.  An authorizer could then be put in place while the
** user-entered SQL is being [sqlite4_prepare | prepared] that
** disallows everything except [SELECT] statements.
**
** Applications that need to process SQL from untrusted sources
** might also consider lowering resource limits using [sqlite4_limit()]
** and limiting database size using the [max_page_count] [PRAGMA]
** in addition to using an authorizer.
**
** ^(Only a single authorizer can be in place on a database connection
** at a time.  Each call to sqlite4_set_authorizer overrides the
** previous call.)^  ^Disable the authorizer by installing a NULL callback.
** The authorizer is disabled by default.
**
** The authorizer callback must not do anything that will modify
** the database connection that invoked the authorizer callback.
** Note that [sqlite4_prepare()] and [sqlite4_step()] both modify their
** database connections for the meaning of "modify" in this paragraph.
**
** ^When [sqlite4_prepare()] is used to prepare a statement, the
** statement might be re-prepared during [sqlite4_step()] due to a 
** schema change.  Hence, the application should ensure that the
** correct authorizer callback remains in place during the [sqlite4_step()].
**
** ^Note that the authorizer callback is invoked only during
** [sqlite4_prepare()] or its variants.  Authorization is not
** performed during statement evaluation in [sqlite4_step()], unless
** as stated in the previous paragraph, sqlite4_step() invokes
** sqlite4_prepare() to reprepare a statement after a schema change.
*/
int sqlite4_set_authorizer(
  sqlite4*,
  int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
  void *pUserData
);

/*
** CAPIREF: Authorizer Return Codes
**
** The [sqlite4_set_authorizer | authorizer callback function] must
** return either [SQLITE4_OK] or one of these two constants in order
** to signal SQLite whether or not the action is permitted.  See the
................................................................................
** information.
**
** Note that SQLITE4_IGNORE is also used as a [SQLITE4_ROLLBACK | return code]
** from the [sqlite4_vtab_on_conflict()] interface.
*/
#define SQLITE4_DENY   1   /* Abort the SQL statement with an error */
#define SQLITE4_IGNORE 2   /* Don't allow access, but don't generate an error */


/*
** CAPIREF: Authorizer Action Codes
**
** The [sqlite4_set_authorizer()] interface registers a callback function
** that is invoked to authorize certain SQL statement actions.  The
** second parameter to the callback is an integer code that specifies







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
<
<
<
<







 







>







1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279






1280
1281
1282
1283
1284
1285
1286
....
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
** ^A call to this routine stores N bytes of pseudo-randomness into buffer P.
*/
void sqlite4_randomness(sqlite4_env*, int N, void *P);

/*
** CAPIREF: Compile-Time Authorization Callbacks
**
** These routines are used to register and deregister authorization 
** callbacks with the database connection passed as the first argument. 
**
** Each database connection has a stack of authorization callbacks, which
** may be empty. Calling sqlite4_authorizer_push() adds an authorization
** callback to the top of the stack, and calling sqlite4_authorizer_pop()
** removes the topmost authorizer. When an authorization callback is 
** pushed onto the stack, the application may pass a pointer to a destructor 
** function as the fourth argument to sqlite3_authorizer_push(). If the
** destructor function pointer is not NULL, then it is invoked with a copy
** of the second argument to sqlite4_authorizer_push() as the only argument
** when the authorizer function is popped off the stack, or when the database
** connection is closed.
**
** Authorization callbacks are invoked by SQLite4 from within 
** sqlite4_prepare() and, when repreparing statements, from within 
** sqlite3_step(). During SQL statement compilation (or recompilation), 
** SQLite4 invokes the authorization callbacks for each action required
** to execute the statement. "Actions" are things like reading a value
** from a specific table column, modifying, inserting or deleting a row 
** within a specific database table, or creating or dropping a schema 
** object. The complete list of actions [SQLITE4_CREATE_INDEX | is here].
**
** The first parameter passed to an authorizer callback is a copy of the 
** second parameter passed to the sqlite4_authorizer_push() interface. The
** second parameter to the callback is an integer [SQLITE4_COPY | action code]
** that specifies the particular action to be authorized. The third through 
** sixth parameters to the callback are zero-terminated strings that contain 
** additional details about the action to be authorized.
**
** An authorization callback must return one of SQLITE4_OK, SQLITE4_IGNORE,
** SQLITE4_DENY or SQLITE4_ALLOW. If any other value is returned, it is an
** error. In this case, statement compilation fails and SQLITE4_ERROR is
** returned to the user.
**
** If an authorization callback returns SQLITE4_OK or SQLITE4_ALLOW, then
** SQLite4 interprets this as an indication that permission is granted for 
** the specified action. If SQLITE4_DENY is returned, then permission has 
** been denied and statement compilation fails. If SQLITE4_IGNORE is returned, 
** and the requested action is to read a table column ([SQLITE4_READ]), then
** permission is denied but statement compilation is allowed to continue. 
** In this case, instead of reading the required value from a table column, 
** the database engine substitues an SQL NULL value instead. If SQLITE4_IGNORE 
** is returned by an authorization callback requesting anything other than to 
** read a table column, then statement compilation is allowed to continue,
** but the requested action is silently omitted.
**
** If there is more than one authorization callback on the stack when a
** statement is compiled (or recompiled), they are invoked in turn, starting 
** with the callback on the top of the stack. If a single authorization 
** callback returns SQLITE4_DENY, then permission for the action is denied
** and no further authorization callbacks are invoked. If one or more
** authorization callbacks return SQLITE4_IGNORE, but all others return
** SQLITE4_OK or SQLITE4_ALLOW, then the column value is replaced by an
** SQL NULL, as described above. If all authorization callbacks return
** SQLITE_OK or SQLITE_ALLOW, then the specified action is authorized and
** statement compilation proceeds.
**
** The difference between SQLITE4_OK and SQLITE4_ALLOW is as follows - if
** an authorization callback returns SQLITE4_ALLOW, then no further callbacks
** are invoked for the action. The action is either authorized (if all
** prior authorization callbacks returned SQLITE_OK) or ignored (if one or
** more earlier callbacks returned SQLITE4_IGNORE).
**
** An authorizer callback must not do anything that will modify the state
** of the database connection that invoked the authorizer callback. Note that 
** [sqlite4_prepare()] and [sqlite4_step()] both modify the state of their 
** database connections for the meaning of "modify" in this paragraph.
*/
int sqlite4_authorizer_push(
  sqlite4*,
  void *pCtx,
  int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
  void (*xDestroy)(void*)
);
int sqlite4_authorizer_pop(sqlite4*);







/*
** CAPIREF: Authorizer Return Codes
**
** The [sqlite4_set_authorizer | authorizer callback function] must
** return either [SQLITE4_OK] or one of these two constants in order
** to signal SQLite whether or not the action is permitted.  See the
................................................................................
** information.
**
** Note that SQLITE4_IGNORE is also used as a [SQLITE4_ROLLBACK | return code]
** from the [sqlite4_vtab_on_conflict()] interface.
*/
#define SQLITE4_DENY   1   /* Abort the SQL statement with an error */
#define SQLITE4_IGNORE 2   /* Don't allow access, but don't generate an error */
#define SQLITE4_ALLOW  3   /* Allow access, do not invoke further callbacks */

/*
** CAPIREF: Authorizer Action Codes
**
** The [sqlite4_set_authorizer()] interface registers a callback function
** that is invoked to authorize certain SQL statement actions.  The
** second parameter to the callback is an integer code that specifies

Changes to src/sqliteInt.h

547
548
549
550
551
552
553

554
555
556
557
558
559
560
...
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
....
2867
2868
2869
2870
2871
2872
2873

2874
2875
2876
2877
2878

2879
2880
2881
2882
2883
2884
2885

/*
** Forward references to structures
*/
typedef struct AggInfo AggInfo;
typedef struct AggInfoCol AggInfoCol;
typedef struct AggInfoFunc AggInfoFunc;

typedef struct AuthContext AuthContext;
typedef struct AutoincInfo AutoincInfo;
typedef struct CollSeq CollSeq;
typedef struct Column Column;
typedef struct CreateIndex CreateIndex;
typedef struct Db Db;
typedef struct Schema Schema;
................................................................................
  char *zErrMsg16;              /* Most recent error message (UTF-16 encoded) */
  union {
    volatile int isInterrupted; /* True if sqlite4_interrupt has been called */
    double notUsed1;            /* Spacer */
  } u1;
  Lookaside lookaside;          /* Lookaside malloc configuration */
#ifndef SQLITE4_OMIT_AUTHORIZATION
  int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
                                /* Access authorization function */
  void *pAuthArg;               /* 1st argument to the access auth function */
#endif
#ifndef SQLITE4_OMIT_PROGRESS_CALLBACK
  int (*xProgress)(void *);     /* The progress callback */
  void *pProgressArg;           /* Argument to the progress callback */
  int nProgressOps;             /* Number of opcodes for progress callback */
#endif
#ifndef SQLITE4_OMIT_VIRTUALTABLE
................................................................................
void sqlite4DeferForeignKey(Parse*, int);
#ifndef SQLITE4_OMIT_AUTHORIZATION
  void sqlite4AuthRead(Parse*,Expr*,Schema*,SrcList*);
  int sqlite4AuthCheck(Parse*,int, const char*, const char*, const char*);
  void sqlite4AuthContextPush(Parse*, AuthContext*, const char*);
  void sqlite4AuthContextPop(AuthContext*);
  int sqlite4AuthReadCol(Parse*, const char *, const char *, int);

#else
# define sqlite4AuthRead(a,b,c,d)
# define sqlite4AuthCheck(a,b,c,d,e)    SQLITE4_OK
# define sqlite4AuthContextPush(a,b,c)
# define sqlite4AuthContextPop(a)  ((void)(a))

#endif
void sqlite4Attach(Parse*, Expr*, Expr*, Expr*);
void sqlite4Detach(Parse*, Expr*);
int sqlite4FixInit(DbFixer*, Parse*, int, const char*, const Token*);
int sqlite4FixSrcList(DbFixer*, SrcList*);
int sqlite4FixSelect(DbFixer*, Select*);
int sqlite4FixExpr(DbFixer*, Expr*);







>







 







|
<
<







 







>





>







547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
...
828
829
830
831
832
833
834
835


836
837
838
839
840
841
842
....
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886

/*
** Forward references to structures
*/
typedef struct AggInfo AggInfo;
typedef struct AggInfoCol AggInfoCol;
typedef struct AggInfoFunc AggInfoFunc;
typedef struct Authorizer Authorizer;
typedef struct AuthContext AuthContext;
typedef struct AutoincInfo AutoincInfo;
typedef struct CollSeq CollSeq;
typedef struct Column Column;
typedef struct CreateIndex CreateIndex;
typedef struct Db Db;
typedef struct Schema Schema;
................................................................................
  char *zErrMsg16;              /* Most recent error message (UTF-16 encoded) */
  union {
    volatile int isInterrupted; /* True if sqlite4_interrupt has been called */
    double notUsed1;            /* Spacer */
  } u1;
  Lookaside lookaside;          /* Lookaside malloc configuration */
#ifndef SQLITE4_OMIT_AUTHORIZATION
  Authorizer *pAuth;            /* Head of authorizer callback stack */


#endif
#ifndef SQLITE4_OMIT_PROGRESS_CALLBACK
  int (*xProgress)(void *);     /* The progress callback */
  void *pProgressArg;           /* Argument to the progress callback */
  int nProgressOps;             /* Number of opcodes for progress callback */
#endif
#ifndef SQLITE4_OMIT_VIRTUALTABLE
................................................................................
void sqlite4DeferForeignKey(Parse*, int);
#ifndef SQLITE4_OMIT_AUTHORIZATION
  void sqlite4AuthRead(Parse*,Expr*,Schema*,SrcList*);
  int sqlite4AuthCheck(Parse*,int, const char*, const char*, const char*);
  void sqlite4AuthContextPush(Parse*, AuthContext*, const char*);
  void sqlite4AuthContextPop(AuthContext*);
  int sqlite4AuthReadCol(Parse*, const char *, const char *, int);
  void sqlite4AuthFreeAll(sqlite4 *db);
#else
# define sqlite4AuthRead(a,b,c,d)
# define sqlite4AuthCheck(a,b,c,d,e)    SQLITE4_OK
# define sqlite4AuthContextPush(a,b,c)
# define sqlite4AuthContextPop(a)  ((void)(a))
# define sqlite4AuthFreeAll(a)
#endif
void sqlite4Attach(Parse*, Expr*, Expr*, Expr*);
void sqlite4Detach(Parse*, Expr*);
int sqlite4FixInit(DbFixer*, Parse*, int, const char*, const Token*);
int sqlite4FixSrcList(DbFixer*, SrcList*);
int sqlite4FixSelect(DbFixer*, Select*);
int sqlite4FixExpr(DbFixer*, Expr*);

Changes to src/tclsqlite.c

1305
1306
1307
1308
1309
1310
1311

1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323

1324


1325
1326
1327
1328
1329
1330
1331
        Tcl_AppendResult(interp, pDb->zAuth, 0);
      }
    }else{
      char *zAuth;
      int len;
      if( pDb->zAuth ){
        Tcl_Free(pDb->zAuth);

      }
      zAuth = Tcl_GetStringFromObj(objv[2], &len);
      if( zAuth && len>0 ){
        pDb->zAuth = Tcl_Alloc( len + 1 );
        memcpy(pDb->zAuth, zAuth, len+1);
      }else{
        pDb->zAuth = 0;
      }
      if( pDb->zAuth ){
        pDb->interp = interp;
        sqlite4_set_authorizer(pDb->db, auth_callback, pDb);
      }else{

        sqlite4_set_authorizer(pDb->db, 0, 0);


      }
    }
#endif
    break;
  }

  /*     $db cache flush







>










|
<
>
|
>
>







1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323

1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
        Tcl_AppendResult(interp, pDb->zAuth, 0);
      }
    }else{
      char *zAuth;
      int len;
      if( pDb->zAuth ){
        Tcl_Free(pDb->zAuth);
        sqlite4_authorizer_pop(pDb->db);
      }
      zAuth = Tcl_GetStringFromObj(objv[2], &len);
      if( zAuth && len>0 ){
        pDb->zAuth = Tcl_Alloc( len + 1 );
        memcpy(pDb->zAuth, zAuth, len+1);
      }else{
        pDb->zAuth = 0;
      }
      if( pDb->zAuth ){
        pDb->interp = interp;
        rc = sqlite4_authorizer_push(pDb->db, pDb, auth_callback, 0);

        if( rc!=SQLITE4_OK ){
          Tcl_SetResult(interp, (char *)sqlite4_errmsg(pDb->db), TCL_VOLATILE);
          return TCL_ERROR;
        }
      }
    }
#endif
    break;
  }

  /*     $db cache flush

Changes to test/auth.test

950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
....
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
....
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
....
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
....
1966
1967
1968
1969
1970
1971
1972







1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
....
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
....
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
  }
  set ::authargs {}
  execsql {
    INSERT INTO t2 VALUES(1,2,3);
  }
  set ::authargs 
} {SQLITE4_INSERT t2 {} main {} SQLITE4_INSERT tx {} main r2 SQLITE4_READ t2 ROWID main r2}
do_test auth-1.136.4 {
  execsql {
    SELECT * FROM tx;
  }
} {3}
do_test auth-1.137 {
  execsql {SELECT name FROM sqlite_master}
} {t2 tx r2}
do_test auth-1.138 {
  proc auth {code arg1 arg2 arg3 arg4} {
    if {$code=="SQLITE4_CREATE_TEMP_TRIGGER"} {
      set ::authargs [list $arg1 $arg2 $arg3 $arg4]
................................................................................
} {1 {not authorized}}
do_test auth-1.230 {
  set ::authargs
} {full_column_names on {} {}}
do_test auth-1.231 {
  execsql2 {SELECT a FROM t2}
} {a 11 a 7}
do_test auth-1.232 {
  proc auth {code arg1 arg2 arg3 arg4} {
    if {$code=="SQLITE4_PRAGMA"} {
      set ::authargs [list $arg1 $arg2 $arg3 $arg4]
      return SQLITE4_IGNORE
    }
    return SQLITE4_OK
  }
  catchsql {PRAGMA full_column_names=on}
} {0 {}}
do_test auth-1.233 {
  set ::authargs
} {full_column_names on {} {}}
do_test auth-1.234 {
  execsql2 {SELECT a FROM t2}
} {a 11 a 7}
do_test auth-1.235 {
  proc auth {code arg1 arg2 arg3 arg4} {
    if {$code=="SQLITE4_PRAGMA"} {
      set ::authargs [list $arg1 $arg2 $arg3 $arg4]
      return SQLITE4_OK
    }
    return SQLITE4_OK
  }
  catchsql {PRAGMA full_column_names=on}
} {0 {}}
do_test auth-1.236 {
  execsql2 {SELECT a FROM t2}
} {t2.a 11 t2.a 7}
do_test auth-1.237 {
  proc auth {code arg1 arg2 arg3 arg4} {
    if {$code=="SQLITE4_PRAGMA"} {
      set ::authargs [list $arg1 $arg2 $arg3 $arg4]
      return SQLITE4_OK
    }
    return SQLITE4_OK
  }
  catchsql {PRAGMA full_column_names=OFF}
} {0 {}}
do_test auth-1.238 {
  set ::authargs
} {full_column_names OFF {} {}}
do_test auth-1.239 {
  execsql2 {SELECT a FROM t2}
} {a 11 a 7}

do_test auth-1.240 {
  proc auth {code arg1 arg2 arg3 arg4} {
    if {$code=="SQLITE4_TRANSACTION"} {
................................................................................
} {t3_idx1 {} main {}}
do_test auth-1.283 {
  set ::authargs {}
  execsql {
    REINDEX BINARY;
  }
  set ::authargs
} {t3_idx1 {} main {} sqlite_autoindex_t3_1 {} main {}}
do_test auth-1.284 {
  set ::authargs {}
  execsql {
    REINDEX NOCASE;
  }
  set ::authargs
} {t3_idx2 {} main {}}
do_test auth-1.285 {
  set ::authargs {}
  execsql {
    REINDEX t3;
  }
  set ::authargs
} {t3_idx2 {} main {} t3_idx1 {} main {} sqlite_autoindex_t3_1 {} main {}}
do_test auth-1.286 {
  execsql {
    DROP TABLE t3;
  }
} {}
ifcapable tempdb {
  do_test auth-1.287 {
................................................................................
  } {t3_idx1 {} temp {}}
  do_test auth-1.289 {
    set ::authargs {}
    execsql {
      REINDEX BINARY;
    }
    set ::authargs
  } {t3_idx1 {} temp {} sqlite_autoindex_t3_1 {} temp {}}
  do_test auth-1.290 {
    set ::authargs {}
    execsql {
      REINDEX NOCASE;
    }
    set ::authargs
  } {t3_idx2 {} temp {}}
  do_test auth-1.291 {
    set ::authargs {}
    execsql {
      REINDEX temp.t3;
    }
    set ::authargs
  } {t3_idx2 {} temp {} t3_idx1 {} temp {} sqlite_autoindex_t3_1 {} temp {}}
  proc auth {code args} {
    if {$code=="SQLITE4_REINDEX"} {
      set ::authargs [concat $::authargs $args]
      return SQLITE4_DENY
    }
    return SQLITE4_OK
  }
................................................................................
      DROP TABLE t3;
    }
  } {}
}

} ;# ifcapable reindex 








ifcapable analyze {
  proc auth {code args} {
    if {$code=="SQLITE4_ANALYZE"} {
      set ::authargs [concat $::authargs $args]
    }
    return SQLITE4_OK
  }
  do_test auth-1.294 {
    set ::authargs {}
    execsql {
      CREATE TABLE t4(a,b,c);
      CREATE INDEX t4i1 ON t4(a);
      CREATE INDEX t4i2 ON t4(b,a,c);
      INSERT INTO t4 VALUES(1,2,3);
      ANALYZE;
    }
    set ::authargs
  } {t4 {} main {} t2 {} main {}}
  do_test auth-1.295 {
    execsql {
      SELECT count(*) FROM sqlite_stat1;
................................................................................
  execsql {CREATE TABLE t3(x INTEGER PRIMARY KEY, y, z)}
  catchsql {SELECT * FROM t3}
} {1 {access to t3.x is prohibited}}
do_test auth-2.1 {
  catchsql {SELECT y,z FROM t3}
} {0 {}}
do_test auth-2.2 {
  catchsql {SELECT ROWID,y,z FROM t3}
} {1 {access to t3.x is prohibited}}
do_test auth-2.3 {
  catchsql {SELECT OID,y,z FROM t3}
} {1 {access to t3.x is prohibited}}
do_test auth-2.4 {
  proc auth {code arg1 arg2 arg3 arg4} {
    if {$code=="SQLITE4_READ" && $arg1=="t3" && $arg2=="x"} {
      return SQLITE4_IGNORE
    }
    return SQLITE4_OK
  }
  execsql {INSERT INTO t3 VALUES(44,55,66)}
  catchsql {SELECT * FROM t3}
} {0 {{} 55 66}}
do_test auth-2.5 {
  catchsql {SELECT rowid,y,z FROM t3}
} {0 {{} 55 66}}
do_test auth-2.6 {
  proc auth {code arg1 arg2 arg3 arg4} {
    if {$code=="SQLITE4_READ" && $arg1=="t3" && $arg2=="ROWID"} {
      return SQLITE4_IGNORE
    }
    return SQLITE4_OK
  }
  catchsql {SELECT * FROM t3}
} {0 {44 55 66}}
do_test auth-2.7 {
  catchsql {SELECT ROWID,y,z FROM t3}
} {0 {44 55 66}}
do_test auth-2.8 {
  proc auth {code arg1 arg2 arg3 arg4} {
    if {$code=="SQLITE4_READ" && $arg1=="t2" && $arg2=="ROWID"} {
      return SQLITE4_IGNORE
    }
    return SQLITE4_OK
................................................................................
  execsql {
    SELECT count(a) AS cnt FROM t4 ORDER BY cnt
  }
} {1}

# Ticket #1607
#
ifcapable compound&&subquery {
  ifcapable trigger {
    execsql {
      DROP TABLE tx;
    }
    ifcapable view {
      execsql {
        DROP TABLE v1chng;







<
<
<
<
<







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|













|







 







|













|







 







>
>
>
>
>
>
>










<
<
<
<







 







|


|












|











|







 







|







950
951
952
953
954
955
956





957
958
959
960
961
962
963
....
1509
1510
1511
1512
1513
1514
1515










































1516
1517
1518
1519
1520
1521
1522
....
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
....
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
....
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942




1943
1944
1945
1946
1947
1948
1949
....
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
....
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
  }
  set ::authargs {}
  execsql {
    INSERT INTO t2 VALUES(1,2,3);
  }
  set ::authargs 
} {SQLITE4_INSERT t2 {} main {} SQLITE4_INSERT tx {} main r2 SQLITE4_READ t2 ROWID main r2}





do_test auth-1.137 {
  execsql {SELECT name FROM sqlite_master}
} {t2 tx r2}
do_test auth-1.138 {
  proc auth {code arg1 arg2 arg3 arg4} {
    if {$code=="SQLITE4_CREATE_TEMP_TRIGGER"} {
      set ::authargs [list $arg1 $arg2 $arg3 $arg4]
................................................................................
} {1 {not authorized}}
do_test auth-1.230 {
  set ::authargs
} {full_column_names on {} {}}
do_test auth-1.231 {
  execsql2 {SELECT a FROM t2}
} {a 11 a 7}










































do_test auth-1.239 {
  execsql2 {SELECT a FROM t2}
} {a 11 a 7}

do_test auth-1.240 {
  proc auth {code arg1 arg2 arg3 arg4} {
    if {$code=="SQLITE4_TRANSACTION"} {
................................................................................
} {t3_idx1 {} main {}}
do_test auth-1.283 {
  set ::authargs {}
  execsql {
    REINDEX BINARY;
  }
  set ::authargs
} {t3_idx1 {} main {}}
do_test auth-1.284 {
  set ::authargs {}
  execsql {
    REINDEX NOCASE;
  }
  set ::authargs
} {t3_idx2 {} main {}}
do_test auth-1.285 {
  set ::authargs {}
  execsql {
    REINDEX t3;
  }
  set ::authargs
} {t3_idx2 {} main {} t3_idx1 {} main {}}
do_test auth-1.286 {
  execsql {
    DROP TABLE t3;
  }
} {}
ifcapable tempdb {
  do_test auth-1.287 {
................................................................................
  } {t3_idx1 {} temp {}}
  do_test auth-1.289 {
    set ::authargs {}
    execsql {
      REINDEX BINARY;
    }
    set ::authargs
  } {t3_idx1 {} temp {}}
  do_test auth-1.290 {
    set ::authargs {}
    execsql {
      REINDEX NOCASE;
    }
    set ::authargs
  } {t3_idx2 {} temp {}}
  do_test auth-1.291 {
    set ::authargs {}
    execsql {
      REINDEX temp.t3;
    }
    set ::authargs
  } {t3_idx2 {} temp {} t3_idx1 {} temp {}}
  proc auth {code args} {
    if {$code=="SQLITE4_REINDEX"} {
      set ::authargs [concat $::authargs $args]
      return SQLITE4_DENY
    }
    return SQLITE4_OK
  }
................................................................................
      DROP TABLE t3;
    }
  } {}
}

} ;# ifcapable reindex 

proc auth {code args} { return SQLITE4_OK }
do_execsql_test auth-1.294a {
  CREATE TABLE t4(a,b,c);
  CREATE INDEX t4i1 ON t4(a);
  CREATE INDEX t4i2 ON t4(b,a,c);
  INSERT INTO t4 VALUES(1,2,3);
}
ifcapable analyze {
  proc auth {code args} {
    if {$code=="SQLITE4_ANALYZE"} {
      set ::authargs [concat $::authargs $args]
    }
    return SQLITE4_OK
  }
  do_test auth-1.294 {
    set ::authargs {}
    execsql {




      ANALYZE;
    }
    set ::authargs
  } {t4 {} main {} t2 {} main {}}
  do_test auth-1.295 {
    execsql {
      SELECT count(*) FROM sqlite_stat1;
................................................................................
  execsql {CREATE TABLE t3(x INTEGER PRIMARY KEY, y, z)}
  catchsql {SELECT * FROM t3}
} {1 {access to t3.x is prohibited}}
do_test auth-2.1 {
  catchsql {SELECT y,z FROM t3}
} {0 {}}
do_test auth-2.2 {
  catchsql {SELECT x,y,z FROM t3}
} {1 {access to t3.x is prohibited}}
do_test auth-2.3 {
  catchsql {SELECT x,y,z FROM t3}
} {1 {access to t3.x is prohibited}}
do_test auth-2.4 {
  proc auth {code arg1 arg2 arg3 arg4} {
    if {$code=="SQLITE4_READ" && $arg1=="t3" && $arg2=="x"} {
      return SQLITE4_IGNORE
    }
    return SQLITE4_OK
  }
  execsql {INSERT INTO t3 VALUES(44,55,66)}
  catchsql {SELECT * FROM t3}
} {0 {{} 55 66}}
do_test auth-2.5 {
  catchsql {SELECT x,y,z FROM t3}
} {0 {{} 55 66}}
do_test auth-2.6 {
  proc auth {code arg1 arg2 arg3 arg4} {
    if {$code=="SQLITE4_READ" && $arg1=="t3" && $arg2=="ROWID"} {
      return SQLITE4_IGNORE
    }
    return SQLITE4_OK
  }
  catchsql {SELECT * FROM t3}
} {0 {44 55 66}}
do_test auth-2.7 {
  catchsql {SELECT x,y,z FROM t3}
} {0 {44 55 66}}
do_test auth-2.8 {
  proc auth {code arg1 arg2 arg3 arg4} {
    if {$code=="SQLITE4_READ" && $arg1=="t2" && $arg2=="ROWID"} {
      return SQLITE4_IGNORE
    }
    return SQLITE4_OK
................................................................................
  execsql {
    SELECT count(a) AS cnt FROM t4 ORDER BY cnt
  }
} {1}

# Ticket #1607
#
ifcapable compound&&subquery&&analyze {
  ifcapable trigger {
    execsql {
      DROP TABLE tx;
    }
    ifcapable view {
      execsql {
        DROP TABLE v1chng;

Changes to test/permutations.test

138
139
140
141
142
143
144

145
146
147
148
149
150
151
  lsm1.test lsm2.test lsm3.test lsm4.test lsm5.test
  csr1.test
  ckpt1.test
  mc1.test
  fts5expr1.test fts5query1.test fts5rnd1.test fts5create.test
  fts5snippet.test


  aggerror.test
  attach.test
  autoindex1.test
  badutf.test
  between.test
  bigrow.test
  bind.test







>







138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
  lsm1.test lsm2.test lsm3.test lsm4.test lsm5.test
  csr1.test
  ckpt1.test
  mc1.test
  fts5expr1.test fts5query1.test fts5rnd1.test fts5create.test
  fts5snippet.test

  auth.test auth2.test auth3.test
  aggerror.test
  attach.test
  autoindex1.test
  badutf.test
  between.test
  bigrow.test
  bind.test