/ Check-in [65884d4f]
Login

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

Overview
Comment:Add the SQLITE_USER_AUTHENTICATION extension to the trunk. This extension is disabled by default. Special compilation procedures are need to enable it.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 65884d4f81a4705b0356b6cb8ec4909945ff5c19
User & Date: drh 2014-09-11 17:27:54
Context
2014-09-11
18:44
Add new APIs that take 64-bit length parameters: sqlite3_malloc64(), sqlite3_realloc64(), sqlite3_bind_blob64(), sqlite3_bind_text64(), sqlite3_result_blob64(), and sqlite3_result_text64(). Add the sqlite3_msize() interface. Internal memory allocation routines now use 64-bit unsigned length parameters for safety. Fix the sqlite3_get_table() to use sqlite3_realloc64() to avoid a integer overflow problem. check-in: 7e4978c0 user: drh tags: trunk
17:27
Add the SQLITE_USER_AUTHENTICATION extension to the trunk. This extension is disabled by default. Special compilation procedures are need to enable it. check-in: 65884d4f user: drh tags: trunk
17:14
Clean up some #includes in the extension API implementation. Closed-Leaf check-in: b149ef5c user: drh tags: user-auth
2014-09-06
17:06
Fixes to os_unix.c to support database (and other) files larger than 2GiB on Android. check-in: ad7063aa user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Added ext/userauth/sqlite3userauth.h.

            1  +/*
            2  +** 2014-09-08
            3  +**
            4  +** The author disclaims copyright to this source code.  In place of
            5  +** a legal notice, here is a blessing:
            6  +**
            7  +**    May you do good and not evil.
            8  +**    May you find forgiveness for yourself and forgive others.
            9  +**    May you share freely, never taking more than you give.
           10  +**
           11  +*************************************************************************
           12  +**
           13  +** This file contains the application interface definitions for the
           14  +** user-authentication extension feature.
           15  +**
           16  +** To compile with the user-authentication feature, append this file to
           17  +** end of an SQLite amalgamation header file ("sqlite3.h"), then add
           18  +** the SQLITE_USER_AUTHENTICATION compile-time option.  See the
           19  +** user-auth.txt file in the same source directory as this file for
           20  +** additional information.
           21  +*/
           22  +#ifdef SQLITE_USER_AUTHENTICATION
           23  +
           24  +/*
           25  +** If a database contains the SQLITE_USER table, then the
           26  +** sqlite3_user_authenticate() interface must be invoked with an
           27  +** appropriate username and password prior to enable read and write
           28  +** access to the database.
           29  +**
           30  +** Return SQLITE_OK on success or SQLITE_ERROR if the username/password
           31  +** combination is incorrect or unknown.
           32  +**
           33  +** If the SQLITE_USER table is not present in the database file, then
           34  +** this interface is a harmless no-op returnning SQLITE_OK.
           35  +*/
           36  +int sqlite3_user_authenticate(
           37  +  sqlite3 *db,           /* The database connection */
           38  +  const char *zUsername, /* Username */
           39  +  const char *aPW,       /* Password or credentials */
           40  +  int nPW                /* Number of bytes in aPW[] */
           41  +);
           42  +
           43  +/*
           44  +** The sqlite3_user_add() interface can be used (by an admin user only)
           45  +** to create a new user.  When called on a no-authentication-required
           46  +** database, this routine converts the database into an authentication-
           47  +** required database, automatically makes the added user an
           48  +** administrator, and logs in the current connection as that user.
           49  +** The sqlite3_user_add() interface only works for the "main" database, not
           50  +** for any ATTACH-ed databases.  Any call to sqlite3_user_add() by a
           51  +** non-admin user results in an error.
           52  +*/
           53  +int sqlite3_user_add(
           54  +  sqlite3 *db,           /* Database connection */
           55  +  const char *zUsername, /* Username to be added */
           56  +  const char *aPW,       /* Password or credentials */
           57  +  int nPW,               /* Number of bytes in aPW[] */
           58  +  int isAdmin            /* True to give new user admin privilege */
           59  +);
           60  +
           61  +/*
           62  +** The sqlite3_user_change() interface can be used to change a users
           63  +** login credentials or admin privilege.  Any user can change their own
           64  +** login credentials.  Only an admin user can change another users login
           65  +** credentials or admin privilege setting.  No user may change their own 
           66  +** admin privilege setting.
           67  +*/
           68  +int sqlite3_user_change(
           69  +  sqlite3 *db,           /* Database connection */
           70  +  const char *zUsername, /* Username to change */
           71  +  const char *aPW,       /* New password or credentials */
           72  +  int nPW,               /* Number of bytes in aPW[] */
           73  +  int isAdmin            /* Modified admin privilege for the user */
           74  +);
           75  +
           76  +/*
           77  +** The sqlite3_user_delete() interface can be used (by an admin user only)
           78  +** to delete a user.  The currently logged-in user cannot be deleted,
           79  +** which guarantees that there is always an admin user and hence that
           80  +** the database cannot be converted into a no-authentication-required
           81  +** database.
           82  +*/
           83  +int sqlite3_user_delete(
           84  +  sqlite3 *db,           /* Database connection */
           85  +  const char *zUsername  /* Username to remove */
           86  +);
           87  +
           88  +#endif /* SQLITE_USER_AUTHENTICATION */

Added ext/userauth/user-auth.txt.

            1  +Activate the user authentication logic by including the
            2  +ext/userauth/userauth.c source code file in the build and
            3  +adding the -DSQLITE_USER_AUTHENTICATION compile-time option.
            4  +The ext/userauth/sqlite3userauth.h header file is available to
            5  +applications to define the interface.
            6  +
            7  +When using the SQLite amalgamation, it is sufficient to append
            8  +the ext/userauth/userauth.c source file onto the end of the
            9  +amalgamation.
           10  +
           11  +The following new APIs are available when user authentication is
           12  +activated:
           13  +
           14  +   int sqlite3_user_authenticate(
           15  +     sqlite3 *db,           /* The database connection */
           16  +     const char *zUsername, /* Username */
           17  +     const char *aPW,       /* Password or credentials */
           18  +     int nPW                /* Number of bytes in aPW[] */
           19  +   );
           20  +   
           21  +   int sqlite3_user_add(
           22  +     sqlite3 *db,           /* Database connection */
           23  +     const char *zUsername, /* Username to be added */
           24  +     const char *aPW,       /* Password or credentials */
           25  +     int nPW,               /* Number of bytes in aPW[] */
           26  +     int isAdmin            /* True to give new user admin privilege */
           27  +   );
           28  +   
           29  +   int sqlite3_user_change(
           30  +     sqlite3 *db,           /* Database connection */
           31  +     const char *zUsername, /* Username to change */
           32  +     const void *aPW,       /* Modified password or credentials */
           33  +     int nPW,               /* Number of bytes in aPW[] */
           34  +     int isAdmin            /* Modified admin privilege for the user */
           35  +   );
           36  +   
           37  +   int sqlite3_user_delete(
           38  +     sqlite3 *db,           /* Database connection */
           39  +     const char *zUsername  /* Username to remove */
           40  +   );
           41  +
           42  +With this extension, a database can be marked as requiring authentication.
           43  +By default a database does not require authentication.
           44  +
           45  +The sqlite3_open(), sqlite3_open16(), and sqlite3_open_v2() interfaces
           46  +work as before: they open a new database connection.  However, if the
           47  +database being opened requires authentication, then attempts to read
           48  +or write from the database will fail with an SQLITE_AUTH error until 
           49  +after sqlite3_user_authenticate() has been called successfully.  The 
           50  +sqlite3_user_authenticate() call will return SQLITE_OK if the 
           51  +authentication credentials are accepted and SQLITE_ERROR if not.
           52  +
           53  +Calling sqlite3_user_authenticate() on a no-authentication-required
           54  +database connection is a harmless no-op.  
           55  +
           56  +If the database is encrypted, then sqlite3_key_v2() must be called first,
           57  +with the correct decryption key, prior to invoking sqlite3_user_authenticate().
           58  +
           59  +To recapitulate: When opening an existing unencrypted authentication-
           60  +required database, the call sequence is:
           61  +
           62  +    sqlite3_open_v2()
           63  +    sqlite3_user_authenticate();
           64  +    /* Database is now usable */
           65  +
           66  +To open an existing, encrypted, authentication-required database, the
           67  +call sequence is:
           68  +
           69  +    sqlite3_open_v2();
           70  +    sqlite3_key_v2();
           71  +    sqlite3_user_authenticate();
           72  +    /* Database is now usable */
           73  +
           74  +When opening a no-authentication-required database, the database
           75  +connection is treated as if it was authenticated as an admin user.
           76  +
           77  +When ATTACH-ing new database files to a connection, each newly attached
           78  +database that is an authentication-required database is checked using
           79  +the same username and password as supplied to the main database.  If that
           80  +check fails, then the ATTACH command fails with an SQLITE_AUTH error.
           81  +
           82  +The sqlite3_user_add() interface can be used (by an admin user only)
           83  +to create a new user.  When called on a no-authentication-required
           84  +database and when A is true, the sqlite3_user_add(D,U,P,N,A) routine
           85  +converts the database into an authentication-required database and
           86  +logs in the database connection D as user U with password P,N.
           87  +To convert a no-authentication-required database into an authentication-
           88  +required database, the isAdmin parameter must be true.  If
           89  +sqlite3_user_add(D,U,P,N,A) is called on a no-authentication-required
           90  +database and A is false, then the call fails with an SQLITE_AUTH error.
           91  +
           92  +Any call to sqlite3_user_add() by a non-admin user results in an error.
           93  +
           94  +Hence, to create a new, unencrypted, authentication-required database,
           95  +the call sequence is:
           96  +
           97  +    sqlite3_open_v2();
           98  +    sqlite3_user_add();
           99  +
          100  +And to create a new, encrypted, authentication-required database, the call
          101  +sequence is:
          102  +
          103  +    sqlite3_open_v2();
          104  +    sqlite3_key_v2();
          105  +    sqlite3_user_add();
          106  +
          107  +The sqlite3_user_delete() interface can be used (by an admin user only)
          108  +to delete a user.  The currently logged-in user cannot be deleted,
          109  +which guarantees that there is always an admin user and hence that
          110  +the database cannot be converted into a no-authentication-required
          111  +database.
          112  +
          113  +The sqlite3_user_change() interface can be used to change a users
          114  +login credentials or admin privilege.  Any user can change their own
          115  +password.  Only an admin user can change another users login
          116  +credentials or admin privilege setting.  No user may change their own 
          117  +admin privilege setting.
          118  +
          119  +The sqlite3_set_authorizer() callback is modified to take a 7th parameter
          120  +which is the username of the currently logged in user, or NULL for a
          121  +no-authentication-required database.
          122  +
          123  +-----------------------------------------------------------------------------
          124  +Implementation notes:
          125  +
          126  +An authentication-required database is identified by the presence of a
          127  +new table:
          128  +
          129  +    CREATE TABLE sqlite_user(
          130  +      uname TEXT PRIMARY KEY,
          131  +      isAdmin BOOLEAN,
          132  +      pw BLOB
          133  +    ) WITHOUT ROWID;
          134  +
          135  +The sqlite_user table is inaccessible (unreadable and unwriteable) to
          136  +non-admin users and is read-only for admin users.  However, if the same
          137  +database file is opened by a version of SQLite that omits
          138  +the -DSQLITE_USER_AUTHENTICATION compile-time option, then the sqlite_user
          139  +table will be readable by anybody and writeable by anybody if
          140  +the "PRAGMA writable_schema=ON" statement is run first.
          141  +
          142  +The sqlite_user.pw field is encoded by a built-in SQL function
          143  +"sqlite_crypt(X,Y)".  The two arguments are both BLOBs.  The first argument
          144  +is the plaintext password supplied to the sqlite3_user_authenticate()
          145  +interface.  The second argument is the sqlite_user.pw value and is supplied
          146  +so that the function can extract the "salt" used by the password encoder.
          147  +The result of sqlite_crypt(X,Y) is another blob which is the value that
          148  +ends up being stored in sqlite_user.pw.  To verify credentials X supplied
          149  +by the sqlite3_user_authenticate() routine, SQLite runs:
          150  +
          151  +    sqlite_user.pw == sqlite_crypt(X, sqlite_user.pw)
          152  +
          153  +To compute an appropriate sqlite_user.pw value from a new or modified
          154  +password X, sqlite_crypt(X,NULL) is run.  A new random salt is selected
          155  +when the second argument is NULL.
          156  +
          157  +The built-in version of of sqlite_crypt() uses a simple Ceasar-cypher
          158  +which prevents passwords from being revealed by searching the raw database
          159  +for ASCII text, but is otherwise trivally broken.  For better password
          160  +security, the database should be encrypted using the SQLite Encryption
          161  +Extension or similar technology.  Or, the application can use the
          162  +sqlite3_create_function() interface to provide an alternative
          163  +implementation of sqlite_crypt() that computes a stronger password hash,
          164  +perhaps using a cryptographic hash function like SHA1.

Added ext/userauth/userauth.c.

            1  +/*
            2  +** 2014-09-08
            3  +**
            4  +** The author disclaims copyright to this source code.  In place of
            5  +** a legal notice, here is a blessing:
            6  +**
            7  +**    May you do good and not evil.
            8  +**    May you find forgiveness for yourself and forgive others.
            9  +**    May you share freely, never taking more than you give.
           10  +**
           11  +*************************************************************************
           12  +**
           13  +** This file contains the bulk of the implementation of the
           14  +** user-authentication extension feature.  Some parts of the user-
           15  +** authentication code are contained within the SQLite core (in the
           16  +** src/ subdirectory of the main source code tree) but those parts
           17  +** that could reasonable be separated out are moved into this file.
           18  +**
           19  +** To compile with the user-authentication feature, append this file to
           20  +** end of an SQLite amalgamation, then add the SQLITE_USER_AUTHENTICATION
           21  +** compile-time option.  See the user-auth.txt file in the same source
           22  +** directory as this file for additional information.
           23  +*/
           24  +#ifdef SQLITE_USER_AUTHENTICATION
           25  +#ifndef _SQLITEINT_H_
           26  +# include "sqliteInt.h"
           27  +#endif
           28  +
           29  +/*
           30  +** Prepare an SQL statement for use by the user authentication logic.
           31  +** Return a pointer to the prepared statement on success.  Return a
           32  +** NULL pointer if there is an error of any kind.
           33  +*/
           34  +static sqlite3_stmt *sqlite3UserAuthPrepare(
           35  +  sqlite3 *db,
           36  +  const char *zFormat,
           37  +  ...
           38  +){
           39  +  sqlite3_stmt *pStmt;
           40  +  char *zSql;
           41  +  int rc;
           42  +  va_list ap;
           43  +  int savedFlags = db->flags;
           44  +
           45  +  va_start(ap, zFormat);
           46  +  zSql = sqlite3_vmprintf(zFormat, ap);
           47  +  va_end(ap);
           48  +  if( zSql==0 ) return 0;
           49  +  db->flags |= SQLITE_WriteSchema;
           50  +  rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
           51  +  db->flags = savedFlags;
           52  +  sqlite3_free(zSql);
           53  +  if( rc ){
           54  +    sqlite3_finalize(pStmt);
           55  +    pStmt = 0;
           56  +  }
           57  +  return pStmt;
           58  +}
           59  +
           60  +/*
           61  +** Check to see if the sqlite_user table exists in database zDb.
           62  +*/
           63  +static int userTableExists(sqlite3 *db, const char *zDb){
           64  +  int rc;
           65  +  sqlite3_mutex_enter(db->mutex);
           66  +  sqlite3BtreeEnterAll(db);
           67  +  if( db->init.busy==0 ){
           68  +    char *zErr = 0;
           69  +    sqlite3Init(db, &zErr);
           70  +    sqlite3DbFree(db, zErr);
           71  +  }
           72  +  rc = sqlite3FindTable(db, "sqlite_user", zDb)!=0;
           73  +  sqlite3BtreeLeaveAll(db);
           74  +  sqlite3_mutex_leave(db->mutex);
           75  +  return rc;
           76  +}
           77  +
           78  +/*
           79  +** Check to see if database zDb has a "sqlite_user" table and if it does
           80  +** whether that table can authenticate zUser with nPw,zPw.  Write one of
           81  +** the UAUTH_* user authorization level codes into *peAuth and return a
           82  +** result code.
           83  +*/
           84  +static int userAuthCheckLogin(
           85  +  sqlite3 *db,               /* The database connection to check */
           86  +  const char *zDb,           /* Name of specific database to check */
           87  +  u8 *peAuth                 /* OUT: One of UAUTH_* constants */
           88  +){
           89  +  sqlite3_stmt *pStmt;
           90  +  int rc;
           91  +
           92  +  *peAuth = UAUTH_Unknown;
           93  +  if( !userTableExists(db, "main") ){
           94  +    *peAuth = UAUTH_Admin;  /* No sqlite_user table.  Everybody is admin. */
           95  +    return SQLITE_OK;
           96  +  }
           97  +  if( db->auth.zAuthUser==0 ){
           98  +    *peAuth = UAUTH_Fail;
           99  +    return SQLITE_OK;
          100  +  }
          101  +  pStmt = sqlite3UserAuthPrepare(db,
          102  +            "SELECT pw=sqlite_crypt(?1,pw), isAdmin FROM \"%w\".sqlite_user"
          103  +            " WHERE uname=?2", zDb);
          104  +  if( pStmt==0 ) return SQLITE_NOMEM;
          105  +  sqlite3_bind_blob(pStmt, 1, db->auth.zAuthPW, db->auth.nAuthPW,SQLITE_STATIC);
          106  +  sqlite3_bind_text(pStmt, 2, db->auth.zAuthUser, -1, SQLITE_STATIC);
          107  +  rc = sqlite3_step(pStmt);
          108  +  if( rc==SQLITE_ROW && sqlite3_column_int(pStmt,0) ){
          109  +    *peAuth = sqlite3_column_int(pStmt, 1) + UAUTH_User;
          110  +  }else{
          111  +    *peAuth = UAUTH_Fail;
          112  +  }
          113  +  return sqlite3_finalize(pStmt);
          114  +}
          115  +int sqlite3UserAuthCheckLogin(
          116  +  sqlite3 *db,               /* The database connection to check */
          117  +  const char *zDb,           /* Name of specific database to check */
          118  +  u8 *peAuth                 /* OUT: One of UAUTH_* constants */
          119  +){
          120  +  int rc;
          121  +  u8 savedAuthLevel;
          122  +  assert( zDb!=0 );
          123  +  assert( peAuth!=0 );
          124  +  savedAuthLevel = db->auth.authLevel;
          125  +  db->auth.authLevel = UAUTH_Admin;
          126  +  rc = userAuthCheckLogin(db, zDb, peAuth);
          127  +  db->auth.authLevel = savedAuthLevel;
          128  +  return rc;
          129  +}
          130  +
          131  +/*
          132  +** If the current authLevel is UAUTH_Unknown, the take actions to figure
          133  +** out what authLevel should be
          134  +*/
          135  +void sqlite3UserAuthInit(sqlite3 *db){
          136  +  if( db->auth.authLevel==UAUTH_Unknown ){
          137  +    u8 authLevel = UAUTH_Fail;
          138  +    sqlite3UserAuthCheckLogin(db, "main", &authLevel);
          139  +    db->auth.authLevel = authLevel;
          140  +    if( authLevel<UAUTH_Admin ) db->flags &= ~SQLITE_WriteSchema;
          141  +  }
          142  +}
          143  +
          144  +/*
          145  +** Implementation of the sqlite_crypt(X,Y) function.
          146  +**
          147  +** If Y is NULL then generate a new hash for password X and return that
          148  +** hash.  If Y is not null, then generate a hash for password X using the
          149  +** same salt as the previous hash Y and return the new hash.
          150  +*/
          151  +void sqlite3CryptFunc(
          152  +  sqlite3_context *context,
          153  +  int NotUsed,
          154  +  sqlite3_value **argv
          155  +){
          156  +  const char *zIn;
          157  +  int nIn, ii;
          158  +  u8 *zOut;
          159  +  char zSalt[8];
          160  +  zIn = sqlite3_value_blob(argv[0]);
          161  +  nIn = sqlite3_value_bytes(argv[0]);
          162  +  if( sqlite3_value_type(argv[1])==SQLITE_BLOB
          163  +   && sqlite3_value_bytes(argv[1])==nIn+sizeof(zSalt)
          164  +  ){
          165  +    memcpy(zSalt, sqlite3_value_blob(argv[1]), sizeof(zSalt));
          166  +  }else{
          167  +    sqlite3_randomness(sizeof(zSalt), zSalt);
          168  +  }
          169  +  zOut = sqlite3_malloc( nIn+sizeof(zSalt) );
          170  +  if( zOut==0 ){
          171  +    sqlite3_result_error_nomem(context);
          172  +  }else{
          173  +    memcpy(zOut, zSalt, sizeof(zSalt));
          174  +    for(ii=0; ii<nIn; ii++){
          175  +      zOut[ii+sizeof(zSalt)] = zIn[ii]^zSalt[ii&0x7];
          176  +    }
          177  +    sqlite3_result_blob(context, zOut, nIn+sizeof(zSalt), sqlite3_free);
          178  +  }
          179  +}
          180  +
          181  +/*
          182  +** If a database contains the SQLITE_USER table, then the
          183  +** sqlite3_user_authenticate() interface must be invoked with an
          184  +** appropriate username and password prior to enable read and write
          185  +** access to the database.
          186  +**
          187  +** Return SQLITE_OK on success or SQLITE_ERROR if the username/password
          188  +** combination is incorrect or unknown.
          189  +**
          190  +** If the SQLITE_USER table is not present in the database file, then
          191  +** this interface is a harmless no-op returnning SQLITE_OK.
          192  +*/
          193  +int sqlite3_user_authenticate(
          194  +  sqlite3 *db,           /* The database connection */
          195  +  const char *zUsername, /* Username */
          196  +  const char *zPW,       /* Password or credentials */
          197  +  int nPW                /* Number of bytes in aPW[] */
          198  +){
          199  +  int rc;
          200  +  u8 authLevel = UAUTH_Fail;
          201  +  db->auth.authLevel = UAUTH_Unknown;
          202  +  sqlite3_free(db->auth.zAuthUser);
          203  +  sqlite3_free(db->auth.zAuthPW);
          204  +  memset(&db->auth, 0, sizeof(db->auth));
          205  +  db->auth.zAuthUser = sqlite3_mprintf("%s", zUsername);
          206  +  if( db->auth.zAuthUser==0 ) return SQLITE_NOMEM;
          207  +  db->auth.zAuthPW = sqlite3_malloc( nPW+1 );
          208  +  if( db->auth.zAuthPW==0 ) return SQLITE_NOMEM;
          209  +  memcpy(db->auth.zAuthPW,zPW,nPW);
          210  +  db->auth.nAuthPW = nPW;
          211  +  rc = sqlite3UserAuthCheckLogin(db, "main", &authLevel);
          212  +  db->auth.authLevel = authLevel;
          213  +  sqlite3ExpirePreparedStatements(db);
          214  +  if( rc ){
          215  +    return rc;           /* OOM error, I/O error, etc. */
          216  +  }
          217  +  if( authLevel<UAUTH_User ){
          218  +    return SQLITE_AUTH;  /* Incorrect username and/or password */
          219  +  }
          220  +  return SQLITE_OK;      /* Successful login */
          221  +}
          222  +
          223  +/*
          224  +** The sqlite3_user_add() interface can be used (by an admin user only)
          225  +** to create a new user.  When called on a no-authentication-required
          226  +** database, this routine converts the database into an authentication-
          227  +** required database, automatically makes the added user an
          228  +** administrator, and logs in the current connection as that user.
          229  +** The sqlite3_user_add() interface only works for the "main" database, not
          230  +** for any ATTACH-ed databases.  Any call to sqlite3_user_add() by a
          231  +** non-admin user results in an error.
          232  +*/
          233  +int sqlite3_user_add(
          234  +  sqlite3 *db,           /* Database connection */
          235  +  const char *zUsername, /* Username to be added */
          236  +  const char *aPW,       /* Password or credentials */
          237  +  int nPW,               /* Number of bytes in aPW[] */
          238  +  int isAdmin            /* True to give new user admin privilege */
          239  +){
          240  +  sqlite3_stmt *pStmt;
          241  +  int rc;
          242  +  sqlite3UserAuthInit(db);
          243  +  if( db->auth.authLevel<UAUTH_Admin ) return SQLITE_AUTH;
          244  +  if( !userTableExists(db, "main") ){
          245  +    if( !isAdmin ) return SQLITE_AUTH;
          246  +    pStmt = sqlite3UserAuthPrepare(db, 
          247  +              "CREATE TABLE sqlite_user(\n"
          248  +              "  uname TEXT PRIMARY KEY,\n"
          249  +              "  isAdmin BOOLEAN,\n"
          250  +              "  pw BLOB\n"
          251  +              ") WITHOUT ROWID;");
          252  +    if( pStmt==0 ) return SQLITE_NOMEM;
          253  +    sqlite3_step(pStmt);
          254  +    rc = sqlite3_finalize(pStmt);
          255  +    if( rc ) return rc;
          256  +  }
          257  +  pStmt = sqlite3UserAuthPrepare(db, 
          258  +            "INSERT INTO sqlite_user(uname,isAdmin,pw)"
          259  +            " VALUES(%Q,%d,sqlite_crypt(?1,NULL))",
          260  +            zUsername, isAdmin!=0);
          261  +  if( pStmt==0 ) return SQLITE_NOMEM;
          262  +  sqlite3_bind_blob(pStmt, 1, aPW, nPW, SQLITE_STATIC);
          263  +  sqlite3_step(pStmt);
          264  +  rc = sqlite3_finalize(pStmt);
          265  +  if( rc ) return rc;
          266  +  if( db->auth.zAuthUser==0 ){
          267  +    assert( isAdmin!=0 );
          268  +    sqlite3_user_authenticate(db, zUsername, aPW, nPW);
          269  +  }
          270  +  return SQLITE_OK;
          271  +}
          272  +
          273  +/*
          274  +** The sqlite3_user_change() interface can be used to change a users
          275  +** login credentials or admin privilege.  Any user can change their own
          276  +** login credentials.  Only an admin user can change another users login
          277  +** credentials or admin privilege setting.  No user may change their own 
          278  +** admin privilege setting.
          279  +*/
          280  +int sqlite3_user_change(
          281  +  sqlite3 *db,           /* Database connection */
          282  +  const char *zUsername, /* Username to change */
          283  +  const char *aPW,       /* Modified password or credentials */
          284  +  int nPW,               /* Number of bytes in aPW[] */
          285  +  int isAdmin            /* Modified admin privilege for the user */
          286  +){
          287  +  sqlite3_stmt *pStmt;
          288  +  int rc;
          289  +  u8 authLevel;
          290  +
          291  +  authLevel = db->auth.authLevel;
          292  +  if( authLevel<UAUTH_User ){
          293  +    /* Must be logged in to make a change */
          294  +    return SQLITE_AUTH;
          295  +  }
          296  +  if( strcmp(db->auth.zAuthUser, zUsername)!=0 ){
          297  +    if( db->auth.authLevel<UAUTH_Admin ){
          298  +      /* Must be an administrator to change a different user */
          299  +      return SQLITE_AUTH;
          300  +    }
          301  +  }else if( isAdmin!=(authLevel==UAUTH_Admin) ){
          302  +    /* Cannot change the isAdmin setting for self */
          303  +    return SQLITE_AUTH;
          304  +  }
          305  +  db->auth.authLevel = UAUTH_Admin;
          306  +  if( !userTableExists(db, "main") ){
          307  +    /* This routine is a no-op if the user to be modified does not exist */
          308  +  }else{
          309  +    pStmt = sqlite3UserAuthPrepare(db,
          310  +              "UPDATE sqlite_user SET isAdmin=%d, pw=sqlite_crypt(?1,NULL)"
          311  +              " WHERE uname=%Q", isAdmin, zUsername);
          312  +    if( pStmt==0 ){
          313  +      rc = SQLITE_NOMEM;
          314  +    }else{
          315  +      sqlite3_bind_blob(pStmt, 1, aPW, nPW, SQLITE_STATIC);
          316  +      sqlite3_step(pStmt);
          317  +      rc = sqlite3_finalize(pStmt);
          318  +    }
          319  +  }
          320  +  db->auth.authLevel = authLevel;
          321  +  return rc;
          322  +}
          323  +
          324  +/*
          325  +** The sqlite3_user_delete() interface can be used (by an admin user only)
          326  +** to delete a user.  The currently logged-in user cannot be deleted,
          327  +** which guarantees that there is always an admin user and hence that
          328  +** the database cannot be converted into a no-authentication-required
          329  +** database.
          330  +*/
          331  +int sqlite3_user_delete(
          332  +  sqlite3 *db,           /* Database connection */
          333  +  const char *zUsername  /* Username to remove */
          334  +){
          335  +  sqlite3_stmt *pStmt;
          336  +  if( db->auth.authLevel<UAUTH_Admin ){
          337  +    /* Must be an administrator to delete a user */
          338  +    return SQLITE_AUTH;
          339  +  }
          340  +  if( strcmp(db->auth.zAuthUser, zUsername)==0 ){
          341  +    /* Cannot delete self */
          342  +    return SQLITE_AUTH;
          343  +  }
          344  +  if( !userTableExists(db, "main") ){
          345  +    /* This routine is a no-op if the user to be deleted does not exist */
          346  +    return SQLITE_OK;
          347  +  }
          348  +  pStmt = sqlite3UserAuthPrepare(db,
          349  +              "DELETE FROM sqlite_user WHERE uname=%Q", zUsername);
          350  +  if( pStmt==0 ) return SQLITE_NOMEM;
          351  +  sqlite3_step(pStmt);
          352  +  return sqlite3_finalize(pStmt);
          353  +}
          354  +
          355  +#endif /* SQLITE_USER_AUTHENTICATION */

