/ Check-in [70121e7c]
Login

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

Overview
Comment:Move user authentication blocking from sqlite3_prepare() over to the table lock generator, thus allowing SQL statements (like "PRAGMA locking_mode") that do not touch database content to run prior to authentication.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | user-auth
Files: files | file ages | folders
SHA1: 70121e7cf868b7d6d19bf98794ddc3809a901456
User & Date: drh 2014-09-11 14:01:41
Context
2014-09-11
14:40
Fix the sqlite3_user_change() interface so that it does allow a non-admin user to change their own password. check-in: 52d440c7 user: drh tags: user-auth
14:01
Move user authentication blocking from sqlite3_prepare() over to the table lock generator, thus allowing SQL statements (like "PRAGMA locking_mode") that do not touch database content to run prior to authentication. check-in: 70121e7c user: drh tags: user-auth
13:44
Add support for the extra parameter on the sqlite3_set_authorizer() callback and support for failing an ATTACH with an authentication-required database using bad credentials. The extension is now feature complete, but much testing and bug-fixing remains. check-in: 596e728b user: drh tags: user-auth
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

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  +      if( db->auth.authLevel<UAUTH_User ){
          162  +        if( db->auth.authLevel==UAUTH_Unknown ){
          163  +          u8 authLevel = UAUTH_Fail;
          164  +          sqlite3UserAuthCheckLogin(db, "main", &authLevel);
          165  +          db->auth.authLevel = authLevel;
          166  +          if( authLevel<UAUTH_Admin ) db->flags &= ~SQLITE_WriteSchema;
          167  +        }
          168  +        if( db->auth.authLevel<UAUTH_User ){
          169  +          pParse->rc = SQLITE_AUTH_USER;
          170  +          sqlite3ErrorMsg(pParse, "user not authenticated");
          171  +          return;
          172  +        }
          173  +      }
          174  +    }
          175  +#endif
   158    176   
   159    177       /* The cookie mask contains one bit for each database file open.
   160    178       ** (Bit 0 is for main, bit 1 is for temp, and so forth.)  Bits are
   161    179       ** set for each database that is used.  Generate code to start a
   162    180       ** transaction on each used database and to verify the schema cookie
   163    181       ** on each used database.
   164    182       */

Changes to src/pragma.c.

  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   1400   #if SQLITE_USER_AUTHENTICATION
  1401         -      if( db->auth.authLevel<UAUTH_Admin ){
         1401  +      if( db->auth.authLevel==UAUTH_User ){
  1402   1402           /* Do not allow non-admin users to modify the schema arbitrarily */
  1403   1403           mask &= ~(SQLITE_WriteSchema);
  1404   1404         }
  1405   1405   #endif
  1406   1406   
  1407   1407         if( sqlite3GetBoolean(zRight, 0) ){
  1408   1408           db->flags |= mask;

Changes to src/prepare.c.

   711    711     int rc;
   712    712     assert( ppStmt!=0 );
   713    713     *ppStmt = 0;
   714    714     if( !sqlite3SafetyCheckOk(db) ){
   715    715       return SQLITE_MISUSE_BKPT;
   716    716     }
   717    717     sqlite3_mutex_enter(db->mutex);
   718         -#if SQLITE_USER_AUTHENTICATION
   719         -  if( db->auth.authLevel<UAUTH_User ){
   720         -    if( db->auth.authLevel==UAUTH_Unknown ){
   721         -      u8 authLevel = UAUTH_Fail;
   722         -      sqlite3UserAuthCheckLogin(db, "main", &authLevel);
   723         -      db->auth.authLevel = authLevel;
   724         -    }
   725         -    if( db->auth.authLevel<UAUTH_User ){
   726         -      sqlite3ErrorWithMsg(db, SQLITE_AUTH_USER, "user not authenticated");
   727         -      sqlite3_mutex_leave(db->mutex);
   728         -      return SQLITE_ERROR;
   729         -    }
   730         -  }
   731         -#endif
   732    718     sqlite3BtreeEnterAll(db);
   733    719     rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail);
   734    720     if( rc==SQLITE_SCHEMA ){
   735    721       sqlite3_finalize(*ppStmt);
   736    722       rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail);
   737    723     }
   738    724     sqlite3BtreeLeaveAll(db);