]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Further ideas on user authentication. Not yet working code.
authordrh <drh@noemail.net>
Wed, 10 Sep 2014 17:34:28 +0000 (17:34 +0000)
committerdrh <drh@noemail.net>
Wed, 10 Sep 2014 17:34:28 +0000 (17:34 +0000)
FossilOrigin-Name: c8171ecd0d6f097c9e95d5f6643bae8d67f44750

ext/userauth/userauth.c
main.mk
manifest
manifest.uuid
src/build.c
src/main.c
src/pragma.c
src/prepare.c
src/sqliteInt.h

index 305ae43a1120047454b35156db34b45761f45458..518f466f143535d6eff91a803b3a62261a1917a7 100644 (file)
@@ -22,6 +22,7 @@
 ** directory as this file for additional information.
 */
 #ifdef SQLITE_USER_AUTHENTICATION
+#include "sqliteInt.h"
 
 /*
 ** Prepare an SQL statement for use by the user authentication logic.
@@ -42,10 +43,7 @@ static sqlite3_stmt *sqlite3UserAuthPrepare(
   zSql = sqlite3_vmprintf(zFormat, ap);
   va_end(ap);
   if( zSql==0 ) return 0;
-  savedFlags = db->auth.authFlags;
-  db->auth.authFlags |= UAUTH_Ovrd;
   rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
-  db->auth.authFlags = savedFlags;
   sqlite3_free(zSql);
   if( rc ){
     sqlite3_finalize(pStmt);
@@ -56,49 +54,67 @@ static sqlite3_stmt *sqlite3UserAuthPrepare(
 
 /*
 ** Check to see if database zDb has a "sqlite_user" table and if it does
-** whether that table can authenticate zUser with nPw,zPw.  
+** whether that table can authenticate zUser with nPw,zPw.  Write one of
+** the UAUTH_* user authorization level codes into *peAuth and return a
+** result code.
 */