Changes to main.mk.

    42     42   # build the SQLite library and testing tools.
    43     43   ################################################################################
    44     44   
    45     45   # This is how we compile
    46     46   #
    47     47   TCCX =  $(TCC) $(OPTS) -I. -I$(TOP)/src -I$(TOP) 
    48     48   TCCX += -I$(TOP)/ext/rtree -I$(TOP)/ext/icu -I$(TOP)/ext/fts3
    49         -TCCX += -I$(TOP)/ext/async
           49  +TCCX += -I$(TOP)/ext/async -I$(TOP)/ext/userauth
    50     50   
    51     51   # Object files for the SQLite library.
    52     52   #
    53     53   LIBOBJ+= vdbe.o parse.o \
    54     54            alter.o analyze.o attach.o auth.o \
    55     55            backup.o bitvec.o btmutex.o btree.o build.o \
    56     56            callback.o complete.o ctime.o date.o delete.o expr.o fault.o fkey.o \
................................................................................
    63     63            main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \
    64     64            memjournal.o \
    65     65            mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \
    66     66            notify.o opcodes.o os.o os_unix.o os_win.o \
    67     67            pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \
    68     68            random.o resolve.o rowset.o rtree.o select.o status.o \
    69     69            table.o threads.o tokenize.o trigger.o \
    70         -         update.o util.o vacuum.o \
           70  +         update.o userauth.o util.o vacuum.o \
    71     71            vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \
    72     72   	 vdbetrace.o wal.o walker.o where.o utf.o vtab.o
    73     73   
    74     74   
    75     75   
    76     76   # All of the source code files.
    77     77   #
................................................................................
   210    210   SRC += \
   211    211     $(TOP)/ext/icu/sqliteicu.h \
   212    212     $(TOP)/ext/icu/icu.c
   213    213   SRC += \
   214    214     $(TOP)/ext/rtree/sqlite3rtree.h \
   215    215     $(TOP)/ext/rtree/rtree.h \
   216    216     $(TOP)/ext/rtree/rtree.c
   217         -
          217  +SRC += \
          218  +  $(TOP)/ext/userauth/userauth.c \
          219  +  $(TOP)/ext/userauth/sqlite3userauth.h
   218    220   
   219    221   # Generated source code files
   220    222   #
   221    223   SRC += \
   222    224     keywordhash.h \
   223    225     opcodes.c \
   224    226     opcodes.h \
................................................................................
   373    375     $(TOP)/ext/fts3/fts3Int.h \
   374    376     $(TOP)/ext/fts3/fts3_hash.h \
   375    377     $(TOP)/ext/fts3/fts3_tokenizer.h
   376    378   EXTHDR += \
   377    379     $(TOP)/ext/rtree/rtree.h
   378    380   EXTHDR += \
   379    381     $(TOP)/ext/icu/sqliteicu.h
          382  +EXTHDR += \
          383  +  $(TOP)/ext/userauth/sqlite3userauth.h
   380    384   
   381    385   # This is the default Makefile target.  The objects listed here
   382    386   # are what get build when you type just "make" with no arguments.
   383    387   #
   384    388   all:	sqlite3.h libsqlite3.a sqlite3$(EXE)
   385    389   
   386    390   libsqlite3.a:	$(LIBOBJ)
................................................................................
   553    557   	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode2.c
   554    558   
   555    559   fts3_write.o:	$(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
   556    560   	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_write.c
   557    561   
   558    562   rtree.o:	$(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR)
   559    563   	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c
          564  +
          565  +userauth.o:	$(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR)
          566  +	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/userauth/userauth.c
   560    567   
   561    568   
   562    569   # Rules for building test programs and for running tests
   563    570   #
   564    571   tclsqlite3:	$(TOP)/src/tclsqlite.c libsqlite3.a
   565    572   	$(TCCX) $(TCL_FLAGS) -DTCLSH=1 -o tclsqlite3 \
   566    573   		$(TOP)/src/tclsqlite.c libsqlite3.a $(LIBTCL) $(THREADLIB)

Changes to src/attach.c.

   203    203     ** we found it.
   204    204     */
   205    205     if( rc==SQLITE_OK ){
   206    206       sqlite3BtreeEnterAll(db);
   207    207       rc = sqlite3Init(db, &zErrDyn);
   208    208       sqlite3BtreeLeaveAll(db);
   209    209     }
          210  +#ifdef SQLITE_USER_AUTHENTICATION
          211  +  if( rc==SQLITE_OK ){
          212  +    u8 newAuth = 0;
          213  +    rc = sqlite3UserAuthCheckLogin(db, zName, &newAuth);
          214  +    if( newAuth<db->auth.authLevel ){
          215  +      rc = SQLITE_AUTH_USER;
          216  +    }
          217  +  }
          218  +#endif
   210    219     if( rc ){
   211    220       int iDb = db->nDb - 1;
   212    221       assert( iDb>=2 );
   213    222       if( db->aDb[iDb].pBt ){
   214    223         sqlite3BtreeClose(db->aDb[iDb].pBt);
   215    224         db->aDb[iDb].pBt = 0;
   216    225         db->aDb[iDb].pSchema = 0;

Changes to src/auth.c.

    69     69   */
    70     70   int sqlite3_set_authorizer(
    71     71     sqlite3 *db,
    72     72     int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
    73     73     void *pArg
    74     74   ){
    75     75     sqlite3_mutex_enter(db->mutex);
    76         -  db->xAuth = xAuth;
           76  +  db->xAuth = (sqlite3_xauth)xAuth;
    77     77     db->pAuthArg = pArg;
    78     78     sqlite3ExpirePreparedStatements(db);
    79     79     sqlite3_mutex_leave(db->mutex);
    80     80     return SQLITE_OK;
    81     81   }
    82     82   
    83     83   /*
................................................................................
   104    104     const char *zCol,               /* Column name */
   105    105     int iDb                         /* Index of containing database. */
   106    106   ){
   107    107     sqlite3 *db = pParse->db;       /* Database handle */
   108    108     char *zDb = db->aDb[iDb].zName; /* Name of attached database */
   109    109     int rc;                         /* Auth callback return code */
   110    110   
   111         -  rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext);
          111  +  rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext
          112  +#ifdef SQLITE_USER_AUTHENTICATION
          113  +                 ,db->auth.zAuthUser
          114  +#endif
          115  +                );
   112    116     if( rc==SQLITE_DENY ){
   113    117       if( db->nDb>2 || iDb!=0 ){
   114    118         sqlite3ErrorMsg(pParse, "access to %s.%s.%s is prohibited",zDb,zTab,zCol);
   115    119       }else{
   116    120         sqlite3ErrorMsg(pParse, "access to %s.%s is prohibited", zTab, zCol);
   117    121       }
   118    122       pParse->rc = SQLITE_AUTH;
................................................................................
   204    208     if( db->init.busy || IN_DECLARE_VTAB ){
   205    209       return SQLITE_OK;
   206    210     }
   207    211   
   208    212     if( db->xAuth==0 ){
   209    213       return SQLITE_OK;
   210    214     }
   211         -  rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext);
          215  +  rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext
          216  +#ifdef SQLITE_USER_AUTHENTICATION
          217  +                 ,db->auth.zAuthUser
          218  +#endif
          219  +                );
   212    220     if( rc==SQLITE_DENY ){
   213    221       sqlite3ErrorMsg(pParse, "not authorized");
   214    222       pParse->rc = SQLITE_AUTH;
   215    223     }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){
   216    224       rc = SQLITE_DENY;
   217    225       sqliteAuthBadReturnCode(pParse);
   218    226     }

Changes to src/build.c.

   151    151     */
   152    152     v = sqlite3GetVdbe(pParse);
   153    153     assert( !pParse->isMultiWrite 
   154    154          || sqlite3VdbeAssertMayAbort(v, pParse->mayAbort));
   155    155     if( v ){
   156    156       while( sqlite3VdbeDeletePriorOpcode(v, OP_Close) ){}
   157    157       sqlite3VdbeAddOp0(v, OP_Halt);
          158  +
          159  +#if SQLITE_USER_AUTHENTICATION
          160  +    if( pParse->nTableLock>0 && db->init.busy==0 ){
          161  +      sqlite3UserAuthInit(db);
          162  +      if( db->auth.authLevel<UAUTH_User ){
          163  +        pParse->rc = SQLITE_AUTH_USER;
          164  +        sqlite3ErrorMsg(pParse, "user not authenticated");
          165  +        return;
          166  +      }
          167  +    }
          168  +#endif
   158    169   
   159    170       /* The cookie mask contains one bit for each database file open.
   160    171       ** (Bit 0 is for main, bit 1 is for temp, and so forth.)  Bits are
   161    172       ** set for each database that is used.  Generate code to start a
   162    173       ** transaction on each used database and to verify the schema cookie
   163    174       ** on each used database.
   164    175       */
................................................................................
   267    278     sqlite3RunParser(pParse, zSql, &zErrMsg);
   268    279     sqlite3DbFree(db, zErrMsg);
   269    280     sqlite3DbFree(db, zSql);
   270    281     memcpy(&pParse->nVar, saveBuf, SAVE_SZ);
   271    282     pParse->nested--;
   272    283   }
   273    284   
          285  +#if SQLITE_USER_AUTHENTICATION
          286  +/*
          287  +** Return TRUE if zTable is the name of the system table that stores the
          288  +** list of users and their access credentials.
          289  +*/
          290  +int sqlite3UserAuthTable(const char *zTable){
          291  +  return sqlite3_stricmp(zTable, "sqlite_user")==0;
          292  +}
          293  +#endif
          294  +
   274    295   /*
   275    296   ** Locate the in-memory structure that describes a particular database
   276    297   ** table given the name of that table and (optionally) the name of the
   277    298   ** database containing the table.  Return NULL if not found.
   278    299   **
   279    300   ** If zDatabase is 0, all databases are searched for the table and the
   280    301   ** first matching table is returned.  (No checking for duplicate table
................................................................................
   285    306   */
   286    307   Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){
   287    308     Table *p = 0;
   288    309     int i;
   289    310     assert( zName!=0 );
   290    311     /* All mutexes are required for schema access.  Make sure we hold them. */
   291    312     assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) );
          313  +#if SQLITE_USER_AUTHENTICATION
          314  +  /* Only the admin user is allowed to know that the sqlite_user table
          315  +  ** exists */
          316  +  if( db->auth.authLevel<UAUTH_Admin && sqlite3UserAuthTable(zName)!=0 ){
          317  +    return 0;
          318  +  }
          319  +#endif
   292    320     for(i=OMIT_TEMPDB; i<db->nDb; i++){
   293    321       int j = (i<2) ? i^1 : i;   /* Search TEMP before MAIN */
   294    322       if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue;
   295    323       assert( sqlite3SchemaMutexHeld(db, j, 0) );
   296    324       p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
   297    325       if( p ) break;
   298    326     }
................................................................................
   329    357       if( zDbase ){
   330    358         sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName);
   331    359       }else{
   332    360         sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
   333    361       }
   334    362       pParse->checkSchema = 1;
   335    363     }
          364  +#if SQLITE_USER_AUTHENICATION
          365  +  else if( pParse->db->auth.authLevel<UAUTH_User ){
          366  +    sqlite3ErrorMsg(pParse, "user not authenticated");
          367  +    p = 0;
          368  +  }
          369  +#endif
   336    370     return p;
   337    371   }
   338    372   
   339    373   /*
   340    374   ** Locate the table identified by *p.
   341    375   **
   342    376   ** This is a wrapper around sqlite3LocateTable(). The difference between
................................................................................
  2048   2082   */
  2049   2083   int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
  2050   2084     Table *pSelTab;   /* A fake table from which we get the result set */
  2051   2085     Select *pSel;     /* Copy of the SELECT that implements the view */
  2052   2086     int nErr = 0;     /* Number of errors encountered */
  2053   2087     int n;            /* Temporarily holds the number of cursors assigned */
  2054   2088     sqlite3 *db = pParse->db;  /* Database connection for malloc errors */
  2055         -  int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
         2089  +  sqlite3_xauth xAuth;       /* Saved xAuth pointer */
  2056   2090   
  2057   2091     assert( pTable );
  2058   2092   
  2059   2093   #ifndef SQLITE_OMIT_VIRTUALTABLE
  2060   2094     if( sqlite3VtabCallConnect(pParse, pTable) ){
  2061   2095       return SQLITE_ERROR;
  2062   2096     }
................................................................................
  2863   2897       iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
  2864   2898     }
  2865   2899     pDb = &db->aDb[iDb];
  2866   2900   
  2867   2901     assert( pTab!=0 );
  2868   2902     assert( pParse->nErr==0 );
  2869   2903     if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 
         2904  +       && db->init.busy==0
         2905  +#if SQLITE_USER_AUTHENTICATION
         2906  +       && sqlite3UserAuthTable(pTab->zName)==0
         2907  +#endif
  2870   2908          && sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0 ){
  2871   2909       sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
  2872   2910       goto exit_create_index;
  2873   2911     }
  2874   2912   #ifndef SQLITE_OMIT_VIEW
  2875   2913     if( pTab->pSelect ){
  2876   2914       sqlite3ErrorMsg(pParse, "views may not be indexed");

Changes to src/ctime.c.

   363    363     "TEST",
   364    364   #endif
   365    365   #if defined(SQLITE_THREADSAFE)
   366    366     "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
   367    367   #endif
   368    368   #ifdef SQLITE_USE_ALLOCA
   369    369     "USE_ALLOCA",
          370  +#endif
          371  +#ifdef SQLITE_USER_AUTHENTICATION
          372  +  "USER_AUTHENTICATION",
   370    373   #endif
   371    374   #ifdef SQLITE_WIN32_MALLOC
   372    375     "WIN32_MALLOC",
   373    376   #endif
   374    377   #ifdef SQLITE_ZERO_MALLOC
   375    378     "ZERO_MALLOC"
   376    379   #endif

Changes to src/func.c.

  1691   1691       FUNCTION2(likely,            1, 0, 0, noopFunc,  SQLITE_FUNC_UNLIKELY),
  1692   1692       VFUNCTION(random,            0, 0, 0, randomFunc       ),
  1693   1693       VFUNCTION(randomblob,        1, 0, 0, randomBlob       ),
  1694   1694       FUNCTION(nullif,             2, 0, 1, nullifFunc       ),
  1695   1695       FUNCTION(sqlite_version,     0, 0, 0, versionFunc      ),
  1696   1696       FUNCTION(sqlite_source_id,   0, 0, 0, sourceidFunc     ),
  1697   1697       FUNCTION(sqlite_log,         2, 0, 0, errlogFunc       ),
         1698  +#if SQLITE_USER_AUTHENTICATION
         1699  +    FUNCTION(sqlite_crypt,       2, 0, 0, sqlite3CryptFunc ),
         1700  +#endif
  1698   1701   #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
  1699   1702       FUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc  ),
  1700   1703       FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc  ),
  1701   1704   #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
  1702   1705       FUNCTION(quote,              1, 0, 0, quoteFunc        ),
  1703   1706       VFUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
  1704   1707       VFUNCTION(changes,           0, 0, 0, changes          ),

