The sqlite3_open(), sqlite3_open16(), and sqlite3_open_v2() interfaces
work as before: they open a new database connection. However, if the
-database being opened requires authentication, then attempts to prepare
-SQL statements (using sqlite3_prepare_v2(), for example) will fail
-with an SQLITE_AUTH error until after sqlite3_user_authenticate()
-has been called successfully. The sqlite3_user_authenticate() call
-will return SQLITE_OK if the authentication credentials are accepted
-and SQLITE_ERROR if not.
+database being opened requires authentication, then attempts to read
+or write from the database will fail with an SQLITE_AUTH error until
+after sqlite3_user_authenticate() has been called successfully. The
+sqlite3_user_authenticate() call will return SQLITE_OK if the
+authentication credentials are accepted and SQLITE_ERROR if not.
Calling sqlite3_user_authenticate() on a no-authentication-required
database connection is a harmless no-op.
pw BLOB
) WITHOUT ROWID;
-This table is inaccessible (unreadable and unwriteable) to non-admin users
-and is read-only for admin users. However, if the same database file is
-opened by a version of SQLite that omits the -DSQLITE_USER_AUTHENTICATION
-compile-time option, then the sqlite_user table will be readable by
-anybody and writeable by anybody if the "PRAGMA writable_schema=ON"
-statement is run first.
+The sqlite_user table is inaccessible (unreadable and unwriteable) to
+non-admin users and is read-only for admin users. However, if the same
+database file is opened by a version of SQLite that omits
+the -DSQLITE_USER_AUTHENTICATION compile-time option, then the sqlite_user
+table will be readable by anybody and writeable by anybody if
+the "PRAGMA writable_schema=ON" statement is run first.
The sqlite_user.pw field is encoded by a built-in SQL function
"sqlite_crypt(X,Y)". The two arguments are both BLOBs. The first argument
int isAdmin /* Modified admin privilege for the user */
){
sqlite3_stmt *pStmt;
- if( db->auth.authLevel<UAUTH_User ){
+ int rc;
+ u8 authLevel;
+
+ authLevel = db->auth.authLevel;
+ if( authLevel<UAUTH_User ){
/* Must be logged in to make a change */
return SQLITE_AUTH;
}
/* Must be an administrator to change a different user */
return SQLITE_AUTH;
}
- }else if( isAdmin!=(db->auth.authLevel==UAUTH_Admin) ){
+ }else if( isAdmin!=(authLevel==UAUTH_Admin) ){
/* Cannot change the isAdmin setting for self */
return SQLITE_AUTH;
}
+ db->auth.authLevel = UAUTH_Admin;
if( !userTableExists(db, "main") ){
/* This routine is a no-op if the user to be modified does not exist */
- return SQLITE_OK;
+ }else{
+ pStmt = sqlite3UserAuthPrepare(db,
+ "UPDATE sqlite_user SET isAdmin=%d, pw=sqlite_crypt(?1,NULL)"
+ " WHERE uname=%Q", isAdmin, zUsername);
+ if( pStmt==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ sqlite3_bind_blob(pStmt, 1, aPW, nPW, SQLITE_STATIC);
+ sqlite3_step(pStmt);
+ rc = sqlite3_finalize(pStmt);
+ }
}
- pStmt = sqlite3UserAuthPrepare(db,
- "UPDATE sqlite_user SET isAdmin=%d, pw=sqlite_crypt(?1,NULL)"
- " WHERE uname=%Q", isAdmin, zUsername);
- if( pStmt==0 ) return SQLITE_NOMEM;
- sqlite3_bind_blob(pStmt, 1, aPW, nPW, SQLITE_STATIC);
- sqlite3_step(pStmt);
- return sqlite3_finalize(pStmt);
+ db->auth.authLevel = authLevel;
+ return rc;
}
/*
-C Move\suser\sauthentication\sblocking\sfrom\ssqlite3_prepare()\sover\sto\sthe\ntable\slock\sgenerator,\sthus\sallowing\sSQL\sstatements\s(like\s\n"PRAGMA\slocking_mode")\sthat\sdo\snot\stouch\sdatabase\scontent\sto\srun\nprior\sto\sauthentication.
-D 2014-09-11T14:01:41.319
+C Fix\sthe\ssqlite3_user_change()\sinterface\sso\sthat\sit\sdoes\sallow\sa\nnon-admin\suser\sto\schange\stheir\sown\spassword.
+D 2014-09-11T14:40:27.156
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in cf57f673d77606ab0f2d9627ca52a9ba1464146a
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220
-F ext/userauth/user-auth.txt 527aaec593ae34dcaf543324623c8351a5d33d3f
-F ext/userauth/userauth.c a66cd3abcc3b2c10b3999ab49f900d561e8ddd33
+F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
+F ext/userauth/userauth.c bcd1aedb0b810b1a1125945e637af54ce3d299f1
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F test/unordered.test ca7adce0419e4ca0c50f039885e76ed2c531eda8
F test/update.test 1b6c488a8f993d090b7ee9ad0e234faa161b3aeb
F test/uri.test 23662b7b61958b0f0e47082de7d06341ccf85d5b
-F test/userauth01.test 695ead5a47e8827dea283abca69c121b679176af
+F test/userauth01.test 3be4d454af151aa8d59804f2fe4e593f367014c3
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
F test/vacuum2.test af432e6e3bfc0ea20a80cb86a03c7d9876d38324
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 596e728b0eb19a34c888e33d4d37978ca2bf1e00
-R c54f70fc39612d9ea503f6c456a7ab1f
+P 70121e7cf868b7d6d19bf98794ddc3809a901456
+R fc5d3c327123005770c7e41594123732
U drh
-Z e2993baf94376fc5d680228ffe933715
+Z 21dad64c9f9cfa4863908b784242b9b1
-70121e7cf868b7d6d19bf98794ddc3809a901456
\ No newline at end of file
+52d440c7e1b07fc03f14ed5fa4cc4c89a75cd430
\ No newline at end of file
}
} {NULL 1 2.5 'three' X'4444' alice 1 sqlite_user t1}
+# The sqlite3_user_add() interface can be used (by an admin user only)
+# to create a new user.
+#
+do_test userauth01-1.6 {
+ sqlite3_user_add db bob pw-4-bob 0
+ sqlite3_user_add db cindy pw-4-cindy 0
+ sqlite3_user_add db david pw-4-david 0
+ execsql {
+ SELECT uname, isadmin FROM sqlite_user ORDER BY uname;
+ }
+} {alice 1 bob 0 cindy 0 david 0}
+
+# The sqlite_user table is inaccessible (unreadable and unwriteable) to
+# non-admin users and is read-only for admin users. However, if the same
+#
+do_test userauth01-1.7 {
+ sqlite3 db2 test.db
+ sqlite3_user_authenticate db2 cindy pw-4-cindy
+ db2 eval {
+ SELECT quote(x) FROM t1 ORDER BY x;
+ SELECT name FROM sqlite_master ORDER BY name;
+ }
+} {NULL 1 2.5 'three' X'4444' sqlite_user t1}
+do_test userauth01-1.8 {
+ catchsql {
+ SELECT uname, isadmin FROM sqlite_user ORDER BY uname;
+ } db2
+} {1 {no such table: sqlite_user}}
+
+# Any user can change their own password.
+#
+do_test userauth01-1.9 {
+ sqlite3_user_change db2 cindy xyzzy-cindy 0
+} {SQLITE_OK}
+do_test userauth01-1.10 {
+ sqlite3_user_authenticate db2 cindy pw-4-cindy
+} {SQLITE_AUTH}
+do_test userauth01-1.11 {
+ sqlite3_user_authenticate db2 cindy xyzzy-cindy
+} {SQLITE_OK}
+
+
finish_test