-static int sqlite3UserAuthCheckLogin(
+static int userAuthCheckLogin(
   sqlite3 *db,               /* The database connection to check */
   const char *zDb,           /* Name of specific database to check */
-  const char *zUser,         /* User name */
-  int nPw,                   /* Size of password in bytes */
-  const char *zPw,           /* Password */
-  int *pbOk                  /* OUT: write boolean result here */
+  u8 *peAuth                 /* OUT: One of UAUTH_* constants */
 ){
   sqlite3_stmt *pStmt;
-  char *zSql;
   int rc;
-  int iResult;
 
-  *pbOk = 0;
-  iResult = 0;
+  *peAuth = UAUTH_Unknown;
   pStmt = sqlite3UserAuthPrepare(db, 
               "SELECT 1 FROM \"%w\".sqlite_master "
               " WHERE name='sqlite_user' AND type='table'", zDb);
-  if( pStmt==0 ) return SQLITE_NOMEM;
-  rc = sqlite3_step(pStmt):
+  if( pStmt==0 ){
+    return SQLITE_NOMEM;
+  }
+  rc = sqlite3_step(pStmt);
   sqlite3_finalize(pStmt);
   if( rc==SQLITE_DONE ){
-    *pbOk = 1;
+    *peAuth = UAUTH_Admin;  /* No sqlite_user table.  Everybody is admin. */
     return SQLITE_OK;
   }
-  if( rc!=SQLITE_OK ){
+  if( rc!=SQLITE_ROW ){
     return rc;
   }
+  if( db->auth.zAuthUser==0 ){
+    *peAuth = UAUTH_Fail;
+    return SQLITE_OK;
+  }
   pStmt = sqlite3UserAuthPrepare(db,
             "SELECT pw=sqlite_crypt(?1,pw), isAdmin FROM \"%w\".sqlite_user"
             " WHERE uname=?2", zDb);
   if( pStmt==0 ) return SQLITE_NOMEM;
-  sqlite3_bind_blob(pStmt, 1, zPw, nPw, SQLITE_STATIC);
-  sqlite3_bind_text(pStmt, 2, zUser, -1, SQLITE_STATIC);
-  rc = sqlite_step(pStmt);
+  sqlite3_bind_blob(pStmt, 1, db->auth.zAuthPW, db->auth.nAuthPW,SQLITE_STATIC);
+  sqlite3_bind_text(pStmt, 2, db->auth.zAuthUser, -1, SQLITE_STATIC);
+  rc = sqlite3_step(pStmt);
   if( rc==SQLITE_ROW && sqlite3_column_int(pStmt,0) ){
-    *pbOk = sqlite3_column_int(pStmt, 1);
+    *peAuth = sqlite3_column_int(pStmt, 1) + UAUTH_User;
+  }else{
+    *peAuth = UAUTH_Fail;
   }
   sqlite3_finalize(pStmt);
   return rc;
 }
+int sqlite3UserAuthCheckLogin(
+  sqlite3 *db,               /* The database connection to check */
+  const char *zDb,           /* Name of specific database to check */
+  u8 *peAuth                 /* OUT: One of UAUTH_* constants */
+){
+  int rc;
+  u8 savedAuthLevel;
+  savedAuthLevel = db->auth.authLevel;
+  db->auth.authLevel = UAUTH_Admin;
+  rc = userAuthCheckLogin(db, zDb, peAuth);
+  db->auth.authLevel = savedAuthLevel;
+  return rc;
+}
+
 
 /*
 ** If a database contains the SQLITE_USER table, then the
@@ -116,29 +132,29 @@ int sqlite3_user_authenticate(
   sqlite3 *db,           /* The database connection */
   const char *zUsername, /* Username */
   int nPW,               /* Number of bytes in aPW[] */
-  const void *aPW        /* Password or credentials */
+  const char *zPW        /* Password or credentials */
 ){
-  int bOk = 0;
   int rc;
-
-  rc = sqlite3UserAuthCheckLogin(db, zUsername, nPw, zPw, &bOk);
-  if( bOk ){
-    db->auth.authFlags = bOk==2 ? UAUTH_Auth|UAUTH_Admin : UAUTH_Auth;
-    sqlite3_free(db->auth.zAuthUser);
-    db->auth.zAuthUser = sqlite3_malloc("%s", zUsername);
-    sqlite3_free(db->auth.zPw);
-    db->auth.zPw = sqlite3_malloc( nPw+1 );
-    if( db->auth.zPw ){
-      memcpy(db->auth.zPw,zPw,nPw);
-      db->auth.nPw = nPw;
-      rc = SQLITE_OK;
-    }else{
-      rc = SQLITE_NOMEM;
-    }
-  }else{
-    db->auth.authFlags = 0;
+  u8 authLevel = UAUTH_Fail;
+  db->auth.authLevel = UAUTH_Unknown;
+  sqlite3_free(db->auth.zAuthUser);
+  sqlite3_free(db->auth.zAuthPW);
+  memset(&db->auth, 0, sizeof(db->auth));
+  db->auth.zAuthUser = sqlite3_mprintf("%s", zUsername);
+  if( db->auth.zAuthUser==0 ) return SQLITE_NOMEM;
+  db->auth.zAuthPW = sqlite3_malloc( nPW+1 );
+  if( db->auth.zAuthPW==0 ) return SQLITE_NOMEM;
+  memcpy(db->auth.zAuthPW,zPW,nPW);
+  db->auth.nAuthPW = nPW;
+  rc = sqlite3UserAuthCheckLogin(db, "main", &authLevel);
+  db->auth.authLevel = authLevel;
+  if( rc ){
+    return rc;           /* OOM error, I/O error, etc. */
   }
-  return rc;
+  if( authLevel<UAUTH_User ){
+    return SQLITE_AUTH;  /* Incorrect username and/or password */
+  }
+  return SQLITE_OK;      /* Successful login */
 }
 
 /*
@@ -158,8 +174,7 @@ int sqlite3_user_add(
   int nPW,               /* Number of bytes in aPW[] */
   const void *aPW        /* Password or credentials */
 ){
-  if( !DbIsAdmin(db) ) return SQLITE_ERROR;
-  
+  if( db->auth.authLevel<UAUTH_Admin ) return SQLITE_ERROR;
   return SQLITE_OK;
 }
 
@@ -177,6 +192,9 @@ int sqlite3_user_change(
   int nPW,               /* Number of bytes in aPW[] */
   const void *aPW        /* Modified password or credentials */
 ){
+  if( db->auth.authLevel<UAUTH_User ) return SQLITE_ERROR;
+  if( strcmp(db->auth.zAuthUser, zUsername)!=0
+       && db->auth.authLevel<UAUTH_Admin ) return SQLITE_ERROR;
   return SQLITE_OK;
 }
 
@@ -191,6 +209,7 @@ int sqlite3_user_delete(
   sqlite3 *db,           /* Database connection */
   const char *zUsername  /* Username to remove */
 ){
+  if( db->auth.authLevel<UAUTH_Admin ) return SQLITE_ERROR;
   return SQLITE_OK;
 }
 
diff --git a/main.mk b/main.mk
index 7a20373abc801a3186175dc80f374c5b4dd16656..2de8a230ff27d461b4f7dd186c990acdd38ce401 100644 (file)
--- a/main.mk
+++ b/main.mk
@@ -67,7 +67,7 @@ LIBOBJ+= vdbe.o parse.o \
          pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \
          random.o resolve.o rowset.o rtree.o select.o status.o \
          table.o threads.o tokenize.o trigger.o \
-         update.o util.o vacuum.o \
+         update.o userauth.o util.o vacuum.o \
          vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \
         vdbetrace.o wal.o walker.o where.o utf.o vtab.o
 
@@ -214,7 +214,9 @@ SRC += \
   $(TOP)/ext/rtree/sqlite3rtree.h \
   $(TOP)/ext/rtree/rtree.h \
   $(TOP)/ext/rtree/rtree.c
-
+SRC += \
+  $(TOP)/ext/userauth/userauth.c \
+  $(TOP)/ext/userauth/userauth.h
 
 # Generated source code files
 #
@@ -377,6 +379,8 @@ EXTHDR += \
   $(TOP)/ext/rtree/rtree.h
 EXTHDR += \
   $(TOP)/ext/icu/sqliteicu.h
+EXTHDR += \
+  $(TOP)/ext/userauth/userauth.h
 
 # This is the default Makefile target.  The objects listed here
 # are what get build when you type just "make" with no arguments.
@@ -558,6 +562,9 @@ fts3_write.o:       $(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
 rtree.o:       $(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR)
        $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c
 
+userauth.o:    $(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR)
+       $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/userauth/userauth.c
+
 
 # Rules for building test programs and for running tests
 #
index 0b16bdd037bdef191618ccf882706ffa21619fc1..fcb6f3314e539751ccd36c37c02a7f50484deb49 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Non-working\spreliminary\simplementation\sattempts\son\suser\sauthentication.
-D 2014-09-09T14:47:53.726
+C Further\sideas\son\suser\sauthentication.\s\sNot\syet\sworking\scode.
+D 2014-09-10T17:34:28.937
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in cf57f673d77606ab0f2d9627ca52a9ba1464146a
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -145,12 +145,12 @@ F ext/rtree/sqlite3rtree.h 83349d519fe5f518b3ea025d18dd1fe51b1684bd
 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
 F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
 F ext/userauth/user-auth.txt f471c5a363ab0682b109d85982ea857f9a144ccc
-F ext/userauth/userauth.c cea064a9b66d7497c74cc504b3a01d7f390cbe6e
+F ext/userauth/userauth.c 0d24bcd4a18b354797b9cc6f8e4ba152d385cebe
 F ext/userauth/userauth.h efbfb68ff083749ad63b12dcb5877b936c3458d6
 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
-F main.mk 9b5ccf1097050b1f16681f7d4beeea4f7f7ac2c3
+F main.mk ac53fd5d61941c0ff1f05e710999b64ffd03f069
 F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
 F mkopcodeh.awk c6b3fa301db6ef7ac916b14c60868aeaec1337b5
 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
@@ -174,7 +174,7 @@ F src/btmutex.c 49ca66250c7dfa844a4d4cb8272b87420d27d3a5
 F src/btree.c b1c1cd1cc3ae2e433a23b9a6c9ab53805707d8cd
 F src/btree.h a79aa6a71e7f1055f01052b7f821bd1c2dce95c8
 F src/btreeInt.h e0ecb5dba292722039a7540beb3fc448103273cc
-F src/build.c 8b4c67c9fb638fb2e64b2bcd24677e71a5d61bfc
+F src/build.c 3a61555d469de2e0f5bcd1ac4d58a2a19ab093d5
 F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
 F src/complete.c 535183afb3c75628b78ce82612931ac7cdf26f14
 F src/ctime.c 0231df905e2c4abba4483ee18ffc05adc321df2a
@@ -193,7 +193,7 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
 F src/legacy.c 87c92f4a08e2f70220e3b22a9c3b2482d36a134a
 F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
 F src/loadext.c 31c2122b7dd05a179049bbf163fd4839f181cbab
-F src/main.c 26299e9d9a72239f0652ac9a23e04ced3f536e70
+F src/main.c d15621461fb0c52675eba2b650492ed1beef69ab
 F src/malloc.c 954de5f998c23237e04474a3f2159bf483bba65a
 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
 F src/mem1.c faf615aafd8be74a71494dfa027c113ea5c6615f
@@ -220,8 +220,8 @@ F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0
 F src/pcache.c 2048affdb09a04478b5fc6e64cb1083078d369be
 F src/pcache.h 9b559127b83f84ff76d735c8262f04853be0c59a
 F src/pcache1.c dab8ab930d4a73b99768d881185994f34b80ecaa
-F src/pragma.c e4f6421d7a1f23cd21bf281f2d8c56874879e1d0
-F src/prepare.c 9548c8efb80dbc14b0d54d58574c8a7414cde4db
+F src/pragma.c 3b7b1a5e90804006f44c65464c7032ee6a1d24e3
+F src/prepare.c 51ca716a2f73364d8f57c69c89423a0831d17572
 F src/printf.c e74925089a85e3c9f0e315595f41c139d3d118c2
 F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
 F src/resolve.c 0d1621e45fffe4b4396477cf46e41a84b0145ffb
@@ -231,7 +231,7 @@ F src/shell.c 713cef4d73c05fc8e12f4960072329d767a05d50
 F src/sqlite.h.in 64a77f2822f1325b12050972003184f99b655a0f
 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
 F src/sqlite3ext.h 1f40357fb9b12a80c5a3b2b109fd249b009213d4
-F src/sqliteInt.h 883f905f17a78bb09061a8efa4f2708faa6ffacc
+F src/sqliteInt.h 10a1f056b6b40449a81cf5d708bc0d9fac053c53
 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
 F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
 F src/table.c 4e28a53e66bad8d014a510ef0205f5497c712b08
@@ -1196,10 +1196,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P ad7063aa1a0db32cdbe71815545b2edca57d3bcc
-R 8d9410cfb98bb3b10637c181b910724f
-T *branch * user-auth
-T *sym-user-auth *
-T -sym-trunk *
+P 8440f093bac19a41d44ee352744354eab897fe4e
+R 6f268f8f48a352ef36f94cb71204780d
 U drh
-Z 7af3a6ca660957a95167232843af8c9e
+Z 6484e1728dcc8ed1c2a7dbcf5e6f2393
index c31b773fe55fd512dcaa2d9852bafa3991c95f06..cff06d83f6fb5a1cf293555b98d4a86431831a03 100644 (file)
@@ -1 +1 @@
-8440f093bac19a41d44ee352744354eab897fe4e
\ No newline at end of file
+c8171ecd0d6f097c9e95d5f6643bae8d67f44750
\ No newline at end of file
index c30645cdc6f05d9f46280b0e62c9f5ef503e36ba..f745164e54ea6b32832c5c156e53c8baded56643 100644 (file)
@@ -302,7 +302,9 @@ Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){
 #if SQLITE_USER_AUTHENTICATION
   /* Only the admin user is allowed to know that the sqlite_user table
   ** exists */
-  if( DbIsAdmin(db)==0 && sqlite3UserAuthTable(zName)!=0 ) return 0;
+  if( db->auth.authLevel<UAUTH_Admin && sqlite3UserAuthTable(zName)!=0 ){
+    return 0;
+  }
 #endif
   for(i=OMIT_TEMPDB; i<db->nDb; i++){
     int j = (i<2) ? i^1 : i;   /* Search TEMP before MAIN */
@@ -348,6 +350,12 @@ Table *sqlite3LocateTable(
     }
     pParse->checkSchema = 1;
   }
+#if SQLITE_USER_AUTHENICATION
+  else if( pParse->db->auth.authLevel<UAUTH_User ){
+    sqlite3ErrorMsg(pParse, "user not authenticated");
+    p = 0;
+  }
+#endif
   return p;
 }
 
index f5114b79249df1878c3f604f7ac446da587fa23b..231890de4ba35ec9699d892a0661790665724742 100644 (file)
@@ -2570,10 +2570,6 @@ static int openDatabase(
   db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt);
   db->aDb[1].pSchema = sqlite3SchemaGet(db, 0);
 
-#if SQLITE_USER_AUTHENTICATION
-  db->auth.authFlags = UAUTH_Auth|UAUTH_Admin;
-#endif
-
   /* The default safety_level for the main database is 'full'; for the temp
   ** database it is 'NONE'. This matches the pager layer defaults.  
   */
index 8ae79bda33bea5a77a875ff46cfe6040fc04b9c0..cbd593f2153ae02d7a641f8192c2ccc284851e78 100644 (file)
@@ -1398,7 +1398,7 @@ void sqlite3Pragma(
         mask &= ~(SQLITE_ForeignKeys);
       }
 #if SQLITE_USER_AUTHENTICATION
-      if( !DbIsAdmin(db) ){
+      if( db->auth.authLevel<UAUTH_Admin ){
         /* Do not allow non-admin users to modify the schema arbitrarily */
         mask &= ~(SQLITE_WriteSchema);
       }
index 3703b35176a911af1e7061bb91817d5be0ce9545..d3531f114b7d17c747d49168eb4901e803bf0bf9 100644 (file)
@@ -206,9 +206,6 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
   if( ALWAYS(pTab) ){
     pTab->tabFlags |= TF_Readonly;
   }
-#if SQLITE_USER_AUTHENTICATION
-  db->auth.authFlags = UAUTH_Auth|UAUTH_Admin;
-#endif
 
   /* Create a cursor to hold the database open
   */
@@ -364,14 +361,6 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
     DbSetProperty(db, iDb, DB_SchemaLoaded);
     rc = SQLITE_OK;
   }
-#if SQLITE_USER_AUTHENTICATION
-  if( rc==SQLITE_OK && iDb!=1 ){
-    if( sqlite3FindTable(db, "sqlite_user", db->aDb[iDb].zName)!=0 ){
-      db->auth.authFlags = UAUTH_AuthReqd;
-    }
-  }
-#endif
-
 
   /* Jump here for an error that occurs after successfully allocating
   ** curMain and calling sqlite3BtreeEnter(). For an error that occurs
@@ -420,8 +409,8 @@ int sqlite3Init(sqlite3 *db, char **pzErrMsg){
   ** schema may contain references to objects in other databases.
   */
 #ifndef SQLITE_OMIT_TEMPDB
-  if( rc==SQLITE_OK && ALWAYS(db->nDb>1)
-                    && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
+  assert( db->nDb>1 );
+  if( rc==SQLITE_OK && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
     rc = sqlite3InitOne(db, 1, pzErrMsg);
     if( rc ){
       sqlite3ResetOneSchema(db, 1);
@@ -725,23 +714,26 @@ static int sqlite3LockAndPrepare(
     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_ERROR, "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);
   }
-#if SQLITE_USER_AUTHENTICATION
-  assert( rc==SQLITE_OK || *ppStmt==0 );
-printf("rc=%d init=%d auth=%d sql=[%.50s]\n", rc, db->init.busy, db->auth.authFlags, zSql);
-fflush(stdout);
-  if( rc==SQLITE_OK && !DbIsAuth(db) && db->init.busy==0 ){
-    sqlite3_finalize(*ppStmt);
-    *ppStmt = 0;
-    sqlite3ErrorWithMsg(db, SQLITE_ERROR, "user not authenticated");
-    rc = SQLITE_ERROR;
-  }
-#endif
   sqlite3BtreeLeaveAll(db);
   sqlite3_mutex_leave(db->mutex);
   assert( rc==SQLITE_OK || *ppStmt==0 );
index ae43014c4c89e773c86a49e11057fd9851ab3f6a..0849ee842b1b800e195d1c42b96b3bfe5afba305 100644 (file)
@@ -995,24 +995,21 @@ struct FuncDefHash {
 */
 typedef struct sqlite3_userauth sqlite3_userauth;
 struct sqlite3_userauth {
-  u8 authFlags;                 /* Status flags for user authentication */
+  u8 authLevel;                 /* Current authentication level */
   int nAuthPW;                  /* Size of the zAuthPW in bytes */
   char *zAuthPW;                /* Password used to authenticate */
   char *zAuthUser;              /* User name used to authenticate */
 };
 
-/* Allowed values for sqlite3_userauth.authFlags */
-#define UAUTH_Ovrd        0x01  /* Do not enforce access restrictions */
-#define UAUTH_Auth        0x02  /* True if the user has authenticated */
-#define UAUTH_Admin       0x04  /* True if the user is an administrator */
-#define UAUTH_AuthReqd    0x08  /* True if main has an sqlite_user table */
-
-/* Macros for accessing sqlite3.auth.authFlags */
-#define DbIsAuth(D)       (((D)->auth.authFlags&UAUTH_Auth)!=0)
-#define DbIsAdmin(D)      (((D)->auth.authFlags&UAUTH_Admin)!=0)
+/* Allowed values for sqlite3_userauth.authLevel */
+#define UAUTH_Unknown     0     /* Authentication not yet checked */
+#define UAUTH_Fail        1     /* User authentication failed */
+#define UAUTH_User        2     /* Authenticated as a normal user */
+#define UAUTH_Admin       3     /* Authenticated as an administrator */
 
 /* Functions used only by user authorization logic */
 int sqlite3UserAuthTable(const char*);
+int sqlite3UserAuthCheckLogin(sqlite3*,const char*,u8*);
 
 #endif /* SQLITE_USER_AUTHENTICATION */