Changes to src/legacy.c.

   121    121     }
   122    122   
   123    123   exec_out:
   124    124     if( pStmt ) sqlite3VdbeFinalize((Vdbe *)pStmt);
   125    125     sqlite3DbFree(db, azCols);
   126    126   
   127    127     rc = sqlite3ApiExit(db, rc);
   128         -  if( rc!=SQLITE_OK && ALWAYS(rc==sqlite3_errcode(db)) && pzErrMsg ){
          128  +  if( rc!=SQLITE_OK && pzErrMsg ){
   129    129       int nErrMsg = 1 + sqlite3Strlen30(sqlite3_errmsg(db));
   130    130       *pzErrMsg = sqlite3Malloc(nErrMsg);
   131    131       if( *pzErrMsg ){
   132    132         memcpy(*pzErrMsg, sqlite3_errmsg(db), nErrMsg);
   133    133       }else{
   134    134         rc = SQLITE_NOMEM;
   135    135         sqlite3Error(db, SQLITE_NOMEM);

Changes to src/main.c.

   981    981     }
   982    982     sqlite3HashClear(&db->aModule);
   983    983   #endif
   984    984   
   985    985     sqlite3Error(db, SQLITE_OK); /* Deallocates any cached error strings. */
   986    986     sqlite3ValueFree(db->pErr);
   987    987     sqlite3CloseExtensions(db);
          988  +#if SQLITE_USER_AUTHENTICATION
          989  +  sqlite3_free(db->auth.zAuthUser);
          990  +  sqlite3_free(db->auth.zAuthPW);
          991  +#endif
   988    992   
   989    993     db->magic = SQLITE_MAGIC_ERROR;
   990    994   
   991    995     /* The temp-database schema is allocated differently from the other schema
   992    996     ** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()).
   993    997     ** So it needs to be freed here. Todo: Why not roll the temp schema into
   994    998     ** the same sqliteMalloc() as the one that allocates the database 
................................................................................
  2561   2565         rc = SQLITE_NOMEM;
  2562   2566       }
  2563   2567       sqlite3Error(db, rc);
  2564   2568       goto opendb_out;
  2565   2569     }
  2566   2570     db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt);
  2567   2571     db->aDb[1].pSchema = sqlite3SchemaGet(db, 0);
  2568         -
  2569   2572   
  2570   2573     /* The default safety_level for the main database is 'full'; for the temp
  2571   2574     ** database it is 'NONE'. This matches the pager layer defaults.  
  2572   2575     */
  2573   2576     db->aDb[0].zName = "main";
  2574   2577     db->aDb[0].safety_level = 3;
  2575   2578     db->aDb[1].zName = "temp";

Changes to src/pragma.c.

  1393   1393       }else{
  1394   1394         int mask = aPragmaNames[mid].iArg;    /* Mask of bits to set or clear. */
  1395   1395         if( db->autoCommit==0 ){
  1396   1396           /* Foreign key support may not be enabled or disabled while not
  1397   1397           ** in auto-commit mode.  */
  1398   1398           mask &= ~(SQLITE_ForeignKeys);
  1399   1399         }
         1400  +#if SQLITE_USER_AUTHENTICATION
         1401  +      if( db->auth.authLevel==UAUTH_User ){
         1402  +        /* Do not allow non-admin users to modify the schema arbitrarily */
         1403  +        mask &= ~(SQLITE_WriteSchema);
         1404  +      }
         1405  +#endif
  1400   1406   
  1401   1407         if( sqlite3GetBoolean(zRight, 0) ){
  1402   1408           db->flags |= mask;
  1403   1409         }else{
  1404   1410           db->flags &= ~mask;
  1405   1411           if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0;
  1406   1412         }

Changes to src/prepare.c.

   324    324     {
   325    325       char *zSql;
   326    326       zSql = sqlite3MPrintf(db, 
   327    327           "SELECT name, rootpage, sql FROM '%q'.%s ORDER BY rowid",
   328    328           db->aDb[iDb].zName, zMasterName);
   329    329   #ifndef SQLITE_OMIT_AUTHORIZATION
   330    330       {
   331         -      int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
          331  +      sqlite3_xauth xAuth;
   332    332         xAuth = db->xAuth;
   333    333         db->xAuth = 0;
   334    334   #endif
   335    335         rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
   336    336   #ifndef SQLITE_OMIT_AUTHORIZATION
   337    337         db->xAuth = xAuth;
   338    338       }
................................................................................
   390    390   ** file was of zero-length, then the DB_Empty flag is also set.
   391    391   */
   392    392   int sqlite3Init(sqlite3 *db, char **pzErrMsg){
   393    393     int i, rc;
   394    394     int commit_internal = !(db->flags&SQLITE_InternChanges);
   395    395     
   396    396     assert( sqlite3_mutex_held(db->mutex) );
          397  +  assert( db->init.busy==0 );
   397    398     rc = SQLITE_OK;
   398    399     db->init.busy = 1;
   399    400     for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
   400    401       if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
   401    402       rc = sqlite3InitOne(db, i, pzErrMsg);
   402    403       if( rc ){
   403    404         sqlite3ResetOneSchema(db, i);
................................................................................
   405    406     }
   406    407   
   407    408     /* Once all the other databases have been initialized, load the schema
   408    409     ** for the TEMP database. This is loaded last, as the TEMP database
   409    410     ** schema may contain references to objects in other databases.
   410    411     */
   411    412   #ifndef SQLITE_OMIT_TEMPDB
   412         -  if( rc==SQLITE_OK && ALWAYS(db->nDb>1)
   413         -                    && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
          413  +  assert( db->nDb>1 );
          414  +  if( rc==SQLITE_OK && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
   414    415       rc = sqlite3InitOne(db, 1, pzErrMsg);
   415    416       if( rc ){
   416    417         sqlite3ResetOneSchema(db, 1);
   417    418       }
   418    419     }
   419    420   #endif
   420    421   

Changes to src/shell.c.

    29     29   #endif
    30     30   
    31     31   #include <stdlib.h>
    32     32   #include <string.h>
    33     33   #include <stdio.h>
    34     34   #include <assert.h>
    35     35   #include "sqlite3.h"
           36  +#if SQLITE_USER_AUTHENTICATION
           37  +# include "sqlite3userauth.h"
           38  +#endif
    36     39   #include <ctype.h>
    37     40   #include <stdarg.h>
    38     41   
    39     42   #if !defined(_WIN32) && !defined(WIN32)
    40     43   # include <signal.h>
    41     44   # if !defined(__RTP__) && !defined(_WRS_KERNEL)
    42     45   #  include <pwd.h>
................................................................................
  3431   3434         sqlite3_trace(p->db, 0, 0);
  3432   3435       }else{
  3433   3436         sqlite3_trace(p->db, sql_trace_callback, p->traceOut);
  3434   3437       }
  3435   3438   #endif
  3436   3439     }else
  3437   3440   
         3441  +#if SQLITE_USER_AUTHENTICATION
         3442  +  if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
         3443  +    if( nArg<2 ){
         3444  +      fprintf(stderr, "Usage: .user SUBCOMMAND ...\n");
         3445  +      rc = 1;
         3446  +      goto meta_command_exit;
         3447  +    }
         3448  +    open_db(p, 0);
         3449  +    if( strcmp(azArg[1],"login")==0 ){
         3450  +      if( nArg!=4 ){
         3451  +        fprintf(stderr, "Usage: .user login USER PASSWORD\n");
         3452  +        rc = 1;
         3453  +        goto meta_command_exit;
         3454  +      }
         3455  +      rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
         3456  +                                    (int)strlen(azArg[3]));
         3457  +      if( rc ){
         3458  +        fprintf(stderr, "Authentication failed for user %s\n", azArg[2]);
         3459  +        rc = 1;
         3460  +      }
         3461  +    }else if( strcmp(azArg[1],"add")==0 ){
         3462  +      if( nArg!=5 ){
         3463  +        fprintf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
         3464  +        rc = 1;
         3465  +        goto meta_command_exit;
         3466  +      }
         3467  +      rc = sqlite3_user_add(p->db, azArg[2],
         3468  +                            azArg[3], (int)strlen(azArg[3]),
         3469  +                            booleanValue(azArg[4]));
         3470  +      if( rc ){
         3471  +        fprintf(stderr, "User-Add failed: %d\n", rc);
         3472  +        rc = 1;
         3473  +      }
         3474  +    }else if( strcmp(azArg[1],"edit")==0 ){
         3475  +      if( nArg!=5 ){
         3476  +        fprintf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
         3477  +        rc = 1;
         3478  +        goto meta_command_exit;
         3479  +      }
         3480  +      rc = sqlite3_user_change(p->db, azArg[2],
         3481  +                              azArg[3], (int)strlen(azArg[3]),
         3482  +                              booleanValue(azArg[4]));
         3483  +      if( rc ){
         3484  +        fprintf(stderr, "User-Edit failed: %d\n", rc);
         3485  +        rc = 1;
         3486  +      }
         3487  +    }else if( strcmp(azArg[1],"delete")==0 ){
         3488  +      if( nArg!=3 ){
         3489  +        fprintf(stderr, "Usage: .user delete USER\n");
         3490  +        rc = 1;
         3491  +        goto meta_command_exit;
         3492  +      }
         3493  +      rc = sqlite3_user_delete(p->db, azArg[2]);
         3494  +      if( rc ){
         3495  +        fprintf(stderr, "User-Delete failed: %d\n", rc);
         3496  +        rc = 1;
         3497  +      }
         3498  +    }else{
         3499  +      fprintf(stderr, "Usage: .user login|add|edit|delete ...\n");
         3500  +      rc = 1;
         3501  +      goto meta_command_exit;
         3502  +    }    
         3503  +  }else
         3504  +#endif /* SQLITE_USER_AUTHENTICATION */
         3505  +
  3438   3506     if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
  3439   3507       fprintf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
  3440   3508           sqlite3_libversion(), sqlite3_sourceid());
  3441   3509     }else
  3442   3510   
  3443   3511     if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
  3444   3512       const char *zDbName = nArg==2 ? azArg[1] : "main";

Changes to src/sqlite.h.in.

   488    488   #define SQLITE_CONSTRAINT_TRIGGER      (SQLITE_CONSTRAINT | (7<<8))
   489    489   #define SQLITE_CONSTRAINT_UNIQUE       (SQLITE_CONSTRAINT | (8<<8))
   490    490   #define SQLITE_CONSTRAINT_VTAB         (SQLITE_CONSTRAINT | (9<<8))
   491    491   #define SQLITE_CONSTRAINT_ROWID        (SQLITE_CONSTRAINT |(10<<8))
   492    492   #define SQLITE_NOTICE_RECOVER_WAL      (SQLITE_NOTICE | (1<<8))
   493    493   #define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
   494    494   #define SQLITE_WARNING_AUTOINDEX       (SQLITE_WARNING | (1<<8))
          495  +#define SQLITE_AUTH_USER               (SQLITE_AUTH | (1<<8))
   495    496   
   496    497   /*
   497    498   ** CAPI3REF: Flags For File Open Operations
   498    499   **
   499    500   ** These bit values are intended for use in the
   500    501   ** 3rd parameter to the [sqlite3_open_v2()] interface and
   501    502   ** in the 4th parameter to the [sqlite3_vfs.xOpen] method.

Changes to src/sqliteInt.h.

   983    983   **
   984    984   ** Hash each FuncDef structure into one of the FuncDefHash.a[] slots.
   985    985   ** Collisions are on the FuncDef.pHash chain.
   986    986   */
   987    987   struct FuncDefHash {
   988    988     FuncDef *a[23];       /* Hash table for functions */
   989    989   };
          990  +
          991  +#ifdef SQLITE_USER_AUTHENTICATION
          992  +/*
          993  +** Information held in the "sqlite3" database connection object and used
          994  +** to manage user authentication.
          995  +*/
          996  +typedef struct sqlite3_userauth sqlite3_userauth;
          997  +struct sqlite3_userauth {
          998  +  u8 authLevel;                 /* Current authentication level */
          999  +  int nAuthPW;                  /* Size of the zAuthPW in bytes */
         1000  +  char *zAuthPW;                /* Password used to authenticate */
         1001  +  char *zAuthUser;              /* User name used to authenticate */
         1002  +};
         1003  +
         1004  +/* Allowed values for sqlite3_userauth.authLevel */
         1005  +#define UAUTH_Unknown     0     /* Authentication not yet checked */
         1006  +#define UAUTH_Fail        1     /* User authentication failed */
         1007  +#define UAUTH_User        2     /* Authenticated as a normal user */
         1008  +#define UAUTH_Admin       3     /* Authenticated as an administrator */
         1009  +
         1010  +/* Functions used only by user authorization logic */
         1011  +int sqlite3UserAuthTable(const char*);
         1012  +int sqlite3UserAuthCheckLogin(sqlite3*,const char*,u8*);
         1013  +void sqlite3UserAuthInit(sqlite3*);
         1014  +void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**);
         1015  +
         1016  +#endif /* SQLITE_USER_AUTHENTICATION */
         1017  +
         1018  +/*
         1019  +** typedef for the authorization callback function.
         1020  +*/
         1021  +#ifdef SQLITE_USER_AUTHENTICATION
         1022  +  typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
         1023  +                               const char*, const char*);
         1024  +#else
         1025  +  typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
         1026  +                               const char*);
         1027  +#endif
         1028  +
   990   1029   
   991   1030   /*
   992   1031   ** Each database connection is an instance of the following structure.
   993   1032   */
   994   1033   struct sqlite3 {
   995   1034     sqlite3_vfs *pVfs;            /* OS Interface */
   996   1035     struct Vdbe *pVdbe;           /* List of active virtual machines */
................................................................................
  1051   1090     sqlite3_value *pErr;          /* Most recent error message */
  1052   1091     union {
  1053   1092       volatile int isInterrupted; /* True if sqlite3_interrupt has been called */
  1054   1093       double notUsed1;            /* Spacer */
  1055   1094     } u1;
  1056   1095     Lookaside lookaside;          /* Lookaside malloc configuration */
  1057   1096   #ifndef SQLITE_OMIT_AUTHORIZATION
  1058         -  int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
  1059         -                                /* Access authorization function */
         1097  +  sqlite3_xauth xAuth;          /* Access authorization function */
  1060   1098     void *pAuthArg;               /* 1st argument to the access auth function */
  1061   1099   #endif
  1062   1100   #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  1063   1101     int (*xProgress)(void *);     /* The progress callback */
  1064   1102     void *pProgressArg;           /* Argument to the progress callback */
  1065   1103     unsigned nProgressOps;        /* Number of opcodes for progress callback */
  1066   1104   #endif
................................................................................
  1078   1116     Savepoint *pSavepoint;        /* List of active savepoints */
  1079   1117     int busyTimeout;              /* Busy handler timeout, in msec */
  1080   1118     int nSavepoint;               /* Number of non-transaction savepoints */
  1081   1119     int nStatement;               /* Number of nested statement-transactions  */
  1082   1120     i64 nDeferredCons;            /* Net deferred constraints this transaction. */
  1083   1121     i64 nDeferredImmCons;         /* Net deferred immediate constraints */
  1084   1122     int *pnBytesFreed;            /* If not NULL, increment this in DbFree() */
  1085         -
  1086   1123   #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
  1087   1124     /* The following variables are all protected by the STATIC_MASTER 
  1088   1125     ** mutex, not by sqlite3.mutex. They are used by code in notify.c. 
  1089   1126     **
  1090   1127     ** When X.pUnlockConnection==Y, that means that X is waiting for Y to
  1091   1128     ** unlock so that it can proceed.
  1092   1129     **
................................................................................
  1096   1133     */
  1097   1134     sqlite3 *pBlockingConnection; /* Connection that caused SQLITE_LOCKED */
  1098   1135     sqlite3 *pUnlockConnection;           /* Connection to watch for unlock */
  1099   1136     void *pUnlockArg;                     /* Argument to xUnlockNotify */
  1100   1137     void (*xUnlockNotify)(void **, int);  /* Unlock notify callback */
  1101   1138     sqlite3 *pNextBlocked;        /* Next in list of all blocked connections */
  1102   1139   #endif
         1140  +#ifdef SQLITE_USER_AUTHENTICATION
         1141  +  sqlite3_userauth auth;        /* User authentication information */
         1142  +#endif
  1103   1143   };
  1104   1144   
  1105   1145   /*
  1106   1146   ** A macro to discover the encoding of a database.
  1107   1147   */
  1108   1148   #define ENC(db) ((db)->aDb[0].pSchema->enc)
  1109   1149   

Changes to src/tclsqlite.c.

   868    868   static int auth_callback(
   869    869     void *pArg,
   870    870     int code,
   871    871     const char *zArg1,
   872    872     const char *zArg2,
   873    873     const char *zArg3,
   874    874     const char *zArg4
          875  +#ifdef SQLITE_USER_AUTHENTICATION
          876  +  ,const char *zArg5
          877  +#endif
   875    878   ){
   876    879     const char *zCode;
   877    880     Tcl_DString str;
   878    881     int rc;
   879    882     const char *zReply;
   880    883     SqliteDb *pDb = (SqliteDb*)pArg;
   881    884     if( pDb->disableAuth ) return SQLITE_OK;
................................................................................
   920    923     Tcl_DStringInit(&str);
   921    924     Tcl_DStringAppend(&str, pDb->zAuth, -1);
   922    925     Tcl_DStringAppendElement(&str, zCode);
   923    926     Tcl_DStringAppendElement(&str, zArg1 ? zArg1 : "");
   924    927     Tcl_DStringAppendElement(&str, zArg2 ? zArg2 : "");
   925    928     Tcl_DStringAppendElement(&str, zArg3 ? zArg3 : "");
   926    929     Tcl_DStringAppendElement(&str, zArg4 ? zArg4 : "");
          930  +#ifdef SQLITE_USER_AUTHENTICATION
          931  +  Tcl_DStringAppendElement(&str, zArg5 ? zArg5 : "");
          932  +#endif  
   927    933     rc = Tcl_GlobalEval(pDb->interp, Tcl_DStringValue(&str));
   928    934     Tcl_DStringFree(&str);
   929    935     zReply = rc==TCL_OK ? Tcl_GetStringResult(pDb->interp) : "SQLITE_DENY";
   930    936     if( strcmp(zReply,"SQLITE_OK")==0 ){
   931    937       rc = SQLITE_OK;
   932    938     }else if( strcmp(zReply,"SQLITE_DENY")==0 ){
   933    939       rc = SQLITE_DENY;
................................................................................
  1696   1702         if( zAuth && len>0 ){
  1697   1703           pDb->zAuth = Tcl_Alloc( len + 1 );
  1698   1704           memcpy(pDb->zAuth, zAuth, len+1);
  1699   1705         }else{
  1700   1706           pDb->zAuth = 0;
  1701   1707         }
  1702   1708         if( pDb->zAuth ){
         1709  +        typedef int (*sqlite3_auth_cb)(
         1710  +           void*,int,const char*,const char*,
         1711  +           const char*,const char*);
  1703   1712           pDb->interp = interp;
  1704         -        sqlite3_set_authorizer(pDb->db, auth_callback, pDb);
         1713  +        sqlite3_set_authorizer(pDb->db,(sqlite3_auth_cb)auth_callback,pDb);
  1705   1714         }else{
  1706   1715           sqlite3_set_authorizer(pDb->db, 0, 0);
  1707   1716         }
  1708   1717       }
  1709   1718   #endif
  1710   1719       break;
  1711   1720     }

Changes to src/test1.c.

  6493   6493     return TCL_OK;
  6494   6494    sql_error:
  6495   6495     Tcl_AppendResult(interp, "sql error: ", sqlite3_errmsg(db), 0);
  6496   6496     return TCL_ERROR;
  6497   6497   }
  6498   6498   
  6499   6499   
         6500  +#ifdef SQLITE_USER_AUTHENTICATION
         6501  +#include "sqlite3userauth.h"
         6502  +/*
         6503  +** tclcmd:  sqlite3_user_authenticate DB USERNAME PASSWORD
         6504  +*/
         6505  +static int test_user_authenticate(
         6506  +  ClientData clientData, /* Unused */
         6507  +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
         6508  +  int objc,              /* Number of arguments */
         6509  +  Tcl_Obj *CONST objv[]  /* Command arguments */
         6510  +){
         6511  +  char *zUser = 0;
         6512  +  char *zPasswd = 0;
         6513  +  int nPasswd = 0;
         6514  +  sqlite3 *db;
         6515  +  int rc;
         6516  +
         6517  +  if( objc!=4 ){
         6518  +    Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD");
         6519  +    return TCL_ERROR;
         6520  +  }
         6521  +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
         6522  +    return TCL_ERROR;
         6523  +  }
         6524  +  zUser = Tcl_GetString(objv[2]);
         6525  +  zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
         6526  +  rc = sqlite3_user_authenticate(db, zUser, zPasswd, nPasswd);
         6527  +  Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
         6528  +  return TCL_OK;
         6529  +}
         6530  +#endif /* SQLITE_USER_AUTHENTICATION */
         6531  +
         6532  +#ifdef SQLITE_USER_AUTHENTICATION
         6533  +/*
         6534  +** tclcmd:  sqlite3_user_add DB USERNAME PASSWORD ISADMIN
         6535  +*/
         6536  +static int test_user_add(
         6537  +  ClientData clientData, /* Unused */
         6538  +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
         6539  +  int objc,              /* Number of arguments */
         6540  +  Tcl_Obj *CONST objv[]  /* Command arguments */
         6541  +){
         6542  +  char *zUser = 0;
         6543  +  char *zPasswd = 0;
         6544  +  int nPasswd = 0;
         6545  +  int isAdmin = 0;
         6546  +  sqlite3 *db;
         6547  +  int rc;
         6548  +
         6549  +  if( objc!=5 ){
         6550  +    Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD ISADMIN");
         6551  +    return TCL_ERROR;
         6552  +  }
         6553  +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
         6554  +    return TCL_ERROR;
         6555  +  }
         6556  +  zUser = Tcl_GetString(objv[2]);
         6557  +  zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
         6558  +  Tcl_GetBooleanFromObj(interp, objv[4], &isAdmin);
         6559  +  rc = sqlite3_user_add(db, zUser, zPasswd, nPasswd, isAdmin);
         6560  +  Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
         6561  +  return TCL_OK;
         6562  +}
         6563  +#endif /* SQLITE_USER_AUTHENTICATION */
         6564  +
         6565  +#ifdef SQLITE_USER_AUTHENTICATION
         6566  +/*
         6567  +** tclcmd:  sqlite3_user_change DB USERNAME PASSWORD ISADMIN
         6568  +*/
         6569  +static int test_user_change(
         6570  +  ClientData clientData, /* Unused */
         6571  +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
         6572  +  int objc,              /* Number of arguments */
         6573  +  Tcl_Obj *CONST objv[]  /* Command arguments */
         6574  +){
         6575  +  char *zUser = 0;
         6576  +  char *zPasswd = 0;
         6577  +  int nPasswd = 0;
         6578  +  int isAdmin = 0;
         6579  +  sqlite3 *db;
         6580  +  int rc;
         6581  +
         6582  +  if( objc!=5 ){
         6583  +    Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD ISADMIN");
         6584  +    return TCL_ERROR;
         6585  +  }
         6586  +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
         6587  +    return TCL_ERROR;
         6588  +  }
         6589  +  zUser = Tcl_GetString(objv[2]);
         6590  +  zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
         6591  +  Tcl_GetBooleanFromObj(interp, objv[4], &isAdmin);
         6592  +  rc = sqlite3_user_change(db, zUser, zPasswd, nPasswd, isAdmin);
         6593  +  Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
         6594  +  return TCL_OK;
         6595  +}
         6596  +#endif /* SQLITE_USER_AUTHENTICATION */
         6597  +
         6598  +#ifdef SQLITE_USER_AUTHENTICATION
         6599  +/*
         6600  +** tclcmd:  sqlite3_user_delete DB USERNAME
         6601  +*/
         6602  +static int test_user_delete(
         6603  +  ClientData clientData, /* Unused */
         6604  +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
         6605  +  int objc,              /* Number of arguments */
         6606  +  Tcl_Obj *CONST objv[]  /* Command arguments */
         6607  +){
         6608  +  char *zUser = 0;
         6609  +  sqlite3 *db;
         6610  +  int rc;
         6611  +
         6612  +  if( objc!=3 ){
         6613  +    Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME");
         6614  +    return TCL_ERROR;
         6615  +  }
         6616  +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
         6617  +    return TCL_ERROR;
         6618  +  }
         6619  +  zUser = Tcl_GetString(objv[2]);
         6620  +  rc = sqlite3_user_delete(db, zUser);
         6621  +  Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
         6622  +  return TCL_OK;
         6623  +}
         6624  +#endif /* SQLITE_USER_AUTHENTICATION */
         6625  +
  6500   6626   /*
  6501   6627   ** Register commands with the TCL interpreter.
  6502   6628   */
  6503   6629   int Sqlitetest1_Init(Tcl_Interp *interp){
  6504   6630     extern int sqlite3_search_count;
  6505   6631     extern int sqlite3_found_count;
  6506   6632     extern int sqlite3_interrupt_count;
................................................................................
  6730   6856        { "sqlite3_test_control", test_test_control },
  6731   6857   #if SQLITE_OS_UNIX
  6732   6858        { "getrusage", test_getrusage },
  6733   6859   #endif
  6734   6860        { "load_static_extension", tclLoadStaticExtensionCmd },
  6735   6861        { "sorter_test_fakeheap", sorter_test_fakeheap },
  6736   6862        { "sorter_test_sort4_helper", sorter_test_sort4_helper },
         6863  +#ifdef SQLITE_USER_AUTHENTICATION
         6864  +     { "sqlite3_user_authenticate", test_user_authenticate, 0 },
         6865  +     { "sqlite3_user_add",          test_user_add,          0 },
         6866  +     { "sqlite3_user_change",       test_user_change,       0 },
         6867  +     { "sqlite3_user_delete",       test_user_delete,       0 },
         6868  +#endif
         6869  +
  6737   6870     };
  6738   6871     static int bitmask_size = sizeof(Bitmask)*8;
  6739   6872     int i;
  6740   6873     extern int sqlite3_sync_count, sqlite3_fullsync_count;
  6741   6874     extern int sqlite3_opentemp_count;
  6742   6875     extern int sqlite3_like_count;
  6743   6876     extern int sqlite3_xferopt_count;

