/ Check-in [c8171ecd]
Login

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

Overview
Comment:Further ideas on user authentication. Not yet working code.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | user-auth
Files: files | file ages | folders
SHA1: c8171ecd0d6f097c9e95d5f6643bae8d67f44750
User & Date: drh 2014-09-10 17:34:28
Context
2014-09-10
19:01
Add the ".user" shell command and implement the sqlite3_user_add() routine. Incremental check-in. The code compiles but does not work. check-in: a0455f9d user: drh tags: user-auth
17:34
Further ideas on user authentication. Not yet working code. check-in: c8171ecd user: drh tags: user-auth
2014-09-09
14:47
Non-working preliminary implementation attempts on user authentication. check-in: 8440f093 user: drh tags: user-auth
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/userauth/userauth.c.

    18     18   **
    19     19   ** To compile with the user-authentication feature, append this file to
    20     20   ** end of an SQLite amalgamation, then add the SQLITE_USER_AUTHENTICATION
    21     21   ** compile-time option.  See the user-auth.txt file in the same source
    22     22   ** directory as this file for additional information.
    23     23   */
    24     24   #ifdef SQLITE_USER_AUTHENTICATION
           25  +#include "sqliteInt.h"
    25     26   
    26     27   /*
    27     28   ** Prepare an SQL statement for use by the user authentication logic.
    28     29   ** Return a pointer to the prepared statement on success.  Return a
    29     30   ** NULL pointer if there is an error of any kind.
    30     31   */
    31     32   static sqlite3_stmt *sqlite3UserAuthPrepare(
................................................................................
    38     39     int rc;
    39     40     va_list ap;
    40     41   
    41     42     va_start(ap, zFormat);
    42     43     zSql = sqlite3_vmprintf(zFormat, ap);
    43     44     va_end(ap);
    44     45     if( zSql==0 ) return 0;
    45         -  savedFlags = db->auth.authFlags;
    46         -  db->auth.authFlags |= UAUTH_Ovrd;
    47     46     rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
    48         -  db->auth.authFlags = savedFlags;
    49     47     sqlite3_free(zSql);
    50     48     if( rc ){
    51     49       sqlite3_finalize(pStmt);
    52     50       pStmt = 0;
    53     51     }
    54     52     return pStmt;
    55     53   }
    56     54   
    57     55   /*
    58     56   ** Check to see if database zDb has a "sqlite_user" table and if it does
    59         -** whether that table can authenticate zUser with nPw,zPw.  
           57  +** whether that table can authenticate zUser with nPw,zPw.  Write one of
           58  +** the UAUTH_* user authorization level codes into *peAuth and return a
           59  +** result code.
    60     60   */
    61         -static int sqlite3UserAuthCheckLogin(
           61  +static int userAuthCheckLogin(
    62     62     sqlite3 *db,               /* The database connection to check */
    63     63     const char *zDb,           /* Name of specific database to check */
    64         -  const char *zUser,         /* User name */
    65         -  int nPw,                   /* Size of password in bytes */
    66         -  const char *zPw,           /* Password */
    67         -  int *pbOk                  /* OUT: write boolean result here */
           64  +  u8 *peAuth                 /* OUT: One of UAUTH_* constants */
    68     65   ){
    69     66     sqlite3_stmt *pStmt;
    70         -  char *zSql;
    71     67     int rc;
    72         -  int iResult;
    73     68   
    74         -  *pbOk = 0;
    75         -  iResult = 0;
           69  +  *peAuth = UAUTH_Unknown;
    76     70     pStmt = sqlite3UserAuthPrepare(db, 
    77     71                 "SELECT 1 FROM \"%w\".sqlite_master "
    78     72                 " WHERE name='sqlite_user' AND type='table'", zDb);
    79         -  if( pStmt==0 ) return SQLITE_NOMEM;
    80         -  rc = sqlite3_step(pStmt):
           73  +  if( pStmt==0 ){
           74  +    return SQLITE_NOMEM;
           75  +  }
           76  +  rc = sqlite3_step(pStmt);
    81     77     sqlite3_finalize(pStmt);
    82     78     if( rc==SQLITE_DONE ){
    83         -    *pbOk = 1;
           79  +    *peAuth = UAUTH_Admin;  /* No sqlite_user table.  Everybody is admin. */
    84     80       return SQLITE_OK;
    85     81     }
    86         -  if( rc!=SQLITE_OK ){
           82  +  if( rc!=SQLITE_ROW ){
    87     83       return rc;
           84  +  }
           85  +  if( db->auth.zAuthUser==0 ){
           86  +    *peAuth = UAUTH_Fail;
           87  +    return SQLITE_OK;
    88     88     }
    89     89     pStmt = sqlite3UserAuthPrepare(db,
    90     90               "SELECT pw=sqlite_crypt(?1,pw), isAdmin FROM \"%w\".sqlite_user"
    91     91               " WHERE uname=?2", zDb);
    92     92     if( pStmt==0 ) return SQLITE_NOMEM;
    93         -  sqlite3_bind_blob(pStmt, 1, zPw, nPw, SQLITE_STATIC);
    94         -  sqlite3_bind_text(pStmt, 2, zUser, -1, SQLITE_STATIC);
    95         -  rc = sqlite_step(pStmt);
           93  +  sqlite3_bind_blob(pStmt, 1, db->auth.zAuthPW, db->auth.nAuthPW,SQLITE_STATIC);
           94  +  sqlite3_bind_text(pStmt, 2, db->auth.zAuthUser, -1, SQLITE_STATIC);
           95  +  rc = sqlite3_step(pStmt);
    96     96     if( rc==SQLITE_ROW && sqlite3_column_int(pStmt,0) ){
    97         -    *pbOk = sqlite3_column_int(pStmt, 1);
           97  +    *peAuth = sqlite3_column_int(pStmt, 1) + UAUTH_User;
           98  +  }else{
           99  +    *peAuth = UAUTH_Fail;
    98    100     }
    99    101     sqlite3_finalize(pStmt);
   100    102     return rc;
   101    103   }
          104  +int sqlite3UserAuthCheckLogin(
          105  +  sqlite3 *db,               /* The database connection to check */
          106  +  const char *zDb,           /* Name of specific database to check */
          107  +  u8 *peAuth                 /* OUT: One of UAUTH_* constants */
          108  +){
          109  +  int rc;
          110  +  u8 savedAuthLevel;
          111  +  savedAuthLevel = db->auth.authLevel;
          112  +  db->auth.authLevel = UAUTH_Admin;
          113  +  rc = userAuthCheckLogin(db, zDb, peAuth);
          114  +  db->auth.authLevel = savedAuthLevel;
          115  +  return rc;
          116  +}
          117  +
   102    118   
   103    119   /*
   104    120   ** If a database contains the SQLITE_USER table, then the
   105    121   ** sqlite3_user_authenticate() interface must be invoked with an
   106    122   ** appropriate username and password prior to enable read and write
   107    123   ** access to the database.
   108    124   **
................................................................................
   112    128   ** If the SQLITE_USER table is not present in the database file, then
   113    129   ** this interface is a harmless no-op returnning SQLITE_OK.
   114    130   */
   115    131   int sqlite3_user_authenticate(
   116    132     sqlite3 *db,           /* The database connection */
   117    133     const char *zUsername, /* Username */
   118    134     int nPW,               /* Number of bytes in aPW[] */
   119         -  const void *aPW        /* Password or credentials */
          135  +  const char *zPW        /* Password or credentials */
   120    136   ){
   121         -  int bOk = 0;
   122    137     int rc;
   123         -
   124         -  rc = sqlite3UserAuthCheckLogin(db, zUsername, nPw, zPw, &bOk);
   125         -  if( bOk ){
   126         -    db->auth.authFlags = bOk==2 ? UAUTH_Auth|UAUTH_Admin : UAUTH_Auth;
   127         -    sqlite3_free(db->auth.zAuthUser);
   128         -    db->auth.zAuthUser = sqlite3_malloc("%s", zUsername);
   129         -    sqlite3_free(db->auth.zPw);
   130         -    db->auth.zPw = sqlite3_malloc( nPw+1 );
   131         -    if( db->auth.zPw ){
   132         -      memcpy(db->auth.zPw,zPw,nPw);
   133         -      db->auth.nPw = nPw;
   134         -      rc = SQLITE_OK;
   135         -    }else{
   136         -      rc = SQLITE_NOMEM;
   137         -    }
   138         -  }else{
   139         -    db->auth.authFlags = 0;
          138  +  u8 authLevel = UAUTH_Fail;
          139  +  db->auth.authLevel = UAUTH_Unknown;
          140  +  sqlite3_free(db->auth.zAuthUser);
          141  +  sqlite3_free(db->auth.zAuthPW);
          142  +  memset(&db->auth, 0, sizeof(db->auth));
          143  +  db->auth.zAuthUser = sqlite3_mprintf("%s", zUsername);
          144  +  if( db->auth.zAuthUser==0 ) return SQLITE_NOMEM;
          145  +  db->auth.zAuthPW = sqlite3_malloc( nPW+1 );
          146  +  if( db->auth.zAuthPW==0 ) return SQLITE_NOMEM;
          147  +  memcpy(db->auth.zAuthPW,zPW,nPW);
          148  +  db->auth.nAuthPW = nPW;
          149  +  rc = sqlite3UserAuthCheckLogin(db, "main", &authLevel);
          150  +  db->auth.authLevel = authLevel;
          151  +  if( rc ){
          152  +    return rc;           /* OOM error, I/O error, etc. */
          153  +  }
          154  +  if( authLevel<UAUTH_User ){
          155  +    return SQLITE_AUTH;  /* Incorrect username and/or password */
   140    156     }
   141         -  return rc;
          157  +  return SQLITE_OK;      /* Successful login */
   142    158   }
   143    159   
   144    160   /*
   145    161   ** The sqlite3_user_add() interface can be used (by an admin user only)
   146    162   ** to create a new user.  When called on a no-authentication-required
   147    163   ** database, this routine converts the database into an authentication-
   148    164   ** required database, automatically makes the added user an
................................................................................
   154    170   int sqlite3_user_add(
   155    171     sqlite3 *db,           /* Database connection */
   156    172     const char *zUsername, /* Username to be added */
   157    173     int isAdmin,           /* True to give new user admin privilege */
   158    174     int nPW,               /* Number of bytes in aPW[] */
   159    175     const void *aPW        /* Password or credentials */
   160    176   ){
   161         -  if( !DbIsAdmin(db) ) return SQLITE_ERROR;
   162         -  
          177  +  if( db->auth.authLevel<UAUTH_Admin ) return SQLITE_ERROR;
   163    178     return SQLITE_OK;
   164    179   }
   165    180   
   166    181   /*
   167    182   ** The sqlite3_user_change() interface can be used to change a users
   168    183   ** login credentials or admin privilege.  Any user can change their own
   169    184   ** login credentials.  Only an admin user can change another users login
................................................................................
   173    188   int sqlite3_user_change(
   174    189     sqlite3 *db,           /* Database connection */
   175    190     const char *zUsername, /* Username to change */
   176    191     int isAdmin,           /* Modified admin privilege for the user */
   177    192     int nPW,               /* Number of bytes in aPW[] */
   178    193     const void *aPW        /* Modified password or credentials */
   179    194   ){
          195  +  if( db->auth.authLevel<UAUTH_User ) return SQLITE_ERROR;
          196  +  if( strcmp(db->auth.zAuthUser, zUsername)!=0
          197  +       && db->auth.authLevel<UAUTH_Admin ) return SQLITE_ERROR;
   180    198     return SQLITE_OK;
   181    199   }
   182    200   
   183    201   /*
   184    202   ** The sqlite3_user_delete() interface can be used (by an admin user only)
   185    203   ** to delete a user.  The currently logged-in user cannot be deleted,
   186    204   ** which guarantees that there is always an admin user and hence that
................................................................................
   187    205   ** the database cannot be converted into a no-authentication-required
   188    206   ** database.
   189    207   */
   190    208   int sqlite3_user_delete(
   191    209     sqlite3 *db,           /* Database connection */
   192    210     const char *zUsername  /* Username to remove */
   193    211   ){
          212  +  if( db->auth.authLevel<UAUTH_Admin ) return SQLITE_ERROR;
   194    213     return SQLITE_OK;
   195    214   }
   196    215   
   197    216   #endif /* SQLITE_USER_AUTHENTICATION */

Changes to main.mk.

    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/userauth.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/userauth.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/build.c.

   298    298     int i;
   299    299     assert( zName!=0 );
   300    300     /* All mutexes are required for schema access.  Make sure we hold them. */
   301    301     assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) );
   302    302   #if SQLITE_USER_AUTHENTICATION
   303    303     /* Only the admin user is allowed to know that the sqlite_user table
   304    304     ** exists */
   305         -  if( DbIsAdmin(db)==0 && sqlite3UserAuthTable(zName)!=0 ) return 0;
          305  +  if( db->auth.authLevel<UAUTH_Admin && sqlite3UserAuthTable(zName)!=0 ){
          306  +    return 0;
          307  +  }
   306    308   #endif
   307    309     for(i=OMIT_TEMPDB; i<db->nDb; i++){
   308    310       int j = (i<2) ? i^1 : i;   /* Search TEMP before MAIN */
   309    311       if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue;
   310    312       assert( sqlite3SchemaMutexHeld(db, j, 0) );
   311    313       p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
   312    314       if( p ) break;
................................................................................
   344    346       if( zDbase ){
   345    347         sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName);
   346    348       }else{
   347    349         sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
   348    350       }
   349    351       pParse->checkSchema = 1;
   350    352     }
          353  +#if SQLITE_USER_AUTHENICATION
          354  +  else if( pParse->db->auth.authLevel<UAUTH_User ){
          355  +    sqlite3ErrorMsg(pParse, "user not authenticated");
          356  +    p = 0;
          357  +  }
          358  +#endif
   351    359     return p;
   352    360   }
   353    361   
   354    362   /*
   355    363   ** Locate the table identified by *p.
   356    364   **
   357    365   ** This is a wrapper around sqlite3LocateTable(). The difference between

Changes to src/main.c.

  2566   2566       }
  2567   2567       sqlite3Error(db, rc);
  2568   2568       goto opendb_out;
  2569   2569     }
  2570   2570     db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt);
  2571   2571     db->aDb[1].pSchema = sqlite3SchemaGet(db, 0);
  2572   2572   
  2573         -#if SQLITE_USER_AUTHENTICATION
  2574         -  db->auth.authFlags = UAUTH_Auth|UAUTH_Admin;
  2575         -#endif
  2576         -
  2577   2573     /* The default safety_level for the main database is 'full'; for the temp
  2578   2574     ** database it is 'NONE'. This matches the pager layer defaults.  
  2579   2575     */
  2580   2576     db->aDb[0].zName = "main";
  2581   2577     db->aDb[0].safety_level = 3;
  2582   2578     db->aDb[1].zName = "temp";
  2583   2579     db->aDb[1].safety_level = 1;

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( !DbIsAdmin(db) ){
         1401  +      if( db->auth.authLevel<UAUTH_Admin ){
  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.

   202    202       rc = initData.rc;
   203    203       goto error_out;
   204    204     }
   205    205     pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName);
   206    206     if( ALWAYS(pTab) ){
   207    207       pTab->tabFlags |= TF_Readonly;
   208    208     }
   209         -#if SQLITE_USER_AUTHENTICATION
   210         -  db->auth.authFlags = UAUTH_Auth|UAUTH_Admin;
   211         -#endif
   212    209   
   213    210     /* Create a cursor to hold the database open
   214    211     */
   215    212     pDb = &db->aDb[iDb];
   216    213     if( pDb->pBt==0 ){
   217    214       if( !OMIT_TEMPDB && ALWAYS(iDb==1) ){
   218    215         DbSetProperty(db, 1, DB_SchemaLoaded);
................................................................................
   360    357       ** of the schema was loaded before the error occurred. The primary
   361    358       ** purpose of this is to allow access to the sqlite_master table
   362    359       ** even when its contents have been corrupted.
   363    360       */
   364    361       DbSetProperty(db, iDb, DB_SchemaLoaded);
   365    362       rc = SQLITE_OK;
   366    363     }
   367         -#if SQLITE_USER_AUTHENTICATION
   368         -  if( rc==SQLITE_OK && iDb!=1 ){
   369         -    if( sqlite3FindTable(db, "sqlite_user", db->aDb[iDb].zName)!=0 ){
   370         -      db->auth.authFlags = UAUTH_AuthReqd;
   371         -    }
   372         -  }
   373         -#endif
   374         -
   375    364   
   376    365     /* Jump here for an error that occurs after successfully allocating
   377    366     ** curMain and calling sqlite3BtreeEnter(). For an error that occurs
   378    367     ** before that point, jump to error_out.
   379    368     */
   380    369   initone_error_out:
   381    370     if( openedTransaction ){
................................................................................
   416    405     }
   417    406   
   418    407     /* Once all the other databases have been initialized, load the schema
   419    408     ** for the TEMP database. This is loaded last, as the TEMP database
   420    409     ** schema may contain references to objects in other databases.
   421    410     */
   422    411   #ifndef SQLITE_OMIT_TEMPDB
   423         -  if( rc==SQLITE_OK && ALWAYS(db->nDb>1)
   424         -                    && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
          412  +  assert( db->nDb>1 );
          413  +  if( rc==SQLITE_OK && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
   425    414       rc = sqlite3InitOne(db, 1, pzErrMsg);
   426    415       if( rc ){
   427    416         sqlite3ResetOneSchema(db, 1);
   428    417       }
   429    418     }
   430    419   #endif
   431    420   
................................................................................
   721    710     int rc;
   722    711     assert( ppStmt!=0 );
   723    712     *ppStmt = 0;
   724    713     if( !sqlite3SafetyCheckOk(db) ){
   725    714       return SQLITE_MISUSE_BKPT;
   726    715     }
   727    716     sqlite3_mutex_enter(db->mutex);
          717  +#if SQLITE_USER_AUTHENTICATION
          718  +  if( db->auth.authLevel<UAUTH_User ){
          719  +    if( db->auth.authLevel==UAUTH_Unknown ){
          720  +      u8 authLevel = UAUTH_Fail;
          721  +      sqlite3UserAuthCheckLogin(db, "main", &authLevel);
          722  +      db->auth.authLevel = authLevel;
          723  +    }
          724  +    if( db->auth.authLevel<UAUTH_User ){
          725  +      sqlite3ErrorWithMsg(db, SQLITE_ERROR, "user not authenticated");
          726  +      sqlite3_mutex_leave(db->mutex);
          727  +      return SQLITE_ERROR;
          728  +    }
          729  +  }
          730  +#endif
   728    731     sqlite3BtreeEnterAll(db);
   729    732     rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail);
   730    733     if( rc==SQLITE_SCHEMA ){
   731    734       sqlite3_finalize(*ppStmt);
   732    735       rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail);
   733    736     }
   734         -#if SQLITE_USER_AUTHENTICATION
   735         -  assert( rc==SQLITE_OK || *ppStmt==0 );
   736         -printf("rc=%d init=%d auth=%d sql=[%.50s]\n", rc, db->init.busy, db->auth.authFlags, zSql);
   737         -fflush(stdout);
   738         -  if( rc==SQLITE_OK && !DbIsAuth(db) && db->init.busy==0 ){
   739         -    sqlite3_finalize(*ppStmt);
   740         -    *ppStmt = 0;
   741         -    sqlite3ErrorWithMsg(db, SQLITE_ERROR, "user not authenticated");
   742         -    rc = SQLITE_ERROR;
   743         -  }
   744         -#endif
   745    737     sqlite3BtreeLeaveAll(db);
   746    738     sqlite3_mutex_leave(db->mutex);
   747    739     assert( rc==SQLITE_OK || *ppStmt==0 );
   748    740     return rc;
   749    741   }
   750    742   
   751    743   /*

Changes to src/sqliteInt.h.

   991    991   #ifdef SQLITE_USER_AUTHENTICATION
   992    992   /*
   993    993   ** Information held in the "sqlite3" database connection object and used
   994    994   ** to manage user authentication.
   995    995   */
   996    996   typedef struct sqlite3_userauth sqlite3_userauth;
   997    997   struct sqlite3_userauth {
   998         -  u8 authFlags;                 /* Status flags for user authentication */
          998  +  u8 authLevel;                 /* Current authentication level */
   999    999     int nAuthPW;                  /* Size of the zAuthPW in bytes */
  1000   1000     char *zAuthPW;                /* Password used to authenticate */
  1001   1001     char *zAuthUser;              /* User name used to authenticate */
  1002   1002   };
  1003   1003   
  1004         -/* Allowed values for sqlite3_userauth.authFlags */
  1005         -#define UAUTH_Ovrd        0x01  /* Do not enforce access restrictions */
  1006         -#define UAUTH_Auth        0x02  /* True if the user has authenticated */
  1007         -#define UAUTH_Admin       0x04  /* True if the user is an administrator */
  1008         -#define UAUTH_AuthReqd    0x08  /* True if main has an sqlite_user table */
  1009         -
  1010         -/* Macros for accessing sqlite3.auth.authFlags */
  1011         -#define DbIsAuth(D)       (((D)->auth.authFlags&UAUTH_Auth)!=0)
  1012         -#define DbIsAdmin(D)      (((D)->auth.authFlags&UAUTH_Admin)!=0)
         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 */
  1013   1009   
  1014   1010   /* Functions used only by user authorization logic */
  1015   1011   int sqlite3UserAuthTable(const char*);
         1012  +int sqlite3UserAuthCheckLogin(sqlite3*,const char*,u8*);
  1016   1013   
  1017   1014   #endif /* SQLITE_USER_AUTHENTICATION */
  1018   1015   
  1019   1016   
  1020   1017   /*
  1021   1018   ** Each database connection is an instance of the following structure.
  1022   1019   */