SQLite

Check-in [70121e7cf8]
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
Timelines: family | ancestors | descendants | both | user-auth
Files: files | file ages | folders
SHA1: 70121e7cf868b7d6d19bf98794ddc3809a901456
User & Date: drh 2014-09-11 14:01:41.319
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: 52d440c7e1 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: 70121e7cf8 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: 596e728b0e user: drh tags: user-auth)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/build.c.
151
152
153
154
155
156
157


















158
159
160
161
162
163
164
  */
  v = sqlite3GetVdbe(pParse);
  assert( !pParse->isMultiWrite 
       || sqlite3VdbeAssertMayAbort(v, pParse->mayAbort));
  if( v ){
    while( sqlite3VdbeDeletePriorOpcode(v, OP_Close) ){}
    sqlite3VdbeAddOp0(v, OP_Halt);



















    /* The cookie mask contains one bit for each database file open.
    ** (Bit 0 is for main, bit 1 is for temp, and so forth.)  Bits are
    ** set for each database that is used.  Generate code to start a
    ** transaction on each used database and to verify the schema cookie
    ** on each used database.
    */







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







151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
  */
  v = sqlite3GetVdbe(pParse);
  assert( !pParse->isMultiWrite 
       || sqlite3VdbeAssertMayAbort(v, pParse->mayAbort));
  if( v ){
    while( sqlite3VdbeDeletePriorOpcode(v, OP_Close) ){}
    sqlite3VdbeAddOp0(v, OP_Halt);

#if SQLITE_USER_AUTHENTICATION
    if( pParse->nTableLock>0 && db->init.busy==0 ){
      if( db->auth.authLevel<UAUTH_User ){
        if( db->auth.authLevel==UAUTH_Unknown ){
          u8 authLevel = UAUTH_Fail;
          sqlite3UserAuthCheckLogin(db, "main", &authLevel);
          db->auth.authLevel = authLevel;
          if( authLevel<UAUTH_Admin ) db->flags &= ~SQLITE_WriteSchema;
        }
        if( db->auth.authLevel<UAUTH_User ){
          pParse->rc = SQLITE_AUTH_USER;
          sqlite3ErrorMsg(pParse, "user not authenticated");
          return;
        }
      }
    }
#endif

    /* The cookie mask contains one bit for each database file open.
    ** (Bit 0 is for main, bit 1 is for temp, and so forth.)  Bits are
    ** set for each database that is used.  Generate code to start a
    ** transaction on each used database and to verify the schema cookie
    ** on each used database.
    */
Changes to src/pragma.c.
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
      int mask = aPragmaNames[mid].iArg;    /* Mask of bits to set or clear. */
      if( db->autoCommit==0 ){
        /* Foreign key support may not be enabled or disabled while not
        ** in auto-commit mode.  */
        mask &= ~(SQLITE_ForeignKeys);
      }
#if SQLITE_USER_AUTHENTICATION
      if( db->auth.authLevel<UAUTH_Admin ){
        /* Do not allow non-admin users to modify the schema arbitrarily */
        mask &= ~(SQLITE_WriteSchema);
      }
#endif

      if( sqlite3GetBoolean(zRight, 0) ){
        db->flags |= mask;







|







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

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







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







711
712
713
714
715
716
717














718
719
720
721
722
723
724
  int rc;
  assert( ppStmt!=0 );
  *ppStmt = 0;
  if( !sqlite3SafetyCheckOk(db) ){
    return SQLITE_MISUSE_BKPT;
  }
  sqlite3_mutex_enter(db->mutex);














  sqlite3BtreeEnterAll(db);
  rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail);
  if( rc==SQLITE_SCHEMA ){
    sqlite3_finalize(*ppStmt);
    rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail);
  }
  sqlite3BtreeLeaveAll(db);