Changes to src/test_config.c.

   598    598   #endif
   599    599   
   600    600   #ifdef SQLITE_SECURE_DELETE
   601    601     Tcl_SetVar2(interp, "sqlite_options", "secure_delete", "1", TCL_GLOBAL_ONLY);
   602    602   #else
   603    603     Tcl_SetVar2(interp, "sqlite_options", "secure_delete", "0", TCL_GLOBAL_ONLY);
   604    604   #endif
          605  +
          606  +#ifdef SQLITE_USER_AUTHENTICATION
          607  +  Tcl_SetVar2(interp, "sqlite_options", "userauth", "1", TCL_GLOBAL_ONLY);
          608  +#else
          609  +  Tcl_SetVar2(interp, "sqlite_options", "userauth", "0", TCL_GLOBAL_ONLY);
          610  +#endif
   605    611   
   606    612   #ifdef SQLITE_MULTIPLEX_EXT_OVWR
   607    613     Tcl_SetVar2(interp, "sqlite_options", "multiplex_ext_overwrite", "1", TCL_GLOBAL_ONLY);
   608    614   #else
   609    615     Tcl_SetVar2(interp, "sqlite_options", "multiplex_ext_overwrite", "0", TCL_GLOBAL_ONLY);
   610    616   #endif
   611    617   

Changes to test/auth.test.

    32     32       db authorizer ::auth
    33     33     }
    34     34   }
    35     35   
    36     36   do_test auth-1.1.1 {
    37     37     db close
    38     38     set ::DB [sqlite3 db test.db]
    39         -  proc auth {code arg1 arg2 arg3 arg4} {
           39  +  proc auth {code arg1 arg2 arg3 arg4 args} {
    40     40       if {$code=="SQLITE_INSERT" && $arg1=="sqlite_master"} {
    41     41         return SQLITE_DENY
    42     42       }
    43     43       return SQLITE_OK
    44     44     }
    45     45     db authorizer ::auth
    46     46     catchsql {CREATE TABLE t1(a,b,c)}
................................................................................
    57     57       SELECT x;
    58     58     }
    59     59   } {1 {no such column: x}}
    60     60   do_test auth-1.2 {
    61     61     execsql {SELECT name FROM sqlite_master}
    62     62   } {}
    63     63   do_test auth-1.3.1 {
    64         -  proc auth {code arg1 arg2 arg3 arg4} {
           64  +  proc auth {code arg1 arg2 arg3 arg4 args} {
    65     65       if {$code=="SQLITE_CREATE_TABLE"} {
    66     66         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
    67     67         return SQLITE_DENY
    68     68       }
    69     69       return SQLITE_OK
    70     70     }
    71     71     catchsql {CREATE TABLE t1(a,b,c)}
................................................................................
    78     78   } {t1 {} main {}}
    79     79   do_test auth-1.4 {
    80     80     execsql {SELECT name FROM sqlite_master}
    81     81   } {}
    82     82   
    83     83   ifcapable tempdb {
    84     84     do_test auth-1.5 {
    85         -    proc auth {code arg1 arg2 arg3 arg4} {
           85  +    proc auth {code arg1 arg2 arg3 arg4 args} {
    86     86         if {$code=="SQLITE_INSERT" && $arg1=="sqlite_temp_master"} {
    87     87           return SQLITE_DENY
    88     88         }
    89     89         return SQLITE_OK
    90     90       }
    91     91       catchsql {CREATE TEMP TABLE t1(a,b,c)}
    92     92     } {1 {not authorized}}
    93     93     do_test auth-1.6 {
    94     94       execsql {SELECT name FROM sqlite_temp_master}
    95     95     } {}
    96     96     do_test auth-1.7.1 {
    97         -    proc auth {code arg1 arg2 arg3 arg4} {
           97  +    proc auth {code arg1 arg2 arg3 arg4 args} {
    98     98         if {$code=="SQLITE_CREATE_TEMP_TABLE"} {
    99     99           set ::authargs [list $arg1 $arg2 $arg3 $arg4]
   100    100           return SQLITE_DENY
   101    101         }
   102    102         return SQLITE_OK
   103    103       }
   104    104       catchsql {CREATE TEMP TABLE t1(a,b,c)}
................................................................................
   108    108     } {t1 {} temp {}}
   109    109     do_test auth-1.8 {
   110    110       execsql {SELECT name FROM sqlite_temp_master}
   111    111     } {}
   112    112   }
   113    113   
   114    114   do_test auth-1.9 {
   115         -  proc auth {code arg1 arg2 arg3 arg4} {
          115  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   116    116       if {$code=="SQLITE_INSERT" && $arg1=="sqlite_master"} {
   117    117         return SQLITE_IGNORE
   118    118       }
   119    119       return SQLITE_OK
   120    120     }
   121    121     catchsql {CREATE TABLE t1(a,b,c)}
   122    122   } {0 {}}
   123    123   do_test auth-1.10 {
   124    124     execsql {SELECT name FROM sqlite_master}
   125    125   } {}
   126    126   do_test auth-1.11 {
   127         -  proc auth {code arg1 arg2 arg3 arg4} {
          127  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   128    128       if {$code=="SQLITE_CREATE_TABLE"} {
   129    129         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
   130    130         return SQLITE_IGNORE
   131    131       }
   132    132       return SQLITE_OK
   133    133     }
   134    134     catchsql {CREATE TABLE t1(a,b,c)}
................................................................................
   135    135   } {0 {}}
   136    136   do_test auth-1.12 {
   137    137     execsql {SELECT name FROM sqlite_master}
   138    138   } {}
   139    139   
   140    140   ifcapable tempdb {
   141    141     do_test auth-1.13 {
   142         -    proc auth {code arg1 arg2 arg3 arg4} {
          142  +    proc auth {code arg1 arg2 arg3 arg4 args} {
   143    143         if {$code=="SQLITE_INSERT" && $arg1=="sqlite_temp_master"} {
   144    144           return SQLITE_IGNORE
   145    145         }
   146    146         return SQLITE_OK
   147    147       }
   148    148       catchsql {CREATE TEMP TABLE t1(a,b,c)}
   149    149     } {0 {}}
   150    150     do_test auth-1.14 {
   151    151       execsql {SELECT name FROM sqlite_temp_master}
   152    152     } {}
   153    153     do_test auth-1.15 {
   154         -    proc auth {code arg1 arg2 arg3 arg4} {
          154  +    proc auth {code arg1 arg2 arg3 arg4 args} {
   155    155         if {$code=="SQLITE_CREATE_TEMP_TABLE"} {
   156    156           set ::authargs [list $arg1 $arg2 $arg3 $arg4]
   157    157           return SQLITE_IGNORE
   158    158         }
   159    159         return SQLITE_OK
   160    160       }
   161    161       catchsql {CREATE TEMP TABLE t1(a,b,c)}
   162    162     } {0 {}}
   163    163     do_test auth-1.16 {
   164    164       execsql {SELECT name FROM sqlite_temp_master}
   165    165     } {}
   166    166     
   167    167     do_test auth-1.17 {
   168         -    proc auth {code arg1 arg2 arg3 arg4} {
          168  +    proc auth {code arg1 arg2 arg3 arg4 args} {
   169    169         if {$code=="SQLITE_CREATE_TABLE"} {
   170    170           set ::authargs [list $arg1 $arg2 $arg3 $arg4]
   171    171           return SQLITE_DENY
   172    172         }
   173    173         return SQLITE_OK
   174    174       }
   175    175       catchsql {CREATE TEMP TABLE t1(a,b,c)}
................................................................................
   177    177     do_test auth-1.18 {
   178    178       execsql {SELECT name FROM sqlite_temp_master}
   179    179     } {t1}
   180    180   }
   181    181   
   182    182   do_test auth-1.19.1 {
   183    183     set ::authargs {}
   184         -  proc auth {code arg1 arg2 arg3 arg4} {
          184  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   185    185       if {$code=="SQLITE_CREATE_TEMP_TABLE"} {
   186    186         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
   187    187         return SQLITE_DENY
   188    188       }
   189    189       return SQLITE_OK
   190    190     }
   191    191     catchsql {CREATE TABLE t2(a,b,c)}
................................................................................
   194    194     set ::authargs
   195    195   } {}
   196    196   do_test auth-1.20 {
   197    197     execsql {SELECT name FROM sqlite_master}
   198    198   } {t2}
   199    199   
   200    200   do_test auth-1.21.1 {
   201         -  proc auth {code arg1 arg2 arg3 arg4} {
          201  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   202    202       if {$code=="SQLITE_DROP_TABLE"} {
   203    203         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
   204    204         return SQLITE_DENY
   205    205       }
   206    206       return SQLITE_OK
   207    207     }
   208    208     catchsql {DROP TABLE t2}
................................................................................
   210    210   do_test auth-1.21.2 {
   211    211     set ::authargs
   212    212   } {t2 {} main {}}
   213    213   do_test auth-1.22 {
   214    214     execsql {SELECT name FROM sqlite_master}
   215    215   } {t2}
   216    216   do_test auth-1.23.1 {
   217         -  proc auth {code arg1 arg2 arg3 arg4} {
          217  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   218    218       if {$code=="SQLITE_DROP_TABLE"} {
   219    219         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
   220    220         return SQLITE_IGNORE
   221    221       }
   222    222       return SQLITE_OK
   223    223     }
   224    224     catchsql {DROP TABLE t2}
................................................................................
   228    228   } {t2 {} main {}}
   229    229   do_test auth-1.24 {
   230    230     execsql {SELECT name FROM sqlite_master}
   231    231   } {t2}
   232    232   
   233    233   ifcapable tempdb {
   234    234     do_test auth-1.25 {
   235         -    proc auth {code arg1 arg2 arg3 arg4} {
          235  +    proc auth {code arg1 arg2 arg3 arg4 args} {
   236    236         if {$code=="SQLITE_DROP_TEMP_TABLE"} {
   237    237           set ::authargs [list $arg1 $arg2 $arg3 $arg4]
   238    238           return SQLITE_DENY
   239    239         }
   240    240         return SQLITE_OK
   241    241       }
   242    242       catchsql {DROP TABLE t1}
   243    243     } {1 {not authorized}}
   244    244     do_test auth-1.26 {
   245    245       execsql {SELECT name FROM sqlite_temp_master}
   246    246     } {t1}
   247    247     do_test auth-1.27 {
   248         -    proc auth {code arg1 arg2 arg3 arg4} {
          248  +    proc auth {code arg1 arg2 arg3 arg4 args} {
   249    249         if {$code=="SQLITE_DROP_TEMP_TABLE"} {
   250    250           set ::authargs [list $arg1 $arg2 $arg3 $arg4]
   251    251           return SQLITE_IGNORE
   252    252         }
   253    253         return SQLITE_OK
   254    254       }
   255    255       catchsql {DROP TABLE t1}
................................................................................
   256    256     } {0 {}}
   257    257     do_test auth-1.28 {
   258    258       execsql {SELECT name FROM sqlite_temp_master}
   259    259     } {t1}
   260    260   }
   261    261   
   262    262   do_test auth-1.29 {
   263         -  proc auth {code arg1 arg2 arg3 arg4} {
          263  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   264    264       if {$code=="SQLITE_INSERT" && $arg1=="t2"} {
   265    265         return SQLITE_DENY
   266    266       }
   267    267       return SQLITE_OK
   268    268     }
   269    269     catchsql {INSERT INTO t2 VALUES(1,2,3)}
   270    270   } {1 {not authorized}}
   271    271   do_test auth-1.30 {
   272    272     execsql {SELECT * FROM t2}
   273    273   } {}
   274    274   do_test auth-1.31 {
   275         -  proc auth {code arg1 arg2 arg3 arg4} {
          275  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   276    276       if {$code=="SQLITE_INSERT" && $arg1=="t2"} {
   277    277         return SQLITE_IGNORE
   278    278       }
   279    279       return SQLITE_OK
   280    280     }
   281    281     catchsql {INSERT INTO t2 VALUES(1,2,3)}
   282    282   } {0 {}}
   283    283   do_test auth-1.32 {
   284    284     execsql {SELECT * FROM t2}
   285    285   } {}
   286    286   do_test auth-1.33 {
   287         -  proc auth {code arg1 arg2 arg3 arg4} {
          287  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   288    288       if {$code=="SQLITE_INSERT" && $arg1=="t1"} {
   289    289         return SQLITE_IGNORE
   290    290       }
   291    291       return SQLITE_OK
   292    292     }
   293    293     catchsql {INSERT INTO t2 VALUES(1,2,3)}
   294    294   } {0 {}}
   295    295   do_test auth-1.34 {
   296    296     execsql {SELECT * FROM t2}
   297    297   } {1 2 3}
   298    298   
   299    299   do_test auth-1.35.1 {
   300         -  proc auth {code arg1 arg2 arg3 arg4} {
          300  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   301    301       if {$code=="SQLITE_READ" && $arg1=="t2" && $arg2=="b"} {
   302    302         return SQLITE_DENY
   303    303       }
   304    304       return SQLITE_OK
   305    305     }
   306    306     catchsql {SELECT * FROM t2}
   307    307   } {1 {access to t2.b is prohibited}}
................................................................................
   309    309     do_test auth-1.35.2 {
   310    310       execsql {ATTACH DATABASE 'test.db' AS two}
   311    311       catchsql {SELECT * FROM two.t2}
   312    312     } {1 {access to two.t2.b is prohibited}}
   313    313     execsql {DETACH DATABASE two}
   314    314   }
   315    315   do_test auth-1.36 {
   316         -  proc auth {code arg1 arg2 arg3 arg4} {
          316  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   317    317       if {$code=="SQLITE_READ" && $arg1=="t2" && $arg2=="b"} {
   318    318         return SQLITE_IGNORE
   319    319       }
   320    320       return SQLITE_OK
   321    321     }
   322    322     catchsql {SELECT * FROM t2}
   323    323   } {0 {1 {} 3}}
   324    324   do_test auth-1.37 {
   325         -  proc auth {code arg1 arg2 arg3 arg4} {
          325  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   326    326       if {$code=="SQLITE_READ" && $arg1=="t2" && $arg2=="b"} {
   327    327         return SQLITE_IGNORE
   328    328       }
   329    329       return SQLITE_OK
   330    330     }
   331    331     catchsql {SELECT * FROM t2 WHERE b=2}
   332    332   } {0 {}}
   333    333   do_test auth-1.38 {
   334         -  proc auth {code arg1 arg2 arg3 arg4} {
          334  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   335    335       if {$code=="SQLITE_READ" && $arg1=="t2" && $arg2=="a"} {
   336    336         return SQLITE_IGNORE
   337    337       }
   338    338       return SQLITE_OK
   339    339     }
   340    340     catchsql {SELECT * FROM t2 WHERE b=2}
   341    341   } {0 {{} 2 3}}
   342    342   do_test auth-1.39 {
   343         -  proc auth {code arg1 arg2 arg3 arg4} {
          343  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   344    344       if {$code=="SQLITE_READ" && $arg1=="t2" && $arg2=="b"} {
   345    345         return SQLITE_IGNORE
   346    346       }
   347    347       return SQLITE_OK
   348    348     }
   349    349     catchsql {SELECT * FROM t2 WHERE b IS NULL}
   350    350   } {0 {1 {} 3}}
   351    351   do_test auth-1.40 {
   352         -  proc auth {code arg1 arg2 arg3 arg4} {
          352  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   353    353       if {$code=="SQLITE_READ" && $arg1=="t2" && $arg2=="b"} {
   354    354         return SQLITE_DENY
   355    355       }
   356    356       return SQLITE_OK
   357    357     }
   358    358     catchsql {SELECT a,c FROM t2 WHERE b IS NULL}
   359    359   } {1 {access to t2.b is prohibited}}
   360    360     
   361    361   do_test auth-1.41 {
   362         -  proc auth {code arg1 arg2 arg3 arg4} {
          362  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   363    363       if {$code=="SQLITE_UPDATE" && $arg1=="t2" && $arg2=="b"} {
   364    364         return SQLITE_DENY
   365    365       }
   366    366       return SQLITE_OK
   367    367     }
   368    368     catchsql {UPDATE t2 SET a=11}
   369    369   } {0 {}}
   370    370   do_test auth-1.42 {
   371    371     execsql {SELECT * FROM t2}
   372    372   } {11 2 3}
   373    373   do_test auth-1.43 {
   374         -  proc auth {code arg1 arg2 arg3 arg4} {
          374  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   375    375       if {$code=="SQLITE_UPDATE" && $arg1=="t2" && $arg2=="b"} {
   376    376         return SQLITE_DENY
   377    377       }
   378    378       return SQLITE_OK
   379    379     }
   380    380     catchsql {UPDATE t2 SET b=22, c=33}
   381    381   } {1 {not authorized}}
   382    382   do_test auth-1.44 {
   383    383     execsql {SELECT * FROM t2}
   384    384   } {11 2 3}
   385    385   do_test auth-1.45 {
   386         -  proc auth {code arg1 arg2 arg3 arg4} {
          386  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   387    387       if {$code=="SQLITE_UPDATE" && $arg1=="t2" && $arg2=="b"} {
   388    388         return SQLITE_IGNORE
   389    389       }
   390    390       return SQLITE_OK
   391    391     }
   392    392     catchsql {UPDATE t2 SET b=22, c=33}
   393    393   } {0 {}}
   394    394   do_test auth-1.46 {
   395    395     execsql {SELECT * FROM t2}
   396    396   } {11 2 33}
   397    397   
   398    398   do_test auth-1.47 {
   399         -  proc auth {code arg1 arg2 arg3 arg4} {
          399  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   400    400       if {$code=="SQLITE_DELETE" && $arg1=="t2"} {
   401    401         return SQLITE_DENY
   402    402       }
   403    403       return SQLITE_OK
   404    404     }
   405    405     catchsql {DELETE FROM t2 WHERE a=11}
   406    406   } {1 {not authorized}}
   407    407   do_test auth-1.48 {
   408    408     execsql {SELECT * FROM t2}
   409    409   } {11 2 33}
   410    410   do_test auth-1.49 {
   411         -  proc auth {code arg1 arg2 arg3 arg4} {
          411  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   412    412       if {$code=="SQLITE_DELETE" && $arg1=="t2"} {
   413    413         return SQLITE_IGNORE
   414    414       }
   415    415       return SQLITE_OK
   416    416     }
   417    417     catchsql {DELETE FROM t2 WHERE a=11}
   418    418   } {0 {}}
................................................................................
   420    420     execsql {SELECT * FROM t2}
   421    421   } {}
   422    422   do_test auth-1.50.2 {
   423    423     execsql {INSERT INTO t2 VALUES(11, 2, 33)}
   424    424   } {}
   425    425   
   426    426   do_test auth-1.51 {
   427         -  proc auth {code arg1 arg2 arg3 arg4} {
          427  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   428    428       if {$code=="SQLITE_SELECT"} {
   429    429         return SQLITE_DENY
   430    430       }
   431    431       return SQLITE_OK
   432    432     }
   433    433     catchsql {SELECT * FROM t2}
   434    434   } {1 {not authorized}}
   435    435   do_test auth-1.52 {
   436         -  proc auth {code arg1 arg2 arg3 arg4} {
          436  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   437    437       if {$code=="SQLITE_SELECT"} {
   438    438         return SQLITE_IGNORE
   439    439       }
   440    440       return SQLITE_OK
   441    441     }
   442    442     catchsql {SELECT * FROM t2}
   443    443   } {0 {}}
   444    444   do_test auth-1.53 {
   445         -  proc auth {code arg1 arg2 arg3 arg4} {
          445  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   446    446       if {$code=="SQLITE_SELECT"} {
   447    447         return SQLITE_OK
   448    448       }
   449    449       return SQLITE_OK
   450    450     }
   451    451     catchsql {SELECT * FROM t2}
   452    452   } {0 {11 2 33}}
................................................................................
   458    458     execsql {INSERT INTO t2 VALUES(7, 8, 9);}
   459    459   } {}
   460    460   do_test auth-1.55 {
   461    461     execsql {SELECT * FROM t2}
   462    462   } {11 2 33 7 8 9}
   463    463   
   464    464   do_test auth-1.63 {
   465         -  proc auth {code arg1 arg2 arg3 arg4} {
          465  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   466    466       if {$code=="SQLITE_DELETE" && $arg1=="sqlite_master"} {
   467    467          return SQLITE_DENY
   468    468       }
   469    469       return SQLITE_OK
   470    470     }
   471    471     catchsql {DROP TABLE t2}
   472    472   } {1 {not authorized}}
   473    473   do_test auth-1.64 {
   474    474     execsql {SELECT name FROM sqlite_master}
   475    475   } {t2}
   476    476   do_test auth-1.65 {
   477         -  proc auth {code arg1 arg2 arg3 arg4} {
          477  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   478    478       if {$code=="SQLITE_DELETE" && $arg1=="t2"} {
   479    479          return SQLITE_DENY
   480    480       }
   481    481       return SQLITE_OK
   482    482     }
   483    483     catchsql {DROP TABLE t2}
   484    484   } {1 {not authorized}}
   485    485   do_test auth-1.66 {
   486    486     execsql {SELECT name FROM sqlite_master}
   487    487   } {t2}
   488    488   
   489    489   ifcapable tempdb {
   490    490     do_test auth-1.67 {
   491         -    proc auth {code arg1 arg2 arg3 arg4} {
          491  +    proc auth {code arg1 arg2 arg3 arg4 args} {
   492    492         if {$code=="SQLITE_DELETE" && $arg1=="sqlite_temp_master"} {
   493    493            return SQLITE_DENY
   494    494         }
   495    495         return SQLITE_OK
   496    496       }
   497    497       catchsql {DROP TABLE t1}
   498    498     } {1 {not authorized}}
   499    499     do_test auth-1.68 {
   500    500       execsql {SELECT name FROM sqlite_temp_master}
   501    501     } {t1}
   502    502     do_test auth-1.69 {
   503         -    proc auth {code arg1 arg2 arg3 arg4} {
          503  +    proc auth {code arg1 arg2 arg3 arg4 args} {
   504    504         if {$code=="SQLITE_DELETE" && $arg1=="t1"} {
   505    505            return SQLITE_DENY
   506    506         }
   507    507         return SQLITE_OK
   508    508       }
   509    509       catchsql {DROP TABLE t1}
   510    510     } {1 {not authorized}}
   511    511     do_test auth-1.70 {
   512    512       execsql {SELECT name FROM sqlite_temp_master}
   513    513     } {t1}
   514    514   }
   515    515   
   516    516   do_test auth-1.71 {
   517         -  proc auth {code arg1 arg2 arg3 arg4} {
          517  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   518    518       if {$code=="SQLITE_DELETE" && $arg1=="sqlite_master"} {
   519    519          return SQLITE_IGNORE
   520    520       }
   521    521       return SQLITE_OK
   522    522     }
   523    523     catchsql {DROP TABLE t2}
   524    524   } {0 {}}
   525    525   do_test auth-1.72 {
   526    526     execsql {SELECT name FROM sqlite_master}
   527    527   } {t2}
   528    528   do_test auth-1.73 {
   529         -  proc auth {code arg1 arg2 arg3 arg4} {
          529  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   530    530       if {$code=="SQLITE_DELETE" && $arg1=="t2"} {
   531    531          return SQLITE_IGNORE
   532    532       }
   533    533       return SQLITE_OK
   534    534     }
   535    535     catchsql {DROP TABLE t2}
   536    536   } {0 {}}
   537    537   do_test auth-1.74 {
   538    538     execsql {SELECT name FROM sqlite_master}
   539    539   } {t2}
   540    540   
   541    541   ifcapable tempdb {
   542    542     do_test auth-1.75 {
   543         -    proc auth {code arg1 arg2 arg3 arg4} {
          543  +    proc auth {code arg1 arg2 arg3 arg4 args} {
   544    544         if {$code=="SQLITE_DELETE" && $arg1=="sqlite_temp_master"} {
   545    545            return SQLITE_IGNORE
   546    546         }
   547    547         return SQLITE_OK
   548    548       }
   549    549       catchsql {DROP TABLE t1}
   550    550     } {0 {}}
   551    551     do_test auth-1.76 {
   552    552       execsql {SELECT name FROM sqlite_temp_master}
   553    553     } {t1}
   554    554     do_test auth-1.77 {
   555         -    proc auth {code arg1 arg2 arg3 arg4} {
          555  +    proc auth {code arg1 arg2 arg3 arg4 args} {
   556    556         if {$code=="SQLITE_DELETE" && $arg1=="t1"} {
   557    557            return SQLITE_IGNORE
   558    558         }
   559    559         return SQLITE_OK
   560    560       }
   561    561       catchsql {DROP TABLE t1}
   562    562     } {0 {}}
................................................................................
   565    565     } {t1}
   566    566   }
   567    567   
   568    568   # Test cases auth-1.79 to auth-1.124 test creating and dropping views.
   569    569   # Omit these if the library was compiled with views omitted.
   570    570   ifcapable view {
   571    571   do_test auth-1.79 {
   572         -  proc auth {code arg1 arg2 arg3 arg4} {
          572  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   573    573       if {$code=="SQLITE_CREATE_VIEW"} {
   574    574         set ::authargs [list $arg1 $arg2 $arg3 $arg4] 
   575    575         return SQLITE_DENY
   576    576       }
   577    577       return SQLITE_OK
   578    578     }
   579    579     catchsql {CREATE VIEW v1 AS SELECT a+1,b+1 FROM t2}
................................................................................
   581    581   do_test auth-1.80 {
   582    582     set ::authargs
   583    583   } {v1 {} main {}}
   584    584   do_test auth-1.81 {
   585    585     execsql {SELECT name FROM sqlite_master}
   586    586   } {t2}
   587    587   do_test auth-1.82 {
   588         -  proc auth {code arg1 arg2 arg3 arg4} {
          588  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   589    589       if {$code=="SQLITE_CREATE_VIEW"} {
   590    590         set ::authargs [list $arg1 $arg2 $arg3 $arg4] 
   591    591         return SQLITE_IGNORE
   592    592       }
   593    593       return SQLITE_OK
   594    594     }
   595    595     catchsql {CREATE VIEW v1 AS SELECT a+1,b+1 FROM t2}
................................................................................
   599    599   } {v1 {} main {}}
   600    600   do_test auth-1.84 {
   601    601     execsql {SELECT name FROM sqlite_master}
   602    602   } {t2}
   603    603   
   604    604   ifcapable tempdb {
   605    605     do_test auth-1.85 {
   606         -    proc auth {code arg1 arg2 arg3 arg4} {
          606  +    proc auth {code arg1 arg2 arg3 arg4 args} {
   607    607         if {$code=="SQLITE_CREATE_TEMP_VIEW"} {
   608    608           set ::authargs [list $arg1 $arg2 $arg3 $arg4] 
   609    609           return SQLITE_DENY
   610    610         }
   611    611         return SQLITE_OK
   612    612       }
   613    613       catchsql {CREATE TEMPORARY VIEW v1 AS SELECT a+1,b+1 FROM t2}
................................................................................
   615    615     do_test auth-1.86 {
   616    616       set ::authargs
   617    617     } {v1 {} temp {}}
   618    618     do_test auth-1.87 {
   619    619       execsql {SELECT name FROM sqlite_temp_master}
   620    620     } {t1}
   621    621     do_test auth-1.88 {
   622         -    proc auth {code arg1 arg2 arg3 arg4} {
          622  +    proc auth {code arg1 arg2 arg3 arg4 args} {
   623    623         if {$code=="SQLITE_CREATE_TEMP_VIEW"} {
   624    624           set ::authargs [list $arg1 $arg2 $arg3 $arg4] 
   625    625           return SQLITE_IGNORE
   626    626         }
   627    627         return SQLITE_OK
   628    628       }
   629    629       catchsql {CREATE TEMPORARY VIEW v1 AS SELECT a+1,b+1 FROM t2}
................................................................................
   633    633     } {v1 {} temp {}}
   634    634     do_test auth-1.90 {
   635    635       execsql {SELECT name FROM sqlite_temp_master}
   636    636     } {t1}
   637    637   }
   638    638   
   639    639   do_test auth-1.91 {
   640         -  proc auth {code arg1 arg2 arg3 arg4} {
          640  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   641    641       if {$code=="SQLITE_INSERT" && $arg1=="sqlite_master"} {
   642    642         return SQLITE_DENY
   643    643       }
   644    644       return SQLITE_OK
   645    645     }
   646    646     catchsql {CREATE VIEW v1 AS SELECT a+1,b+1 FROM t2}
   647    647   } {1 {not authorized}}
   648    648   do_test auth-1.92 {
   649    649     execsql {SELECT name FROM sqlite_master}
   650    650   } {t2}
   651    651   do_test auth-1.93 {
   652         -  proc auth {code arg1 arg2 arg3 arg4} {
          652  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   653    653       if {$code=="SQLITE_INSERT" && $arg1=="sqlite_master"} {
   654    654         return SQLITE_IGNORE
   655    655       }
   656    656       return SQLITE_OK
   657    657     }
   658    658     catchsql {CREATE VIEW v1 AS SELECT a+1,b+1 FROM t2}
   659    659   } {0 {}}
   660    660   do_test auth-1.94 {
   661    661     execsql {SELECT name FROM sqlite_master}
   662    662   } {t2}
   663    663   
   664    664   ifcapable tempdb {
   665    665     do_test auth-1.95 {
   666         -    proc auth {code arg1 arg2 arg3 arg4} {
          666  +    proc auth {code arg1 arg2 arg3 arg4 args} {
   667    667         if {$code=="SQLITE_INSERT" && $arg1=="sqlite_temp_master"} {
   668    668           return SQLITE_DENY
   669    669         }
   670    670         return SQLITE_OK
   671    671       }
   672    672       catchsql {CREATE TEMPORARY VIEW v1 AS SELECT a+1,b+1 FROM t2}
   673    673     } {1 {not authorized}}
   674    674     do_test auth-1.96 {
   675    675       execsql {SELECT name FROM sqlite_temp_master}
   676    676     } {t1}
   677    677     do_test auth-1.97 {
   678         -    proc auth {code arg1 arg2 arg3 arg4} {
          678  +    proc auth {code arg1 arg2 arg3 arg4 args} {
   679    679         if {$code=="SQLITE_INSERT" && $arg1=="sqlite_temp_master"} {
   680    680           return SQLITE_IGNORE
   681    681         }
   682    682         return SQLITE_OK
   683    683       }
   684    684       catchsql {CREATE TEMPORARY VIEW v1 AS SELECT a+1,b+1 FROM t2}
   685    685     } {0 {}}
   686    686     do_test auth-1.98 {
   687    687       execsql {SELECT name FROM sqlite_temp_master}
   688    688     } {t1}
   689    689   }
   690    690   
   691    691   do_test auth-1.99 {
   692         -  proc auth {code arg1 arg2 arg3 arg4} {
          692  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   693    693       if {$code=="SQLITE_DELETE" && $arg1=="sqlite_master"} {
   694    694         return SQLITE_DENY
   695    695       }
   696    696       return SQLITE_OK
   697    697     }
   698    698     catchsql {
   699    699       CREATE VIEW v2 AS SELECT a+1,b+1 FROM t2;
................................................................................
   700    700       DROP VIEW v2
   701    701     }
   702    702   } {1 {not authorized}}
   703    703   do_test auth-1.100 {
   704    704     execsql {SELECT name FROM sqlite_master}
   705    705   } {t2 v2}
   706    706   do_test auth-1.101 {
   707         -  proc auth {code arg1 arg2 arg3 arg4} {
          707  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   708    708       if {$code=="SQLITE_DROP_VIEW"} {
   709    709         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
   710    710         return SQLITE_DENY
   711    711       }
   712    712       return SQLITE_OK
   713    713     }
   714    714     catchsql {DROP VIEW v2}
................................................................................
   716    716   do_test auth-1.102 {
   717    717     set ::authargs
   718    718   } {v2 {} main {}}
   719    719   do_test auth-1.103 {
   720    720     execsql {SELECT name FROM sqlite_master}
   721    721   } {t2 v2}
   722    722   do_test auth-1.104 {
   723         -  proc auth {code arg1 arg2 arg3 arg4} {
          723  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   724    724       if {$code=="SQLITE_DELETE" && $arg1=="sqlite_master"} {
   725    725         return SQLITE_IGNORE
   726    726       }
   727    727       return SQLITE_OK
   728    728     }
   729    729     catchsql {DROP VIEW v2}
   730    730   } {0 {}}
   731    731   do_test auth-1.105 {
   732    732     execsql {SELECT name FROM sqlite_master}
   733    733   } {t2 v2}
   734    734   do_test auth-1.106 {
   735         -  proc auth {code arg1 arg2 arg3 arg4} {
          735  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   736    736       if {$code=="SQLITE_DROP_VIEW"} {
   737    737         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
   738    738         return SQLITE_IGNORE
   739    739       }
   740    740       return SQLITE_OK
   741    741     }
   742    742     catchsql {DROP VIEW v2}
................................................................................
   744    744   do_test auth-1.107 {
   745    745     set ::authargs
   746    746   } {v2 {} main {}}
   747    747   do_test auth-1.108 {
   748    748     execsql {SELECT name FROM sqlite_master}
   749    749   } {t2 v2}
   750    750   do_test auth-1.109 {
   751         -  proc auth {code arg1 arg2 arg3 arg4} {
          751  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   752    752       if {$code=="SQLITE_DROP_VIEW"} {
   753    753         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
   754    754         return SQLITE_OK
   755    755       }
   756    756       return SQLITE_OK
   757    757     }
   758    758     catchsql {DROP VIEW v2}
................................................................................
   763    763   do_test auth-1.111 {
   764    764     execsql {SELECT name FROM sqlite_master}
   765    765   } {t2}
   766    766   
   767    767   
   768    768   ifcapable tempdb {
   769    769     do_test auth-1.112 {
   770         -    proc auth {code arg1 arg2 arg3 arg4} {
          770  +    proc auth {code arg1 arg2 arg3 arg4 args} {
   771    771         if {$code=="SQLITE_DELETE" && $arg1=="sqlite_temp_master"} {
   772    772           return SQLITE_DENY
   773    773         }
   774    774         return SQLITE_OK
   775    775       }
   776    776       catchsql {
   777    777         CREATE TEMP VIEW v1 AS SELECT a+1,b+1 FROM t1;
................................................................................
   778    778         DROP VIEW v1
   779    779       }
   780    780     } {1 {not authorized}}
   781    781     do_test auth-1.113 {
   782    782       execsql {SELECT name FROM sqlite_temp_master}
   783    783     } {t1 v1}
   784    784     do_test auth-1.114 {
   785         -    proc auth {code arg1 arg2 arg3 arg4} {
          785  +    proc auth {code arg1 arg2 arg3 arg4 args} {
   786    786         if {$code=="SQLITE_DROP_TEMP_VIEW"} {
   787    787           set ::authargs [list $arg1 $arg2 $arg3 $arg4]
   788    788           return SQLITE_DENY
   789    789         }
   790    790         return SQLITE_OK
   791    791       }
   792    792       catchsql {DROP VIEW v1}
................................................................................
   794    794     do_test auth-1.115 {
   795    795       set ::authargs
   796    796     } {v1 {} temp {}}
   797    797     do_test auth-1.116 {
   798    798       execsql {SELECT name FROM sqlite_temp_master}
   799    799     } {t1 v1}
   800    800     do_test auth-1.117 {
   801         -    proc auth {code arg1 arg2 arg3 arg4} {
          801  +    proc auth {code arg1 arg2 arg3 arg4 args} {
   802    802         if {$code=="SQLITE_DELETE" && $arg1=="sqlite_temp_master"} {
   803    803           return SQLITE_IGNORE
   804    804         }
   805    805         return SQLITE_OK
   806    806       }
   807    807       catchsql {DROP VIEW v1}
   808    808     } {0 {}}
   809    809     do_test auth-1.118 {
   810    810       execsql {SELECT name FROM sqlite_temp_master}
   811    811     } {t1 v1}
   812    812     do_test auth-1.119 {
   813         -    proc auth {code arg1 arg2 arg3 arg4} {
          813  +    proc auth {code arg1 arg2 arg3 arg4 args} {
   814    814         if {$code=="SQLITE_DROP_TEMP_VIEW"} {
   815    815           set ::authargs [list $arg1 $arg2 $arg3 $arg4]
   816    816           return SQLITE_IGNORE
   817    817         }
   818    818         return SQLITE_OK
   819    819       }
   820    820       catchsql {DROP VIEW v1}
................................................................................
   822    822     do_test auth-1.120 {
   823    823       set ::authargs
   824    824     } {v1 {} temp {}}
   825    825     do_test auth-1.121 {
   826    826       execsql {SELECT name FROM sqlite_temp_master}
   827    827     } {t1 v1}
   828    828     do_test auth-1.122 {
   829         -    proc auth {code arg1 arg2 arg3 arg4} {
          829  +    proc auth {code arg1 arg2 arg3 arg4 args} {
   830    830         if {$code=="SQLITE_DROP_TEMP_VIEW"} {
   831    831           set ::authargs [list $arg1 $arg2 $arg3 $arg4]
   832    832           return SQLITE_OK
   833    833         }
   834    834         return SQLITE_OK
   835    835       }
   836    836       catchsql {DROP VIEW v1}
................................................................................
   845    845   } ;# ifcapable view
   846    846   
   847    847   # Test cases auth-1.125 to auth-1.176 test creating and dropping triggers.
   848    848   # Omit these if the library was compiled with triggers omitted.
   849    849   #
   850    850   ifcapable trigger&&tempdb {
   851    851   do_test auth-1.125 {
   852         -  proc auth {code arg1 arg2 arg3 arg4} {
          852  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   853    853       if {$code=="SQLITE_CREATE_TRIGGER"} {
   854    854         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
   855    855         return SQLITE_DENY
   856    856       }
   857    857       return SQLITE_OK
   858    858     }
   859    859     catchsql {
................................................................................
   865    865   do_test auth-1.126 {
   866    866     set ::authargs
   867    867   } {r2 t2 main {}}
   868    868   do_test auth-1.127 {
   869    869     execsql {SELECT name FROM sqlite_master}
   870    870   } {t2}
   871    871   do_test auth-1.128 {
   872         -  proc auth {code arg1 arg2 arg3 arg4} {
          872  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   873    873       if {$code=="SQLITE_INSERT" && $arg1=="sqlite_master"} {
   874    874         return SQLITE_DENY
   875    875       }
   876    876       return SQLITE_OK
   877    877     }
   878    878     catchsql {
   879    879       CREATE TRIGGER r2 DELETE on t2 BEGIN
................................................................................
   881    881       END;
   882    882     }
   883    883   } {1 {not authorized}}
   884    884   do_test auth-1.129 {
   885    885     execsql {SELECT name FROM sqlite_master}
   886    886   } {t2}
   887    887   do_test auth-1.130 {
   888         -  proc auth {code arg1 arg2 arg3 arg4} {
          888  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   889    889       if {$code=="SQLITE_CREATE_TRIGGER"} {
   890    890         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
   891    891         return SQLITE_IGNORE
   892    892       }
   893    893       return SQLITE_OK
   894    894     }
   895    895     catchsql {
................................................................................
   901    901   do_test auth-1.131 {
   902    902     set ::authargs
   903    903   } {r2 t2 main {}}
   904    904   do_test auth-1.132 {
   905    905     execsql {SELECT name FROM sqlite_master}
   906    906   } {t2}
   907    907   do_test auth-1.133 {
   908         -  proc auth {code arg1 arg2 arg3 arg4} {
          908  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   909    909       if {$code=="SQLITE_INSERT" && $arg1=="sqlite_master"} {
   910    910         return SQLITE_IGNORE
   911    911       }
   912    912       return SQLITE_OK
   913    913     }
   914    914     catchsql {
   915    915       CREATE TRIGGER r2 DELETE on t2 BEGIN
................................................................................
   917    917       END;
   918    918     }
   919    919   } {0 {}}
   920    920   do_test auth-1.134 {
   921    921     execsql {SELECT name FROM sqlite_master}
   922    922   } {t2}
   923    923   do_test auth-1.135 {
   924         -  proc auth {code arg1 arg2 arg3 arg4} {
          924  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   925    925       if {$code=="SQLITE_CREATE_TRIGGER"} {
   926    926         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
   927    927         return SQLITE_OK
   928    928       }
   929    929       return SQLITE_OK
   930    930     }
   931    931     catchsql {
................................................................................
   940    940   } {r2 t2 main {}}
   941    941   do_test auth-1.136.2 {
   942    942     execsql {
   943    943       SELECT name FROM sqlite_master WHERE type='trigger'
   944    944     }
   945    945   } {r2}
   946    946   do_test auth-1.136.3 {
   947         -  proc auth {code arg1 arg2 arg3 arg4} {
          947  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   948    948       lappend ::authargs $code $arg1 $arg2 $arg3 $arg4
   949    949       return SQLITE_OK
   950    950     }
   951    951     set ::authargs {}
   952    952     execsql {
   953    953       INSERT INTO t2 VALUES(1,2,3);
   954    954     }
................................................................................
   959    959       SELECT * FROM tx;
   960    960     }
   961    961   } {3}
   962    962   do_test auth-1.137 {
   963    963     execsql {SELECT name FROM sqlite_master}
   964    964   } {t2 tx r2}
   965    965   do_test auth-1.138 {
   966         -  proc auth {code arg1 arg2 arg3 arg4} {
          966  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   967    967       if {$code=="SQLITE_CREATE_TEMP_TRIGGER"} {
   968    968         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
   969    969         return SQLITE_DENY
   970    970       }
   971    971       return SQLITE_OK
   972    972     }
   973    973     catchsql {
................................................................................
   979    979   do_test auth-1.139 {
   980    980     set ::authargs
   981    981   } {r1 t1 temp {}}
   982    982   do_test auth-1.140 {
   983    983     execsql {SELECT name FROM sqlite_temp_master}
   984    984   } {t1}
   985    985   do_test auth-1.141 {
   986         -  proc auth {code arg1 arg2 arg3 arg4} {
          986  +  proc auth {code arg1 arg2 arg3 arg4 args} {
   987    987       if {$code=="SQLITE_INSERT" && $arg1=="sqlite_temp_master"} {
   988    988         return SQLITE_DENY
   989    989       }
   990    990       return SQLITE_OK
   991    991     }
   992    992     catchsql {
   993    993       CREATE TRIGGER r1 DELETE on t1 BEGIN
................................................................................
   995    995       END;
   996    996     }
   997    997   } {1 {not authorized}}
   998    998   do_test auth-1.142 {
   999    999     execsql {SELECT name FROM sqlite_temp_master}
  1000   1000   } {t1}
  1001   1001   do_test auth-1.143 {
  1002         -  proc auth {code arg1 arg2 arg3 arg4} {
         1002  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1003   1003       if {$code=="SQLITE_CREATE_TEMP_TRIGGER"} {
  1004   1004         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1005   1005         return SQLITE_IGNORE
  1006   1006       }
  1007   1007       return SQLITE_OK
  1008   1008     }
  1009   1009     catchsql {
................................................................................
  1015   1015   do_test auth-1.144 {
  1016   1016     set ::authargs
  1017   1017   } {r1 t1 temp {}}
  1018   1018   do_test auth-1.145 {
  1019   1019     execsql {SELECT name FROM sqlite_temp_master}
  1020   1020   } {t1}
  1021   1021   do_test auth-1.146 {
  1022         -  proc auth {code arg1 arg2 arg3 arg4} {
         1022  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1023   1023       if {$code=="SQLITE_INSERT" && $arg1=="sqlite_temp_master"} {
  1024   1024         return SQLITE_IGNORE
  1025   1025       }
  1026   1026       return SQLITE_OK
  1027   1027     }
  1028   1028     catchsql {
  1029   1029       CREATE TRIGGER r1 DELETE on t1 BEGIN
................................................................................
  1031   1031       END;
  1032   1032     }
  1033   1033   } {0 {}}
  1034   1034   do_test auth-1.147 {
  1035   1035     execsql {SELECT name FROM sqlite_temp_master}
  1036   1036   } {t1}
  1037   1037   do_test auth-1.148 {
  1038         -  proc auth {code arg1 arg2 arg3 arg4} {
         1038  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1039   1039       if {$code=="SQLITE_CREATE_TEMP_TRIGGER"} {
  1040   1040         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1041   1041         return SQLITE_OK
  1042   1042       }
  1043   1043       return SQLITE_OK
  1044   1044     }
  1045   1045     catchsql {
................................................................................
  1052   1052     set ::authargs
  1053   1053   } {r1 t1 temp {}}
  1054   1054   do_test auth-1.150 {
  1055   1055     execsql {SELECT name FROM sqlite_temp_master}
  1056   1056   } {t1 r1}
  1057   1057   
  1058   1058   do_test auth-1.151 {
  1059         -  proc auth {code arg1 arg2 arg3 arg4} {
         1059  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1060   1060       if {$code=="SQLITE_DELETE" && $arg1=="sqlite_master"} {
  1061   1061         return SQLITE_DENY
  1062   1062       }
  1063   1063       return SQLITE_OK
  1064   1064     }
  1065   1065     catchsql {DROP TRIGGER r2}
  1066   1066   } {1 {not authorized}}
  1067   1067   do_test auth-1.152 {
  1068   1068     execsql {SELECT name FROM sqlite_master}
  1069   1069   } {t2 tx r2}
  1070   1070   do_test auth-1.153 {
  1071         -  proc auth {code arg1 arg2 arg3 arg4} {
         1071  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1072   1072       if {$code=="SQLITE_DROP_TRIGGER"} {
  1073   1073         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1074   1074         return SQLITE_DENY
  1075   1075       }
  1076   1076       return SQLITE_OK
  1077   1077     }
  1078   1078     catchsql {DROP TRIGGER r2}
................................................................................
  1080   1080   do_test auth-1.154 {
  1081   1081     set ::authargs
  1082   1082   } {r2 t2 main {}}
  1083   1083   do_test auth-1.155 {
  1084   1084     execsql {SELECT name FROM sqlite_master}
  1085   1085   } {t2 tx r2}
  1086   1086   do_test auth-1.156 {
  1087         -  proc auth {code arg1 arg2 arg3 arg4} {
         1087  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1088   1088       if {$code=="SQLITE_DELETE" && $arg1=="sqlite_master"} {
  1089   1089         return SQLITE_IGNORE
  1090   1090       }
  1091   1091       return SQLITE_OK
  1092   1092     }
  1093   1093     catchsql {DROP TRIGGER r2}
  1094   1094   } {0 {}}
  1095   1095   do_test auth-1.157 {
  1096   1096     execsql {SELECT name FROM sqlite_master}
  1097   1097   } {t2 tx r2}
  1098   1098   do_test auth-1.158 {
  1099         -  proc auth {code arg1 arg2 arg3 arg4} {
         1099  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1100   1100       if {$code=="SQLITE_DROP_TRIGGER"} {
  1101   1101         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1102   1102         return SQLITE_IGNORE
  1103   1103       }
  1104   1104       return SQLITE_OK
  1105   1105     }
  1106   1106     catchsql {DROP TRIGGER r2}
................................................................................
  1108   1108   do_test auth-1.159 {
  1109   1109     set ::authargs
  1110   1110   } {r2 t2 main {}}
  1111   1111   do_test auth-1.160 {
  1112   1112     execsql {SELECT name FROM sqlite_master}
  1113   1113   } {t2 tx r2}
  1114   1114   do_test auth-1.161 {
  1115         -  proc auth {code arg1 arg2 arg3 arg4} {
         1115  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1116   1116       if {$code=="SQLITE_DROP_TRIGGER"} {
  1117   1117         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1118   1118         return SQLITE_OK
  1119   1119       }
  1120   1120       return SQLITE_OK
  1121   1121     }
  1122   1122     catchsql {DROP TRIGGER r2}
................................................................................
  1129   1129       DROP TABLE tx;
  1130   1130       DELETE FROM t2 WHERE a=1 AND b=2 AND c=3;
  1131   1131       SELECT name FROM sqlite_master;
  1132   1132     }
  1133   1133   } {t2}
  1134   1134   
  1135   1135   do_test auth-1.164 {
  1136         -  proc auth {code arg1 arg2 arg3 arg4} {
         1136  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1137   1137       if {$code=="SQLITE_DELETE" && $arg1=="sqlite_temp_master"} {
  1138   1138         return SQLITE_DENY
  1139   1139       }
  1140   1140       return SQLITE_OK
  1141   1141     }
  1142   1142     catchsql {DROP TRIGGER r1}
  1143   1143   } {1 {not authorized}}
  1144   1144   do_test auth-1.165 {
  1145   1145     execsql {SELECT name FROM sqlite_temp_master}
  1146   1146   } {t1 r1}
  1147   1147   do_test auth-1.166 {
  1148         -  proc auth {code arg1 arg2 arg3 arg4} {
         1148  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1149   1149       if {$code=="SQLITE_DROP_TEMP_TRIGGER"} {
  1150   1150         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1151   1151         return SQLITE_DENY
  1152   1152       }
  1153   1153       return SQLITE_OK
  1154   1154     }
  1155   1155     catchsql {DROP TRIGGER r1}
................................................................................
  1157   1157   do_test auth-1.167 {
  1158   1158     set ::authargs
  1159   1159   } {r1 t1 temp {}}
  1160   1160   do_test auth-1.168 {
  1161   1161     execsql {SELECT name FROM sqlite_temp_master}
  1162   1162   } {t1 r1}
  1163   1163   do_test auth-1.169 {
  1164         -  proc auth {code arg1 arg2 arg3 arg4} {
         1164  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1165   1165       if {$code=="SQLITE_DELETE" && $arg1=="sqlite_temp_master"} {
  1166   1166         return SQLITE_IGNORE
  1167   1167       }
  1168   1168       return SQLITE_OK
  1169   1169     }
  1170   1170     catchsql {DROP TRIGGER r1}
  1171   1171   } {0 {}}
  1172   1172   do_test auth-1.170 {
  1173   1173     execsql {SELECT name FROM sqlite_temp_master}
  1174   1174   } {t1 r1}
  1175   1175   do_test auth-1.171 {
  1176         -  proc auth {code arg1 arg2 arg3 arg4} {
         1176  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1177   1177       if {$code=="SQLITE_DROP_TEMP_TRIGGER"} {
  1178   1178         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1179   1179         return SQLITE_IGNORE
  1180   1180       }
  1181   1181       return SQLITE_OK
  1182   1182     }
  1183   1183     catchsql {DROP TRIGGER r1}
................................................................................
  1185   1185   do_test auth-1.172 {
  1186   1186     set ::authargs
  1187   1187   } {r1 t1 temp {}}
  1188   1188   do_test auth-1.173 {
  1189   1189     execsql {SELECT name FROM sqlite_temp_master}
  1190   1190   } {t1 r1}
  1191   1191   do_test auth-1.174 {
  1192         -  proc auth {code arg1 arg2 arg3 arg4} {
         1192  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1193   1193       if {$code=="SQLITE_DROP_TEMP_TRIGGER"} {
  1194   1194         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1195   1195         return SQLITE_OK
  1196   1196       }
  1197   1197       return SQLITE_OK
  1198   1198     }
  1199   1199     catchsql {DROP TRIGGER r1}
................................................................................
  1203   1203   } {r1 t1 temp {}}
  1204   1204   do_test auth-1.176 {
  1205   1205     execsql {SELECT name FROM sqlite_temp_master}
  1206   1206   } {t1}
  1207   1207   } ;# ifcapable trigger
  1208   1208   
  1209   1209   do_test auth-1.177 {
  1210         -  proc auth {code arg1 arg2 arg3 arg4} {
         1210  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1211   1211       if {$code=="SQLITE_CREATE_INDEX"} {
  1212   1212         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1213   1213         return SQLITE_DENY
  1214   1214       }
  1215   1215       return SQLITE_OK
  1216   1216     }
  1217   1217     catchsql {CREATE INDEX i2 ON t2(a)}
................................................................................
  1219   1219   do_test auth-1.178 {
  1220   1220     set ::authargs
  1221   1221   } {i2 t2 main {}}
  1222   1222   do_test auth-1.179 {
  1223   1223     execsql {SELECT name FROM sqlite_master}
  1224   1224   } {t2}
  1225   1225   do_test auth-1.180 {
  1226         -  proc auth {code arg1 arg2 arg3 arg4} {
         1226  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1227   1227       if {$code=="SQLITE_INSERT" && $arg1=="sqlite_master"} {
  1228   1228         return SQLITE_DENY
  1229   1229       }
  1230   1230       return SQLITE_OK
  1231   1231     }
  1232   1232     catchsql {CREATE INDEX i2 ON t2(a)}
  1233   1233   } {1 {not authorized}}
  1234   1234   do_test auth-1.181 {
  1235   1235     execsql {SELECT name FROM sqlite_master}
  1236   1236   } {t2}
  1237   1237   do_test auth-1.182 {
  1238         -  proc auth {code arg1 arg2 arg3 arg4} {
         1238  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1239   1239       if {$code=="SQLITE_CREATE_INDEX"} {
  1240   1240         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1241   1241         return SQLITE_IGNORE
  1242   1242       }
  1243   1243       return SQLITE_OK
  1244   1244     }
  1245   1245     catchsql {CREATE INDEX i2 ON t2(b)}
................................................................................
  1247   1247   do_test auth-1.183 {
  1248   1248     set ::authargs
  1249   1249   } {i2 t2 main {}}
  1250   1250   do_test auth-1.184 {
  1251   1251     execsql {SELECT name FROM sqlite_master}
  1252   1252   } {t2}
  1253   1253   do_test auth-1.185 {
  1254         -  proc auth {code arg1 arg2 arg3 arg4} {
         1254  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1255   1255       if {$code=="SQLITE_INSERT" && $arg1=="sqlite_master"} {
  1256   1256         return SQLITE_IGNORE
  1257   1257       }
  1258   1258       return SQLITE_OK
  1259   1259     }
  1260   1260     catchsql {CREATE INDEX i2 ON t2(b)}
  1261   1261   } {0 {}}
  1262   1262   do_test auth-1.186 {
  1263   1263     execsql {SELECT name FROM sqlite_master}
  1264   1264   } {t2}
  1265   1265   do_test auth-1.187 {
  1266         -  proc auth {code arg1 arg2 arg3 arg4} {
         1266  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1267   1267       if {$code=="SQLITE_CREATE_INDEX"} {
  1268   1268         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1269   1269         return SQLITE_OK
  1270   1270       }
  1271   1271       return SQLITE_OK
  1272   1272     }
  1273   1273     catchsql {CREATE INDEX i2 ON t2(a)}
................................................................................
  1277   1277   } {i2 t2 main {}}
  1278   1278   do_test auth-1.189 {
  1279   1279     execsql {SELECT name FROM sqlite_master}
  1280   1280   } {t2 i2}
  1281   1281   
  1282   1282   ifcapable tempdb {
  1283   1283     do_test auth-1.190 {
  1284         -    proc auth {code arg1 arg2 arg3 arg4} {
         1284  +    proc auth {code arg1 arg2 arg3 arg4 args} {
  1285   1285         if {$code=="SQLITE_CREATE_TEMP_INDEX"} {
  1286   1286           set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1287   1287           return SQLITE_DENY
  1288   1288         }
  1289   1289         return SQLITE_OK
  1290   1290       }
  1291   1291       catchsql {CREATE INDEX i1 ON t1(a)}
................................................................................
  1293   1293     do_test auth-1.191 {
  1294   1294       set ::authargs
  1295   1295     } {i1 t1 temp {}}
  1296   1296     do_test auth-1.192 {
  1297   1297       execsql {SELECT name FROM sqlite_temp_master}
  1298   1298     } {t1}
  1299   1299     do_test auth-1.193 {
  1300         -    proc auth {code arg1 arg2 arg3 arg4} {
         1300  +    proc auth {code arg1 arg2 arg3 arg4 args} {
  1301   1301         if {$code=="SQLITE_INSERT" && $arg1=="sqlite_temp_master"} {
  1302   1302           return SQLITE_DENY
  1303   1303         }
  1304   1304         return SQLITE_OK
  1305   1305       }
  1306   1306       catchsql {CREATE INDEX i1 ON t1(b)}
  1307   1307     } {1 {not authorized}}
  1308   1308     do_test auth-1.194 {
  1309   1309       execsql {SELECT name FROM sqlite_temp_master}
  1310   1310     } {t1}
  1311   1311     do_test auth-1.195 {
  1312         -    proc auth {code arg1 arg2 arg3 arg4} {
         1312  +    proc auth {code arg1 arg2 arg3 arg4 args} {
  1313   1313         if {$code=="SQLITE_CREATE_TEMP_INDEX"} {
  1314   1314           set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1315   1315           return SQLITE_IGNORE
  1316   1316         }
  1317   1317         return SQLITE_OK
  1318   1318       }
  1319   1319       catchsql {CREATE INDEX i1 ON t1(b)}
................................................................................
  1321   1321     do_test auth-1.196 {
  1322   1322       set ::authargs
  1323   1323     } {i1 t1 temp {}}
  1324   1324     do_test auth-1.197 {
  1325   1325       execsql {SELECT name FROM sqlite_temp_master}
  1326   1326     } {t1}
  1327   1327     do_test auth-1.198 {
  1328         -    proc auth {code arg1 arg2 arg3 arg4} {
         1328  +    proc auth {code arg1 arg2 arg3 arg4 args} {
  1329   1329         if {$code=="SQLITE_INSERT" && $arg1=="sqlite_temp_master"} {
  1330   1330           return SQLITE_IGNORE
  1331   1331         }
  1332   1332         return SQLITE_OK
  1333   1333       }
  1334   1334       catchsql {CREATE INDEX i1 ON t1(c)}
  1335   1335     } {0 {}}
  1336   1336     do_test auth-1.199 {
  1337   1337       execsql {SELECT name FROM sqlite_temp_master}
  1338   1338     } {t1}
  1339   1339     do_test auth-1.200 {
  1340         -    proc auth {code arg1 arg2 arg3 arg4} {
         1340  +    proc auth {code arg1 arg2 arg3 arg4 args} {
  1341   1341         if {$code=="SQLITE_CREATE_TEMP_INDEX"} {
  1342   1342           set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1343   1343           return SQLITE_OK
  1344   1344         }
  1345   1345         return SQLITE_OK
  1346   1346       }
  1347   1347       catchsql {CREATE INDEX i1 ON t1(a)}
................................................................................
  1351   1351     } {i1 t1 temp {}}
  1352   1352     do_test auth-1.202 {
  1353   1353       execsql {SELECT name FROM sqlite_temp_master}
  1354   1354     } {t1 i1}
  1355   1355   }
  1356   1356   
  1357   1357   do_test auth-1.203 {
  1358         -  proc auth {code arg1 arg2 arg3 arg4} {
         1358  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1359   1359       if {$code=="SQLITE_DELETE" && $arg1=="sqlite_master"} {
  1360   1360         return SQLITE_DENY
  1361   1361       }
  1362   1362       return SQLITE_OK
  1363   1363     }
  1364   1364     catchsql {DROP INDEX i2}
  1365   1365   } {1 {not authorized}}
  1366   1366   do_test auth-1.204 {
  1367   1367     execsql {SELECT name FROM sqlite_master}
  1368   1368   } {t2 i2}
  1369   1369   do_test auth-1.205 {
  1370         -  proc auth {code arg1 arg2 arg3 arg4} {
         1370  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1371   1371       if {$code=="SQLITE_DROP_INDEX"} {
  1372   1372         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1373   1373         return SQLITE_DENY
  1374   1374       }
  1375   1375       return SQLITE_OK
  1376   1376     }
  1377   1377     catchsql {DROP INDEX i2}
................................................................................
  1379   1379   do_test auth-1.206 {
  1380   1380     set ::authargs
  1381   1381   } {i2 t2 main {}}
  1382   1382   do_test auth-1.207 {
  1383   1383     execsql {SELECT name FROM sqlite_master}
  1384   1384   } {t2 i2}
  1385   1385   do_test auth-1.208 {
  1386         -  proc auth {code arg1 arg2 arg3 arg4} {
         1386  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1387   1387       if {$code=="SQLITE_DELETE" && $arg1=="sqlite_master"} {
  1388   1388         return SQLITE_IGNORE
  1389   1389       }
  1390   1390       return SQLITE_OK
  1391   1391     }
  1392   1392     catchsql {DROP INDEX i2}
  1393   1393   } {0 {}}
  1394   1394   do_test auth-1.209 {
  1395   1395     execsql {SELECT name FROM sqlite_master}
  1396   1396   } {t2 i2}
  1397   1397   do_test auth-1.210 {
  1398         -  proc auth {code arg1 arg2 arg3 arg4} {
         1398  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1399   1399       if {$code=="SQLITE_DROP_INDEX"} {
  1400   1400         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1401   1401         return SQLITE_IGNORE
  1402   1402       }
  1403   1403       return SQLITE_OK
  1404   1404     }
  1405   1405     catchsql {DROP INDEX i2}
................................................................................
  1407   1407   do_test auth-1.211 {
  1408   1408     set ::authargs
  1409   1409   } {i2 t2 main {}}
  1410   1410   do_test auth-1.212 {
  1411   1411     execsql {SELECT name FROM sqlite_master}
  1412   1412   } {t2 i2}
  1413   1413   do_test auth-1.213 {
  1414         -  proc auth {code arg1 arg2 arg3 arg4} {
         1414  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1415   1415       if {$code=="SQLITE_DROP_INDEX"} {
  1416   1416         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1417   1417         return SQLITE_OK
  1418   1418       }
  1419   1419       return SQLITE_OK
  1420   1420     }
  1421   1421     catchsql {DROP INDEX i2}
................................................................................
  1425   1425   } {i2 t2 main {}}
  1426   1426   do_test auth-1.215 {
  1427   1427     execsql {SELECT name FROM sqlite_master}
  1428   1428   } {t2}
  1429   1429   
  1430   1430   ifcapable tempdb {
  1431   1431     do_test auth-1.216 {
  1432         -    proc auth {code arg1 arg2 arg3 arg4} {
         1432  +    proc auth {code arg1 arg2 arg3 arg4 args} {
  1433   1433         if {$code=="SQLITE_DELETE" && $arg1=="sqlite_temp_master"} {
  1434   1434           return SQLITE_DENY
  1435   1435         }
  1436   1436         return SQLITE_OK
  1437   1437       }
  1438   1438       catchsql {DROP INDEX i1}
  1439   1439     } {1 {not authorized}}
  1440   1440     do_test auth-1.217 {
  1441   1441       execsql {SELECT name FROM sqlite_temp_master}
  1442   1442     } {t1 i1}
  1443   1443     do_test auth-1.218 {
  1444         -    proc auth {code arg1 arg2 arg3 arg4} {
         1444  +    proc auth {code arg1 arg2 arg3 arg4 args} {
  1445   1445         if {$code=="SQLITE_DROP_TEMP_INDEX"} {
  1446   1446           set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1447   1447           return SQLITE_DENY
  1448   1448         }
  1449   1449         return SQLITE_OK
  1450   1450       }
  1451   1451       catchsql {DROP INDEX i1}
................................................................................
  1453   1453     do_test auth-1.219 {
  1454   1454       set ::authargs
  1455   1455     } {i1 t1 temp {}}
  1456   1456     do_test auth-1.220 {
  1457   1457       execsql {SELECT name FROM sqlite_temp_master}
  1458   1458     } {t1 i1}
  1459   1459     do_test auth-1.221 {
  1460         -    proc auth {code arg1 arg2 arg3 arg4} {
         1460  +    proc auth {code arg1 arg2 arg3 arg4 args} {
  1461   1461         if {$code=="SQLITE_DELETE" && $arg1=="sqlite_temp_master"} {
  1462   1462           return SQLITE_IGNORE
  1463   1463         }
  1464   1464         return SQLITE_OK
  1465   1465       }
  1466   1466       catchsql {DROP INDEX i1}
  1467   1467     } {0 {}}
  1468   1468     do_test auth-1.222 {
  1469   1469       execsql {SELECT name FROM sqlite_temp_master}
  1470   1470     } {t1 i1}
  1471   1471     do_test auth-1.223 {
  1472         -    proc auth {code arg1 arg2 arg3 arg4} {
         1472  +    proc auth {code arg1 arg2 arg3 arg4 args} {
  1473   1473         if {$code=="SQLITE_DROP_TEMP_INDEX"} {
  1474   1474           set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1475   1475           return SQLITE_IGNORE
  1476   1476         }
  1477   1477         return SQLITE_OK
  1478   1478       }
  1479   1479       catchsql {DROP INDEX i1}
................................................................................
  1481   1481     do_test auth-1.224 {
  1482   1482       set ::authargs
  1483   1483     } {i1 t1 temp {}}
  1484   1484     do_test auth-1.225 {
  1485   1485       execsql {SELECT name FROM sqlite_temp_master}
  1486   1486     } {t1 i1}
  1487   1487     do_test auth-1.226 {
  1488         -    proc auth {code arg1 arg2 arg3 arg4} {
         1488  +    proc auth {code arg1 arg2 arg3 arg4 args} {
  1489   1489         if {$code=="SQLITE_DROP_TEMP_INDEX"} {
  1490   1490           set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1491   1491           return SQLITE_OK
  1492   1492         }
  1493   1493         return SQLITE_OK
  1494   1494       }
  1495   1495       catchsql {DROP INDEX i1}
................................................................................
  1499   1499     } {i1 t1 temp {}}
  1500   1500     do_test auth-1.228 {
  1501   1501       execsql {SELECT name FROM sqlite_temp_master}
  1502   1502     } {t1}
  1503   1503   }
  1504   1504   
  1505   1505   do_test auth-1.229 {
  1506         -  proc auth {code arg1 arg2 arg3 arg4} {
         1506  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1507   1507       if {$code=="SQLITE_PRAGMA"} {
  1508   1508         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1509   1509         return SQLITE_DENY
  1510   1510       }
  1511   1511       return SQLITE_OK
  1512   1512     }
  1513   1513     catchsql {PRAGMA full_column_names=on}
................................................................................
  1515   1515   do_test auth-1.230 {
  1516   1516     set ::authargs
  1517   1517   } {full_column_names on {} {}}
  1518   1518   do_test auth-1.231 {
  1519   1519     execsql2 {SELECT a FROM t2}
  1520   1520   } {a 11 a 7}
  1521   1521   do_test auth-1.232 {
  1522         -  proc auth {code arg1 arg2 arg3 arg4} {
         1522  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1523   1523       if {$code=="SQLITE_PRAGMA"} {
  1524   1524         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1525   1525         return SQLITE_IGNORE
  1526   1526       }
  1527   1527       return SQLITE_OK
  1528   1528     }
  1529   1529     catchsql {PRAGMA full_column_names=on}
................................................................................
  1531   1531   do_test auth-1.233 {
  1532   1532     set ::authargs
  1533   1533   } {full_column_names on {} {}}
  1534   1534   do_test auth-1.234 {
  1535   1535     execsql2 {SELECT a FROM t2}
  1536   1536   } {a 11 a 7}
  1537   1537   do_test auth-1.235 {
  1538         -  proc auth {code arg1 arg2 arg3 arg4} {
         1538  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1539   1539       if {$code=="SQLITE_PRAGMA"} {
  1540   1540         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1541   1541         return SQLITE_OK
  1542   1542       }
  1543   1543       return SQLITE_OK
  1544   1544     }
  1545   1545     catchsql {PRAGMA full_column_names=on}
  1546   1546   } {0 {}}
  1547   1547   do_test auth-1.236 {
  1548   1548     execsql2 {SELECT a FROM t2}
  1549   1549   } {t2.a 11 t2.a 7}
  1550   1550   do_test auth-1.237 {
  1551         -  proc auth {code arg1 arg2 arg3 arg4} {
         1551  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1552   1552       if {$code=="SQLITE_PRAGMA"} {
  1553   1553         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1554   1554         return SQLITE_OK
  1555   1555       }
  1556   1556       return SQLITE_OK
  1557   1557     }
  1558   1558     catchsql {PRAGMA full_column_names=OFF}
................................................................................
  1561   1561     set ::authargs
  1562   1562   } {full_column_names OFF {} {}}
  1563   1563   do_test auth-1.239 {
  1564   1564     execsql2 {SELECT a FROM t2}
  1565   1565   } {a 11 a 7}
  1566   1566   
  1567   1567   do_test auth-1.240 {
  1568         -  proc auth {code arg1 arg2 arg3 arg4} {
         1568  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1569   1569       if {$code=="SQLITE_TRANSACTION"} {
  1570   1570         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1571   1571         return SQLITE_DENY
  1572   1572       }
  1573   1573       return SQLITE_OK
  1574   1574     }
  1575   1575     catchsql {BEGIN}
  1576   1576   } {1 {not authorized}}
  1577   1577   do_test auth-1.241 {
  1578   1578     set ::authargs
  1579   1579   } {BEGIN {} {} {}}
  1580   1580   do_test auth-1.242 {
  1581         -  proc auth {code arg1 arg2 arg3 arg4} {
         1581  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1582   1582       if {$code=="SQLITE_TRANSACTION" && $arg1!="BEGIN"} {
  1583   1583         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1584   1584         return SQLITE_DENY
  1585   1585       }
  1586   1586       return SQLITE_OK
  1587   1587     }
  1588   1588     catchsql {BEGIN; INSERT INTO t2 VALUES(44,55,66); COMMIT}
................................................................................
  1614   1614   } {11 2 33 7 8 9}
  1615   1615   
  1616   1616   # ticket #340 - authorization for ATTACH and DETACH.
  1617   1617   #
  1618   1618   ifcapable attach {
  1619   1619     do_test auth-1.251 {
  1620   1620       db authorizer ::auth
  1621         -    proc auth {code arg1 arg2 arg3 arg4} {
         1621  +    proc auth {code arg1 arg2 arg3 arg4 args} {
  1622   1622         if {$code=="SQLITE_ATTACH"} {
  1623   1623           set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1624   1624         }
  1625   1625         return SQLITE_OK
  1626   1626       }
  1627   1627       catchsql {
  1628   1628         ATTACH DATABASE ':memory:' AS test1
................................................................................
  1640   1640     do_test auth-1.252c {
  1641   1641       db eval {DETACH test1}
  1642   1642       db eval {ATTACH ':mem' || 'ory:' AS test1}
  1643   1643       set ::authargs
  1644   1644     } {{} {} {} {}}
  1645   1645     do_test auth-1.253 {
  1646   1646       catchsql {DETACH DATABASE test1}
  1647         -    proc auth {code arg1 arg2 arg3 arg4} {
         1647  +    proc auth {code arg1 arg2 arg3 arg4 args} {
  1648   1648         if {$code=="SQLITE_ATTACH"} {
  1649   1649           set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1650   1650           return SQLITE_DENY
  1651   1651         }
  1652   1652         return SQLITE_OK
  1653   1653       }
  1654   1654       catchsql {
................................................................................
  1656   1656       }
  1657   1657     } {1 {not authorized}}
  1658   1658     do_test auth-1.254 {
  1659   1659       lindex [execsql {PRAGMA database_list}] 7
  1660   1660     } {}
  1661   1661     do_test auth-1.255 {
  1662   1662       catchsql {DETACH DATABASE test1}
  1663         -    proc auth {code arg1 arg2 arg3 arg4} {
         1663  +    proc auth {code arg1 arg2 arg3 arg4 args} {
  1664   1664         if {$code=="SQLITE_ATTACH"} {
  1665   1665           set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1666   1666           return SQLITE_IGNORE
  1667   1667         }
  1668   1668         return SQLITE_OK
  1669   1669       }
  1670   1670       catchsql {
................................................................................
  1671   1671         ATTACH DATABASE ':memory:' AS test1;
  1672   1672       }
  1673   1673     } {0 {}}
  1674   1674     do_test auth-1.256 {
  1675   1675       lindex [execsql {PRAGMA database_list}] 7
  1676   1676     } {}
  1677   1677     do_test auth-1.257 {
  1678         -    proc auth {code arg1 arg2 arg3 arg4} {
         1678  +    proc auth {code arg1 arg2 arg3 arg4 args} {
  1679   1679         if {$code=="SQLITE_DETACH"} {
  1680   1680           set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1681   1681           return SQLITE_OK
  1682   1682         }
  1683   1683         return SQLITE_OK
  1684   1684       }
  1685   1685       execsql {ATTACH DATABASE ':memory:' AS test1}
................................................................................
  1688   1688       }
  1689   1689     } {0 {}}
  1690   1690     do_test auth-1.258 {
  1691   1691       lindex [execsql {PRAGMA database_list}] 7
  1692   1692     } {}
  1693   1693     do_test auth-1.259 {
  1694   1694       execsql {ATTACH DATABASE ':memory:' AS test1}
  1695         -    proc auth {code arg1 arg2 arg3 arg4} {
         1695  +    proc auth {code arg1 arg2 arg3 arg4 args} {
  1696   1696         if {$code=="SQLITE_DETACH"} {
  1697   1697           set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1698   1698           return SQLITE_IGNORE
  1699   1699         }
  1700   1700         return SQLITE_OK
  1701   1701       }
  1702   1702       catchsql {
................................................................................
  1706   1706     ifcapable tempdb {
  1707   1707       ifcapable schema_pragmas {
  1708   1708       do_test auth-1.260 {
  1709   1709         lindex [execsql {PRAGMA database_list}] 7
  1710   1710       } {test1}
  1711   1711       } ;# ifcapable schema_pragmas
  1712   1712       do_test auth-1.261 {
  1713         -      proc auth {code arg1 arg2 arg3 arg4} {
         1713  +      proc auth {code arg1 arg2 arg3 arg4 args} {
  1714   1714           if {$code=="SQLITE_DETACH"} {
  1715   1715             set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1716   1716             return SQLITE_DENY
  1717   1717           }
  1718   1718           return SQLITE_OK
  1719   1719         }
  1720   1720         catchsql {
................................................................................
  1731   1731       db authorizer ::auth
  1732   1732       
  1733   1733       # Authorization for ALTER TABLE. These tests are omitted if the library
  1734   1734       # was built without ALTER TABLE support.
  1735   1735       ifcapable altertable {
  1736   1736       
  1737   1737         do_test auth-1.263 {
  1738         -        proc auth {code arg1 arg2 arg3 arg4} {
         1738  +        proc auth {code arg1 arg2 arg3 arg4 args} {
  1739   1739             if {$code=="SQLITE_ALTER_TABLE"} {
  1740   1740               set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1741   1741               return SQLITE_OK
  1742   1742             }
  1743   1743             return SQLITE_OK
  1744   1744           }
  1745   1745           catchsql {
................................................................................
  1749   1749         do_test auth-1.264 {
  1750   1750           execsql {SELECT name FROM sqlite_temp_master WHERE type='table'}
  1751   1751         } {t1x}
  1752   1752         do_test auth-1.265 {
  1753   1753           set authargs
  1754   1754         } {temp t1 {} {}}
  1755   1755         do_test auth-1.266 {
  1756         -        proc auth {code arg1 arg2 arg3 arg4} {
         1756  +        proc auth {code arg1 arg2 arg3 arg4 args} {
  1757   1757             if {$code=="SQLITE_ALTER_TABLE"} {
  1758   1758               set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1759   1759               return SQLITE_IGNORE
  1760   1760             }
  1761   1761             return SQLITE_OK
  1762   1762           }
  1763   1763           catchsql {
................................................................................
  1767   1767         do_test auth-1.267 {
  1768   1768           execsql {SELECT name FROM sqlite_temp_master WHERE type='table'}
  1769   1769         } {t1x}
  1770   1770         do_test auth-1.268 {
  1771   1771           set authargs
  1772   1772         } {temp t1x {} {}}
  1773   1773         do_test auth-1.269 {
  1774         -        proc auth {code arg1 arg2 arg3 arg4} {
         1774  +        proc auth {code arg1 arg2 arg3 arg4 args} {
  1775   1775             if {$code=="SQLITE_ALTER_TABLE"} {
  1776   1776               set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1777   1777               return SQLITE_DENY
  1778   1778             }
  1779   1779             return SQLITE_OK
  1780   1780           }
  1781   1781           catchsql {
................................................................................
  1800   1800   }
  1801   1801   
  1802   1802   ifcapable  altertable {
  1803   1803   db authorizer {}
  1804   1804   catchsql {ALTER TABLE t1x RENAME TO t1}
  1805   1805   db authorizer ::auth
  1806   1806   do_test auth-1.272 {
  1807         -  proc auth {code arg1 arg2 arg3 arg4} {
         1807  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1808   1808       if {$code=="SQLITE_ALTER_TABLE"} {
  1809   1809         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1810   1810         return SQLITE_OK
  1811   1811       }
  1812   1812       return SQLITE_OK
  1813   1813     }
  1814   1814     catchsql {
................................................................................
  1818   1818   do_test auth-1.273 {
  1819   1819     execsql {SELECT name FROM sqlite_master WHERE type='table'}
  1820   1820   } {t2x}
  1821   1821   do_test auth-1.274 {
  1822   1822     set authargs
  1823   1823   } {main t2 {} {}}
  1824   1824   do_test auth-1.275 {
  1825         -  proc auth {code arg1 arg2 arg3 arg4} {
         1825  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1826   1826       if {$code=="SQLITE_ALTER_TABLE"} {
  1827   1827         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1828   1828         return SQLITE_IGNORE
  1829   1829       }
  1830   1830       return SQLITE_OK
  1831   1831     }
  1832   1832     catchsql {
................................................................................
  1836   1836   do_test auth-1.276 {
  1837   1837     execsql {SELECT name FROM sqlite_master WHERE type='table'}
  1838   1838   } {t2x}
  1839   1839   do_test auth-1.277 {
  1840   1840     set authargs
  1841   1841   } {main t2x {} {}}
  1842   1842   do_test auth-1.278 {
  1843         -  proc auth {code arg1 arg2 arg3 arg4} {
         1843  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  1844   1844       if {$code=="SQLITE_ALTER_TABLE"} {
  1845   1845         set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  1846   1846         return SQLITE_DENY
  1847   1847       }
  1848   1848       return SQLITE_OK
  1849   1849     }
  1850   1850     catchsql {
................................................................................
  1863   1863   } ;# ifcapable altertable
  1864   1864   
  1865   1865   # Test the authorization callbacks for the REINDEX command.
  1866   1866   ifcapable reindex {
  1867   1867   
  1868   1868   proc auth {code args} {
  1869   1869     if {$code=="SQLITE_REINDEX"} {
  1870         -    set ::authargs [concat $::authargs $args]
         1870  +    set ::authargs [concat $::authargs [lrange $args 0 3]]
  1871   1871     }
  1872   1872     return SQLITE_OK
  1873   1873   }
  1874   1874   db authorizer auth
  1875   1875   do_test auth-1.281 {
  1876   1876     execsql {
  1877   1877       CREATE TABLE t3(a PRIMARY KEY, b, c);
................................................................................
  1946   1946       execsql {
  1947   1947         REINDEX temp.t3;
  1948   1948       }
  1949   1949       set ::authargs
  1950   1950     } {t3_idx2 {} temp {} t3_idx1 {} temp {} sqlite_autoindex_t3_1 {} temp {}}
  1951   1951     proc auth {code args} {
  1952   1952       if {$code=="SQLITE_REINDEX"} {
  1953         -      set ::authargs [concat $::authargs $args]
         1953  +      set ::authargs [concat $::authargs [lrange $args 0 3]]
  1954   1954         return SQLITE_DENY
  1955   1955       }
  1956   1956       return SQLITE_OK
  1957   1957     }
  1958   1958     do_test auth-1.292 {
  1959   1959       set ::authargs {}
  1960   1960       catchsql {
................................................................................
  1969   1969   }
  1970   1970   
  1971   1971   } ;# ifcapable reindex 
  1972   1972   
  1973   1973   ifcapable analyze {
  1974   1974     proc auth {code args} {
  1975   1975       if {$code=="SQLITE_ANALYZE"} {
  1976         -      set ::authargs [concat $::authargs $args]
         1976  +      set ::authargs [concat $::authargs [lrange $args 0 3]]
  1977   1977       }
  1978   1978       return SQLITE_OK
  1979   1979     }
  1980   1980     do_test auth-1.294 {
  1981   1981       set ::authargs {}
  1982   1982       execsql {
  1983   1983         CREATE TABLE t4(a,b,c);
................................................................................
  2016   2016   
  2017   2017   # Authorization for ALTER TABLE ADD COLUMN.
  2018   2018   # These tests are omitted if the library
  2019   2019   # was built without ALTER TABLE support.
  2020   2020   ifcapable {altertable} {
  2021   2021     do_test auth-1.300 {
  2022   2022       execsql {CREATE TABLE t5(x)}
  2023         -    proc auth {code arg1 arg2 arg3 arg4} {
         2023  +    proc auth {code arg1 arg2 arg3 arg4 args} {
  2024   2024         if {$code=="SQLITE_ALTER_TABLE"} {
  2025   2025           set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  2026   2026           return SQLITE_OK
  2027   2027         }
  2028   2028         return SQLITE_OK
  2029   2029       }
  2030   2030       catchsql {
................................................................................
  2035   2035       set x [execsql {SELECT sql FROM sqlite_master WHERE name='t5'}]
  2036   2036       regexp new_col_1 $x
  2037   2037     } {1}
  2038   2038     do_test auth-1.302 {
  2039   2039       set authargs
  2040   2040     } {main t5 {} {}}
  2041   2041     do_test auth-1.303 {
  2042         -    proc auth {code arg1 arg2 arg3 arg4} {
         2042  +    proc auth {code arg1 arg2 arg3 arg4 args} {
  2043   2043         if {$code=="SQLITE_ALTER_TABLE"} {
  2044   2044           set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  2045   2045           return SQLITE_IGNORE
  2046   2046         }
  2047   2047         return SQLITE_OK
  2048   2048       }
  2049   2049       catchsql {
................................................................................
  2054   2054       set x [execsql {SELECT sql FROM sqlite_master WHERE name='t5'}]
  2055   2055       regexp new_col_2 $x
  2056   2056     } {0}
  2057   2057     do_test auth-1.305 {
  2058   2058       set authargs
  2059   2059     } {main t5 {} {}}
  2060   2060     do_test auth-1.306 {
  2061         -    proc auth {code arg1 arg2 arg3 arg4} {
         2061  +    proc auth {code arg1 arg2 arg3 arg4 args} {
  2062   2062         if {$code=="SQLITE_ALTER_TABLE"} {
  2063   2063           set ::authargs [list $arg1 $arg2 $arg3 $arg4]
  2064   2064           return SQLITE_DENY
  2065   2065         }
  2066   2066         return SQLITE_OK
  2067   2067       }
  2068   2068       catchsql {
................................................................................
  2078   2078       set authargs
  2079   2079     } {main t5 {} {}}
  2080   2080     execsql {DROP TABLE t5}
  2081   2081   } ;# ifcapable altertable
  2082   2082   
  2083   2083   ifcapable {cte} {
  2084   2084     do_test auth-1.310 {
  2085         -    proc auth {code arg1 arg2 arg3 arg4} {
         2085  +    proc auth {code arg1 arg2 arg3 arg4 args} {
  2086   2086         if {$code=="SQLITE_RECURSIVE"} {
  2087   2087           return SQLITE_DENY
  2088   2088         }
  2089   2089         return SQLITE_OK
  2090   2090       }
  2091   2091       db eval {
  2092   2092          DROP TABLE IF EXISTS t1;
................................................................................
  2113   2113       WITH RECURSIVE
  2114   2114          auth1314(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM auth1314 WHERE x<5)
  2115   2115       SELECT * FROM t1 LEFT JOIN auth1314;
  2116   2116     } {1 {not authorized}}
  2117   2117   } ;# ifcapable cte
  2118   2118   
  2119   2119   do_test auth-2.1 {
  2120         -  proc auth {code arg1 arg2 arg3 arg4} {
         2120  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  2121   2121       if {$code=="SQLITE_READ" && $arg1=="t3" && $arg2=="x"} {
  2122   2122         return SQLITE_DENY
  2123   2123       }
  2124   2124       return SQLITE_OK
  2125   2125     }
  2126   2126     db authorizer ::auth
  2127   2127     execsql {CREATE TABLE t3(x INTEGER PRIMARY KEY, y, z)}
................................................................................
  2133   2133   do_test auth-2.2 {
  2134   2134     catchsql {SELECT ROWID,y,z FROM t3}
  2135   2135   } {1 {access to t3.x is prohibited}}
  2136   2136   do_test auth-2.3 {
  2137   2137     catchsql {SELECT OID,y,z FROM t3}
  2138   2138   } {1 {access to t3.x is prohibited}}
  2139   2139   do_test auth-2.4 {
  2140         -  proc auth {code arg1 arg2 arg3 arg4} {
         2140  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  2141   2141       if {$code=="SQLITE_READ" && $arg1=="t3" && $arg2=="x"} {
  2142   2142         return SQLITE_IGNORE
  2143   2143       }
  2144   2144       return SQLITE_OK
  2145   2145     }
  2146   2146     execsql {INSERT INTO t3 VALUES(44,55,66)}
  2147   2147     catchsql {SELECT * FROM t3}
  2148   2148   } {0 {{} 55 66}}
  2149   2149   do_test auth-2.5 {
  2150   2150     catchsql {SELECT rowid,y,z FROM t3}
  2151   2151   } {0 {{} 55 66}}
  2152   2152   do_test auth-2.6 {
  2153         -  proc auth {code arg1 arg2 arg3 arg4} {
         2153  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  2154   2154       if {$code=="SQLITE_READ" && $arg1=="t3" && $arg2=="ROWID"} {
  2155   2155         return SQLITE_IGNORE
  2156   2156       }
  2157   2157       return SQLITE_OK
  2158   2158     }
  2159   2159     catchsql {SELECT * FROM t3}
  2160   2160   } {0 {44 55 66}}
  2161   2161   do_test auth-2.7 {
  2162   2162     catchsql {SELECT ROWID,y,z FROM t3}
  2163   2163   } {0 {44 55 66}}
  2164   2164   do_test auth-2.8 {
  2165         -  proc auth {code arg1 arg2 arg3 arg4} {
         2165  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  2166   2166       if {$code=="SQLITE_READ" && $arg1=="t2" && $arg2=="ROWID"} {
  2167   2167         return SQLITE_IGNORE
  2168   2168       }
  2169   2169       return SQLITE_OK
  2170   2170     }
  2171   2171     catchsql {SELECT ROWID,b,c FROM t2}
  2172   2172   } {0 {{} 2 33 {} 8 9}}
................................................................................
  2177   2177     # trying to recompile the statement, the authorization error is encountered.
  2178   2178     # If we do not flush the cache, the correct error message is returned, but
  2179   2179     # the error code is SQLITE_SCHEMA, not SQLITE_ERROR as required by the test
  2180   2180     # case after this one.
  2181   2181     #
  2182   2182     db cache flush
  2183   2183   
  2184         -  proc auth {code arg1 arg2 arg3 arg4} {
         2184  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  2185   2185       if {$code=="SQLITE_READ" && $arg1=="t2" && $arg2=="ROWID"} {
  2186   2186         return bogus
  2187   2187       }
  2188   2188       return SQLITE_OK
  2189   2189     }
  2190   2190     catchsql {SELECT ROWID,b,c FROM t2}
  2191   2191   } {1 {authorizer malfunction}}
  2192   2192   do_test auth-2.9.2 {
  2193   2193     db errorcode
  2194   2194   } {1}
  2195   2195   do_test auth-2.10 {
  2196         -  proc auth {code arg1 arg2 arg3 arg4} {
         2196  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  2197   2197       if {$code=="SQLITE_SELECT"} {
  2198   2198         return bogus
  2199   2199       }
  2200   2200       return SQLITE_OK
  2201   2201     }
  2202   2202     catchsql {SELECT ROWID,b,c FROM t2}
  2203   2203   } {1 {authorizer malfunction}}
  2204   2204   do_test auth-2.11.1 {
  2205         -  proc auth {code arg1 arg2 arg3 arg4} {
         2205  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  2206   2206       if {$code=="SQLITE_READ" && $arg2=="a"} {
  2207   2207         return SQLITE_IGNORE
  2208   2208       }
  2209   2209       return SQLITE_OK
  2210   2210     }
  2211   2211     catchsql {SELECT * FROM t2, t3}
  2212   2212   } {0 {{} 2 33 44 55 66 {} 8 9 44 55 66}}
  2213   2213   do_test auth-2.11.2 {
  2214         -  proc auth {code arg1 arg2 arg3 arg4} {
         2214  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  2215   2215       if {$code=="SQLITE_READ" && $arg2=="x"} {
  2216   2216         return SQLITE_IGNORE
  2217   2217       }
  2218   2218       return SQLITE_OK
  2219   2219     }
  2220   2220     catchsql {SELECT * FROM t2, t3}
  2221   2221   } {0 {11 2 33 {} 55 66 7 8 9 {} 55 66}}
  2222   2222   
  2223   2223   # Make sure the OLD and NEW pseudo-tables of a trigger get authorized.
  2224   2224   #
  2225   2225   ifcapable trigger {
  2226   2226     do_test auth-3.1 {
  2227         -    proc auth {code arg1 arg2 arg3 arg4} {
         2227  +    proc auth {code arg1 arg2 arg3 arg4 args} {
  2228   2228         return SQLITE_OK
  2229   2229       }
  2230   2230       execsql {
  2231   2231         CREATE TABLE tx(a1,a2,b1,b2,c1,c2);
  2232   2232         CREATE TRIGGER r1 AFTER UPDATE ON t2 FOR EACH ROW BEGIN
  2233   2233           INSERT INTO tx VALUES(OLD.a,NEW.a,OLD.b,NEW.b,OLD.c,NEW.c);
  2234   2234         END;
  2235   2235         UPDATE t2 SET a=a+1;
  2236   2236         SELECT * FROM tx;
  2237   2237       }
  2238   2238     } {11 12 2 2 33 33 7 8 8 8 9 9}
  2239   2239     do_test auth-3.2 {
  2240         -    proc auth {code arg1 arg2 arg3 arg4} {
         2240  +    proc auth {code arg1 arg2 arg3 arg4 args} {
  2241   2241         if {$code=="SQLITE_READ" && $arg1=="t2" && $arg2=="c"} {
  2242   2242           return SQLITE_IGNORE
  2243   2243         }
  2244   2244         return SQLITE_OK
  2245   2245       }
  2246   2246       execsql {
  2247   2247         DELETE FROM tx;
................................................................................
  2251   2251     } {12 112 2 2 {} {} 8 108 8 8 {} {}}
  2252   2252   } ;# ifcapable trigger
  2253   2253   
  2254   2254   # Make sure the names of views and triggers are passed on on arg4.
  2255   2255   #
  2256   2256   ifcapable trigger {
  2257   2257   do_test auth-4.1 {
  2258         -  proc auth {code arg1 arg2 arg3 arg4} {
         2258  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  2259   2259       lappend ::authargs $code $arg1 $arg2 $arg3 $arg4
  2260   2260       return SQLITE_OK
  2261   2261     }
  2262   2262     set authargs {}
  2263   2263     execsql {
  2264   2264       UPDATE t2 SET a=a+1;
  2265   2265     }
................................................................................
  2336   2336   
  2337   2337   } ;# ifcapable view && trigger
  2338   2338   
  2339   2339   # Ticket #1338:  Make sure authentication works in the presence of an AS
  2340   2340   # clause.
  2341   2341   #
  2342   2342   do_test auth-5.1 {
  2343         -  proc auth {code arg1 arg2 arg3 arg4} {
         2343  +  proc auth {code arg1 arg2 arg3 arg4 args} {
  2344   2344       return SQLITE_OK
  2345   2345     }
  2346   2346     execsql {
  2347   2347       SELECT count(a) AS cnt FROM t4 ORDER BY cnt
  2348   2348     }
  2349   2349   } {1}
  2350   2350   
................................................................................
  2389   2389         CREATE TRIGGER t5_tr1 AFTER INSERT ON t5 BEGIN 
  2390   2390           UPDATE t5 SET x = 1 WHERE NEW.x = 0;
  2391   2391         END;
  2392   2392       }
  2393   2393     } {}
  2394   2394     set ::authargs [list]
  2395   2395     proc auth {args} {
  2396         -    eval lappend ::authargs $args
         2396  +    eval lappend ::authargs [lrange $args 0 4]
  2397   2397       return SQLITE_OK
  2398   2398     }
  2399   2399     do_test auth-5.3.2 {
  2400   2400       execsql { INSERT INTO t5 (x) values(0) }
  2401   2401       set ::authargs
  2402   2402     } [list SQLITE_INSERT t5 {} main {}    \
  2403   2403             SQLITE_UPDATE t5 x main t5_tr1 \
................................................................................
  2415   2415     execsql {
  2416   2416       CREATE TABLE t6(a,b,c,d,e,f,g,h);
  2417   2417       INSERT INTO t6 VALUES(1,2,3,4,5,6,7,8);
  2418   2418     }
  2419   2419   } {}
  2420   2420   set ::authargs [list]
  2421   2421   proc auth {args} {
  2422         -  eval lappend ::authargs $args
         2422  +  eval lappend ::authargs [lrange $args 0 4]
  2423   2423     return SQLITE_OK
  2424   2424   }
  2425   2425   do_test auth-6.2 {
  2426   2426     execsql {UPDATE t6 SET rowID=rowID+100}
  2427   2427     set ::authargs
  2428   2428   } [list SQLITE_READ   t6 ROWID main {} \
  2429   2429           SQLITE_UPDATE t6 ROWID main {} \

Changes to test/auth2.test.

    27     27   
    28     28   do_test auth2-1.1 {
    29     29     execsql {
    30     30       CREATE TABLE t1(a,b,c);
    31     31       INSERT INTO t1 VALUES(1,2,3);
    32     32     }
    33     33     set ::flist {}
    34         -  proc auth {code arg1 arg2 arg3 arg4} {
           34  +  proc auth {code arg1 arg2 arg3 arg4 args} {
    35     35       if {$code=="SQLITE_FUNCTION"} {
    36     36         lappend ::flist $arg2
    37     37         if {$arg2=="max"} {
    38     38           return SQLITE_DENY
    39     39         } elseif {$arg2=="min"} {
    40     40           return SQLITE_IGNORE
    41     41         } else {
................................................................................
    76     76   # and when computing the result set of a view.
    77     77   #
    78     78   db close
    79     79   sqlite3 db test.db
    80     80   sqlite3 db2 test.db
    81     81   proc auth {args} {
    82     82     global authargs
    83         -  append authargs $args\n
           83  +  append authargs [lrange $args 0 4]\n
    84     84     return SQLITE_OK
    85     85   }
    86     86   db auth auth
    87     87   do_test auth2-2.1 {
    88     88     set ::authargs {}
    89     89     db eval {
    90     90       CREATE TABLE t2(x,y,z);

Changes to test/auth3.test.

    26     26   }
    27     27   
    28     28   # Disable the statement cache for these tests.
    29     29   # 
    30     30   db cache size 0
    31     31   
    32     32   db authorizer ::auth
    33         -proc auth {code arg1 arg2 arg3 arg4} {
           33  +proc auth {code arg1 arg2 arg3 arg4 args} {
    34     34     if {$code=="SQLITE_DELETE"} {
    35     35       return $::authcode
    36     36     }
    37     37     return SQLITE_OK
    38     38   }
    39     39   
    40     40   #--------------------------------------------------------------------------

Changes to test/fkey2.test.

  1550   1550       execsql {
  1551   1551         CREATE TABLE long(a, b PRIMARY KEY, c);
  1552   1552         CREATE TABLE short(d, e, f REFERENCES long);
  1553   1553         CREATE TABLE mid(g, h, i REFERENCES long DEFERRABLE INITIALLY DEFERRED);
  1554   1554       }
  1555   1555     } {}
  1556   1556   
  1557         -  proc auth {args} {eval lappend ::authargs $args ; return SQLITE_OK}
         1557  +  proc auth {args} {eval lappend ::authargs [lrange $args 0 4]; return SQLITE_OK}
  1558   1558     db auth auth
  1559   1559   
  1560   1560     # An insert on the parent table must read the child key of any deferred
  1561   1561     # foreign key constraints. But not the child key of immediate constraints.
  1562   1562     set authargs {}
  1563   1563     do_test fkey2-18.2 {
  1564   1564       execsql { INSERT INTO long VALUES(1, 2, 3) }

Changes to test/fts4aa.test.

   166    166       db eval {SELECT docid FROM t1 WHERE words MATCH $::q ORDER BY docid}
   167    167     } $r
   168    168   }
   169    169   
   170    170   # Should get the same search results when an authorizer prevents
   171    171   # all PRAGMA statements.
   172    172   #
   173         -proc no_pragma_auth {code arg1 arg2 arg3 arg4} {
          173  +proc no_pragma_auth {code arg1 arg2 arg3 arg4 args} {
   174    174     if {$code=="SQLITE_PRAGMA"} {return SQLITE_DENY}
   175    175     return SQLITE_OK;
   176    176   }
   177    177   do_test fts4aa-4.0 {
   178    178     db auth ::no_pragma_auth
   179    179     db eval {
   180    180       DROP TABLE t1;

Changes to test/savepoint.test.

   557    557     execsql { RELEASE "including Whitespace " }
   558    558   } {}
   559    559   
   560    560   # Test that the authorization callback works.
   561    561   #
   562    562   ifcapable auth {
   563    563     proc auth {args} {
   564         -    eval lappend ::authdata $args
          564  +    eval lappend ::authdata [lrange $args 0 4]
   565    565       return SQLITE_OK
   566    566     }
   567    567     db auth auth
   568    568   
   569    569     do_test savepoint-9.1 {
   570    570       set ::authdata [list]
   571    571       execsql { SAVEPOINT sp1 }
................................................................................
   579    579     do_test savepoint-9.3 {
   580    580       set ::authdata [list]
   581    581       execsql { RELEASE sp1 }
   582    582       set ::authdata
   583    583     } {SQLITE_SAVEPOINT RELEASE sp1 {} {}}
   584    584   
   585    585     proc auth {args} {
   586         -    eval lappend ::authdata $args
          586  +    eval lappend ::authdata [lrange $args 0 4]
   587    587       return SQLITE_DENY
   588    588     }
   589    589     db auth auth
   590    590   
   591    591     do_test savepoint-9.4 {
   592    592       set ::authdata [list]
   593    593       set res [catchsql { SAVEPOINT sp1 }]

Added test/userauth01.test.

            1  +# 2014-09-10
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +# 
           12  +# This file implements tests of the SQLITE_USER_AUTHENTICATION extension.
           13  +#
           14  +
           15  +set testdir [file dirname $argv0]
           16  +source $testdir/tester.tcl
           17  +set testprefix userauth01
           18  +
           19  +ifcapable !userauth {
           20  +  finish_test
           21  +  return
           22  +}
           23  +
           24  +# Create a no-authentication-required database
           25  +#
           26  +do_execsql_test userauth01-1.0 {
           27  +  CREATE TABLE t1(x);
           28  +  INSERT INTO t1 VALUES(1),(2.5),('three'),(x'4444'),(NULL);
           29  +  SELECT quote(x) FROM t1 ORDER BY x;
           30  +  SELECT name FROM sqlite_master;
           31  +} {NULL 1 2.5 'three' X'4444' t1}
           32  +
           33  +# Calling sqlite3_user_authenticate() on a no-authentication-required
           34  +# database connection is a harmless no-op.  
           35  +#
           36  +do_test userauth01-1.1 {
           37  +  sqlite3_user_authenticate db alice pw-4-alice
           38  +  execsql {
           39  +    SELECT quote(x) FROM t1 ORDER BY x;
           40  +    SELECT name FROM sqlite_master;
           41  +  }
           42  +} {NULL 1 2.5 'three' X'4444' t1}
           43  +
           44  +# If sqlite3_user_add(D,U,P,N,A) is called on a no-authentication-required
           45  +# database and A is false, then the call fails with an SQLITE_AUTH error.
           46  +#
           47  +do_test userauth01-1.2 {
           48  +  sqlite3_user_add db bob pw-4-bob 0
           49  +} {SQLITE_AUTH}
           50  +do_test userauth01-1.3 {
           51  +  execsql {
           52  +    SELECT quote(x) FROM t1 ORDER BY x;
           53  +    SELECT name FROM sqlite_master;
           54  +  }
           55  +} {NULL 1 2.5 'three' X'4444' t1}
           56  +
           57  +# When called on a no-authentication-required
           58  +# database and when A is true, the sqlite3_user_add(D,U,P,N,A) routine
           59  +# converts the database into an authentication-required database and
           60  +# logs the database connection D in using user U with password P,N.
           61  +#  
           62  +do_test userauth01-1.4 {
           63  +  sqlite3_user_add db alice pw-4-alice 1
           64  +} {SQLITE_OK}
           65  +do_test userauth01-1.5 {
           66  +  execsql {
           67  +    SELECT quote(x) FROM t1 ORDER BY x;
           68  +    SELECT uname, isadmin FROM sqlite_user ORDER BY uname;
           69  +    SELECT name FROM sqlite_master ORDER BY name;
           70  +  }
           71  +} {NULL 1 2.5 'three' X'4444' alice 1 sqlite_user t1}
           72  +
           73  +# The sqlite3_user_add() interface can be used (by an admin user only)
           74  +# to create a new user.
           75  +#
           76  +do_test userauth01-1.6 {
           77  +  sqlite3_user_add db bob pw-4-bob 0
           78  +  sqlite3_user_add db cindy pw-4-cindy 0
           79  +  sqlite3_user_add db david pw-4-david 0
           80  +  execsql {
           81  +    SELECT uname, isadmin FROM sqlite_user ORDER BY uname;
           82  +  }
           83  +} {alice 1 bob 0 cindy 0 david 0}
           84  +
           85  +# The sqlite_user table is inaccessible (unreadable and unwriteable) to
           86  +# non-admin users and is read-only for admin users.  However, if the same
           87  +#
           88  +do_test userauth01-1.7 {
           89  +  sqlite3 db2 test.db
           90  +  sqlite3_user_authenticate db2 cindy pw-4-cindy
           91  +  db2 eval {
           92  +    SELECT quote(x) FROM t1 ORDER BY x;
           93  +    SELECT name FROM sqlite_master ORDER BY name;
           94  +  }
           95  +} {NULL 1 2.5 'three' X'4444' sqlite_user t1}
           96  +do_test userauth01-1.8 {
           97  +  catchsql {
           98  +    SELECT uname, isadmin FROM sqlite_user ORDER BY uname;
           99  +  } db2
          100  +} {1 {no such table: sqlite_user}}
          101  +
          102  +# Any user can change their own password.  
          103  +#
          104  +do_test userauth01-1.9 {
          105  +  sqlite3_user_change db2 cindy xyzzy-cindy 0
          106  +} {SQLITE_OK}
          107  +do_test userauth01-1.10 {
          108  +  sqlite3_user_authenticate db2 cindy pw-4-cindy
          109  +} {SQLITE_AUTH}
          110  +do_test userauth01-1.11 {
          111  +  sqlite3_user_authenticate db2 cindy xyzzy-cindy
          112  +} {SQLITE_OK}
          113  +do_test userauth01-1.12 {
          114  +  sqlite3_user_change db alice xyzzy-alice 1
          115  +} {SQLITE_OK}
          116  +do_test userauth01-1.13 {
          117  +  sqlite3_user_authenticate db alice pw-4-alice
          118  +} {SQLITE_AUTH}
          119  +do_test userauth01-1.14 {
          120  +  sqlite3_user_authenticate db alice xyzzy-alice
          121  +} {SQLITE_OK}
          122  +
          123  +# No user may change their own admin privilege setting.
          124  +#
          125  +do_test userauth01-1.15 {
          126  +  sqlite3_user_change db alice xyzzy-alice 0
          127  +} {SQLITE_AUTH}
          128  +do_test userauth01-1.16 {
          129  +  db eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
          130  +} {alice 1 bob 0 cindy 0 david 0}
          131  +do_test userauth01-1.17 {
          132  +  sqlite3_user_change db2 cindy xyzzy-cindy 1
          133  +} {SQLITE_AUTH}
          134  +do_test userauth01-1.18 {
          135  +  db eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
          136  +} {alice 1 bob 0 cindy 0 david 0}
          137  +
          138  +# The sqlite3_user_change() interface can be used to change a users
          139  +# login credentials or admin privilege.
          140  +#
          141  +do_test userauth01-1.20 {
          142  +  sqlite3_user_change db david xyzzy-david 1
          143  +} {SQLITE_OK}
          144  +do_test userauth01-1.21 {
          145  +  db eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
          146  +} {alice 1 bob 0 cindy 0 david 1}
          147  +do_test userauth01-1.22 {
          148  +  sqlite3_user_authenticate db2 david xyzzy-david
          149  +} {SQLITE_OK}
          150  +do_test userauth01-1.23 {
          151  +  db2 eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
          152  +} {alice 1 bob 0 cindy 0 david 1}
          153  +do_test userauth01-1.24 {
          154  +  sqlite3_user_change db david pw-4-david 0
          155  +} {SQLITE_OK}
          156  +do_test userauth01-1.25 {
          157  +  sqlite3_user_authenticate db2 david pw-4-david
          158  +} {SQLITE_OK}
          159  +do_test userauth01-1.26 {
          160  +  db eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
          161  +} {alice 1 bob 0 cindy 0 david 0}
          162  +do_test userauth01-1.27 {
          163  +  catchsql {SELECT uname, isadmin FROM sqlite_user ORDER BY uname} db2
          164  +} {1 {no such table: sqlite_user}}
          165  +
          166  +# Only an admin user can change another users login
          167  +# credentials or admin privilege setting.
          168  +#
          169  +do_test userauth01-1.30 {
          170  +  sqlite3_user_change db2 bob xyzzy-bob 1
          171  +} {SQLITE_AUTH}
          172  +do_test userauth01-1.31 {
          173  +  db eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
          174  +} {alice 1 bob 0 cindy 0 david 0}
          175  +
          176  +# The sqlite3_user_delete() interface can be used (by an admin user only)
          177  +# to delete a user.
          178  +#
          179  +do_test userauth01-1.40 {
          180  +  sqlite3_user_delete db bob
          181  +} {SQLITE_OK}
          182  +do_test userauth01-1.41 {
          183  +  db eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
          184  +} {alice 1 cindy 0 david 0}
          185  +do_test userauth01-1.42 {
          186  +  sqlite3_user_delete db2 cindy
          187  +} {SQLITE_AUTH}
          188  +do_test userauth01-1.43 {
          189  +  sqlite3_user_delete db2 alice
          190  +} {SQLITE_AUTH}
          191  +do_test userauth01-1.44 {
          192  +  db eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
          193  +} {alice 1 cindy 0 david 0}
          194  +
          195  +# The currently logged-in user cannot be deleted
          196  +#
          197  +do_test userauth01-1.50 {
          198  +  sqlite3_user_delete db alice
          199  +} {SQLITE_AUTH}
          200  +do_test userauth01-1.51 {
          201  +  db eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
          202  +} {alice 1 cindy 0 david 0}
          203  +
          204  +# When ATTACH-ing new database files to a connection, each newly attached
          205  +# database that is an authentication-required database is checked using
          206  +# the same username and password as supplied to the main database.  If that
          207  +# check fails, then the ATTACH command fails with an SQLITE_AUTH error.
          208  +#
          209  +do_test userauth01-1.60 {
          210  +  forcedelete test3.db
          211  +  sqlite3 db3 test3.db
          212  +  sqlite3_user_add db3 alice xyzzy-alice 1
          213  +} {SQLITE_OK}
          214  +do_test userauth01-1.61 {
          215  +  db3 eval {
          216  +    CREATE TABLE t3(a,b,c); INSERT INTO t3 VALUES(1,2,3);
          217  +    SELECT * FROM t3;
          218  +  }
          219  +} {1 2 3}
          220  +do_test userauth01-1.62 {
          221  +  db eval {
          222  +    ATTACH 'test3.db' AS aux;
          223  +    SELECT * FROM t1, t3 ORDER BY x LIMIT 1;
          224  +    DETACH aux;
          225  +  }
          226  +} {{} 1 2 3}
          227  +do_test userauth01-1.63 {
          228  +  sqlite3_user_change db alice pw-4-alice 1
          229  +  sqlite3_user_authenticate db alice pw-4-alice
          230  +  catchsql {
          231  +    ATTACH 'test3.db' AS aux;
          232  +  }
          233  +} {1 {unable to open database: test3.db}}
          234  +do_test userauth01-1.64 {
          235  +  sqlite3_extended_errcode db
          236  +} {SQLITE_AUTH}
          237  +do_test userauth01-1.65 {
          238  +  db eval {PRAGMA database_list}
          239  +} {~/test3.db/}
          240  +
          241  +# The sqlite3_set_authorizer() callback is modified to take a 7th parameter
          242  +# which is the username of the currently logged in user, or NULL for a
          243  +# no-authentication-required database.
          244  +#
          245  +proc auth {args} {
          246  +  lappend ::authargs $args
          247  +  return SQLITE_OK
          248  +}
          249  +do_test authuser01-2.1 {
          250  +  unset -nocomplain ::authargs
          251  +  db auth auth
          252  +  db eval {SELECT x FROM t1}
          253  +  set ::authargs
          254  +} {/SQLITE_SELECT {} {} {} {} alice/}  
          255  +
          256  +
          257  +finish_test

Changes to test/vtab3.test.

    21     21     return
    22     22   }
    23     23   
    24     24   set ::auth_fail 0
    25     25   set ::auth_log [list]
    26     26   set ::auth_filter [list SQLITE_READ SQLITE_UPDATE SQLITE_SELECT SQLITE_PRAGMA]
    27     27   
    28         -proc auth {code arg1 arg2 arg3 arg4} {
           28  +proc auth {code arg1 arg2 arg3 arg4 args} {
    29     29     if {[lsearch $::auth_filter $code]>-1} {
    30     30       return SQLITE_OK
    31     31     }
    32     32     lappend ::auth_log $code $arg1 $arg2 $arg3 $arg4
    33     33     incr ::auth_fail -1
    34     34     if {$::auth_fail == 0} {
    35     35       return SQLITE_DENY

Changes to test/without_rowid3.test.

  1617   1617       execsql {
  1618   1618         CREATE TABLE long(a, b PRIMARY KEY, c) WITHOUT rowid;
  1619   1619         CREATE TABLE short(d, e, f REFERENCES long);
  1620   1620         CREATE TABLE mid(g, h, i REFERENCES long DEFERRABLE INITIALLY DEFERRED);
  1621   1621       }
  1622   1622     } {}
  1623   1623   
  1624         -  proc auth {args} {eval lappend ::authargs $args ; return SQLITE_OK}
         1624  +  proc auth {args} {eval lappend ::authargs [lrange $args 0 4]; return SQLITE_OK}
  1625   1625     db auth auth
  1626   1626   
  1627   1627     # An insert on the parent table must read the child key of any deferred
  1628   1628     # foreign key constraints. But not the child key of immediate constraints.
  1629   1629     set authargs {}
  1630   1630     do_test without_rowid3-18.2 {
  1631   1631       execsql { INSERT INTO long VALUES(1, 2, 3) }