Non-working preliminary implementation attempts on user authentication.

FossilOrigin-Name: 8440f093bac19a41d44ee352744354eab897fe4e
This commit is contained in:
drh 2014-09-09 14:47:53 +00:00
parent 524a733d89
commit d45309796b
10 changed files with 539 additions and 13 deletions

151
ext/userauth/user-auth.txt Normal file
View File

@ -0,0 +1,151 @@
Activate the user authentication logic by compiling SQLite with
the -DSQLITE_USER_AUTHENTICATION compile-time option.
The following new APIs are available when user authentication is
activated:
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 */
);
int sqlite3_user_add(
sqlite3 *db, /* Database connection */
const char *zUsername, /* Username to be added */
int isAdmin, /* True to give new user admin privilege */
int nPW, /* Number of bytes in aPW[] */
const void *aPW /* Password or credentials */
);
int sqlite3_user_change(
sqlite3 *db, /* Database connection */
const char *zUsername, /* Username to change */
int isAdmin, /* Modified admin privilege for the user */
int nPW, /* Number of bytes in aPW[] */
const void *aPW /* Modified password or credentials */
);
int sqlite3_user_delete(
sqlite3 *db, /* Database connection */
const char *zUsername /* Username to remove */
);
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 the database
connection will be unusable until after sqlite3_user_authenticate()
has been called successfully [1c]. 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.
If the database is encrypted, then sqlite3_key_v2() must be called first,
with the correct decryption key, prior to invoking sqlite3_user_authenticate().
To recapitulate: When opening an existing unencrypted authentication-
required database, the call sequence is:
sqlite3_open_v2()
sqlite3_user_authenticate();
/* Database is now usable */
To open an existing, encrypted, authentication-required database, the
call sequence is:
sqlite3_open_v2();
sqlite3_key_v2();
sqlite3_user_authenticate();
/* Database is now usable */
When opening a no-authentication-required database, the database
connection is treated as if it was authenticated as an admin user.
When ATTACH-ing new database files to a connection, each newly attached
database that is an authentication-required database is checked using
the same username and password as supplied to the main database. If that
check fails, then the ATTACH-ed database is unreadable [1g].
The sqlite3_user_add() interface can be used (by an admin user only)
to create a new user. When called on a no-authentication-required
database, this routine converts the database into an authentication-
required database [3], automatically makes the added user an
administrator [1b], and logs in the current connection as that user [1a].
The sqlite3_user_add() interface only works for the "main" database, not
for any ATTACH-ed databases. Any call to sqlite3_user_add() by a
non-admin user results in an error.
Hence, to create a new, unencrypted, authentication-required database,
the call sequence is:
sqlite3_open_v2();
sqlite3_user_add();
And to create a new, encrypted, authentication-required database, the call
sequence is:
sqlite3_open_v2();
sqlite3_key_v2();
sqlite3_user_add();
The sqlite3_user_delete() interface can be used (by an admin user only)
to delete a user. The currently logged-in user cannot be deleted,
which guarantees that there is always an admin user and hence that
the database cannot be converted into a no-authentication-required
database [3].
The sqlite3_user_change() interface can be used to change a users
login credentials or admin privilege. Any user can change their own
login credentials [1b]. Only an admin user can change another users login
credentials or admin privilege setting. No user may change their own
admin privilege setting.
The sqlite3_set_authorizer() callback is modified to take a 7th parameter
which is the username of the currently logged in user, or NULL for a
no-authentication-required database [1d].
-----------------------------------------------------------------------------
Implementation notes:
An authentication-required database is identified by the presence of a
new table:
CREATE TABLE sqlite_user(
uname TEXT PRIMARY KEY,
isAdmin BOOLEAN,
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.pw field is encoded by a built-in SQL function
"sqlite_crypt(X,Y)". The two arguments are both BLOBs. The first argument
is the plaintext password supplied to the sqlite3_user_authenticate()
interface. The second argument is the sqlite_user.pw value and is supplied
so that the function can extra the "salt" used by the password encoder.
the result of sqlite_crypt(X,Y) is another blob which is the value that
ends up being stored in sqlite_user.pw. To verify credentials X supplied
by the sqlite3_user_authenticate() routine, SQLite runs:
sqlite_user.pw == sqlite_crypt(X, sqlite_user.pw)
To compute an appropriate sqlite_user.pw value from a new or modified
password X, sqlite_crypt(X,NULL) is run. A new random salt is selected
when the second argument is NULL.
The built-in version of of sqlite_crypt() uses a simple Ceasar-cypher
which prevents passwords from being revealed by search the raw database
for ASCII text, but is otherwise trivally broken. To truly secure the
passwords, the database should be encrypted using the SQLite Encryption
Extension or similar technology. Or, the application can use the
sqlite3_create_function() interface to provide an alternative
implementation of sqlite_crypt() that computes a stronger password hash,
perhaps using a cryptographic hash function like SHA1.

197
ext/userauth/userauth.c Normal file
View File

@ -0,0 +1,197 @@
/*
** 2014-09-08
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains the bulk of the implementation of the
** user-authentication extension feature. Some parts of the user-
** authentication code are contained within the SQLite core (in the
** src/ subdirectory of the main source code tree) but those parts
** that could reasonable be separated out are moved into this file.
**
** To compile with the user-authentication feature, append this file to
** end of an SQLite amalgamation, then add the SQLITE_USER_AUTHENTICATION
** compile-time option. See the user-auth.txt file in the same source
** directory as this file for additional information.
*/
#ifdef SQLITE_USER_AUTHENTICATION
/*
** Prepare an SQL statement for use by the user authentication logic.
** Return a pointer to the prepared statement on success. Return a
** NULL pointer if there is an error of any kind.
*/
static sqlite3_stmt *sqlite3UserAuthPrepare(
sqlite3 *db,
const char *zFormat,
...
){
sqlite3_stmt *pStmt;
char *zSql;
int rc;
va_list ap;
va_start(ap, zFormat);
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);
pStmt = 0;
}
return pStmt;
}
/*
** Check to see if database zDb has a "sqlite_user" table and if it does
** whether that table can authenticate zUser with nPw,zPw.
*/
static int sqlite3UserAuthCheckLogin(
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 */
){
sqlite3_stmt *pStmt;
char *zSql;
int rc;
int iResult;
*pbOk = 0;
iResult = 0;
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):
sqlite3_finalize(pStmt);
if( rc==SQLITE_DONE ){
*pbOk = 1;
return SQLITE_OK;
}
if( rc!=SQLITE_OK ){
return rc;
}
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);
if( rc==SQLITE_ROW && sqlite3_column_int(pStmt,0) ){
*pbOk = sqlite3_column_int(pStmt, 1);
}
sqlite3_finalize(pStmt);
return rc;
}
/*
** If a database contains the SQLITE_USER table, then the
** sqlite3_user_authenticate() interface must be invoked with an
** appropriate username and password prior to enable read and write
** access to the database.
**
** Return SQLITE_OK on success or SQLITE_ERROR if the username/password
** combination is incorrect or unknown.
**
** If the SQLITE_USER table is not present in the database file, then
** this interface is a harmless no-op returnning SQLITE_OK.
*/
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 */
){
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;
}
return rc;
}
/*
** The sqlite3_user_add() interface can be used (by an admin user only)
** to create a new user. When called on a no-authentication-required
** database, this routine converts the database into an authentication-
** required database, automatically makes the added user an
** administrator, and logs in the current connection as that user.
** The sqlite3_user_add() interface only works for the "main" database, not
** for any ATTACH-ed databases. Any call to sqlite3_user_add() by a
** non-admin user results in an error.
*/
int sqlite3_user_add(
sqlite3 *db, /* Database connection */
const char *zUsername, /* Username to be added */
int isAdmin, /* True to give new user admin privilege */
int nPW, /* Number of bytes in aPW[] */
const void *aPW /* Password or credentials */
){
if( !DbIsAdmin(db) ) return SQLITE_ERROR;
return SQLITE_OK;
}
/*
** The sqlite3_user_change() interface can be used to change a users
** login credentials or admin privilege. Any user can change their own
** login credentials. Only an admin user can change another users login
** credentials or admin privilege setting. No user may change their own
** admin privilege setting.
*/
int sqlite3_user_change(
sqlite3 *db, /* Database connection */
const char *zUsername, /* Username to change */
int isAdmin, /* Modified admin privilege for the user */
int nPW, /* Number of bytes in aPW[] */
const void *aPW /* Modified password or credentials */
){
return SQLITE_OK;
}
/*
** The sqlite3_user_delete() interface can be used (by an admin user only)
** to delete a user. The currently logged-in user cannot be deleted,
** which guarantees that there is always an admin user and hence that
** the database cannot be converted into a no-authentication-required
** database.
*/
int sqlite3_user_delete(
sqlite3 *db, /* Database connection */
const char *zUsername /* Username to remove */
){
return SQLITE_OK;
}
#endif /* SQLITE_USER_AUTHENTICATION */

88
ext/userauth/userauth.h Normal file
View File

@ -0,0 +1,88 @@
/*
** 2014-09-08
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains the application interface definitions for the
** user-authentication extension feature.
**
** To compile with the user-authentication feature, append this file to
** end of an SQLite amalgamation header file ("sqlite3.h"), then add
** the SQLITE_USER_AUTHENTICATION compile-time option. See the
** user-auth.txt file in the same source directory as this file for
** additional information.
*/
#ifdef SQLITE_USER_AUTHENTICATION
/*
** If a database contains the SQLITE_USER table, then the
** sqlite3_user_authenticate() interface must be invoked with an
** appropriate username and password prior to enable read and write
** access to the database.
**
** Return SQLITE_OK on success or SQLITE_ERROR if the username/password
** combination is incorrect or unknown.
**
** If the SQLITE_USER table is not present in the database file, then
** this interface is a harmless no-op returnning SQLITE_OK.
*/
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 */
);
/*
** The sqlite3_user_add() interface can be used (by an admin user only)
** to create a new user. When called on a no-authentication-required
** database, this routine converts the database into an authentication-
** required database, automatically makes the added user an
** administrator, and logs in the current connection as that user.
** The sqlite3_user_add() interface only works for the "main" database, not
** for any ATTACH-ed databases. Any call to sqlite3_user_add() by a
** non-admin user results in an error.
*/
int sqlite3_user_add(
sqlite3 *db, /* Database connection */
const char *zUsername, /* Username to be added */
int isAdmin, /* True to give new user admin privilege */
int nPW, /* Number of bytes in aPW[] */
const void *aPW /* Password or credentials */
);
/*
** The sqlite3_user_change() interface can be used to change a users
** login credentials or admin privilege. Any user can change their own
** login credentials. Only an admin user can change another users login
** credentials or admin privilege setting. No user may change their own
** admin privilege setting.
*/
int sqlite3_user_change(
sqlite3 *db, /* Database connection */
const char *zUsername, /* Username to change */
int isAdmin, /* Modified admin privilege for the user */
int nPW, /* Number of bytes in aPW[] */
const void *aPW /* Modified password or credentials */
);
/*
** The sqlite3_user_delete() interface can be used (by an admin user only)
** to delete a user. The currently logged-in user cannot be deleted,
** which guarantees that there is always an admin user and hence that
** the database cannot be converted into a no-authentication-required
** database.
*/
int sqlite3_user_delete(
sqlite3 *db, /* Database connection */
const char *zUsername /* Username to remove */
);
#endif /* SQLITE_USER_AUTHENTICATION */

View File

@ -1,5 +1,5 @@
C Fixes\sto\sos_unix.c\sto\ssupport\sdatabase\s(and\sother)\sfiles\slarger\sthan\s2GiB\son\sAndroid.
D 2014-09-06T17:06:13.410
C Non-working\spreliminary\simplementation\sattempts\son\suser\sauthentication.
D 2014-09-09T14:47:53.726
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in cf57f673d77606ab0f2d9627ca52a9ba1464146a
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -144,6 +144,9 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea
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.h efbfb68ff083749ad63b12dcb5877b936c3458d6
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
@ -171,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 8cb237719c185eec7bd8449b2e747491ded11932
F src/build.c 8b4c67c9fb638fb2e64b2bcd24677e71a5d61bfc
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
F src/complete.c 535183afb3c75628b78ce82612931ac7cdf26f14
F src/ctime.c 0231df905e2c4abba4483ee18ffc05adc321df2a
@ -190,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 e48517e3da289d93ad86e8b7b4f68078df5e6e51
F src/main.c 26299e9d9a72239f0652ac9a23e04ced3f536e70
F src/malloc.c 954de5f998c23237e04474a3f2159bf483bba65a
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c faf615aafd8be74a71494dfa027c113ea5c6615f
@ -217,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 14bcdb504128a476cce5bbc086d5226c5e46c225
F src/prepare.c 3842c1dfc0b053458e3adcf9f6efc48e03e3fe3d
F src/pragma.c e4f6421d7a1f23cd21bf281f2d8c56874879e1d0
F src/prepare.c 9548c8efb80dbc14b0d54d58574c8a7414cde4db
F src/printf.c e74925089a85e3c9f0e315595f41c139d3d118c2
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
F src/resolve.c 0d1621e45fffe4b4396477cf46e41a84b0145ffb
@ -228,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 4d1b0488f097aa7be346176c4d5e3cc1e25d99da
F src/sqliteInt.h 883f905f17a78bb09061a8efa4f2708faa6ffacc
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
F src/table.c 4e28a53e66bad8d014a510ef0205f5497c712b08
@ -1193,7 +1196,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P e62aab5e9290503869e1f4d5e0fefd2b4dee0a69 9dca7ce55797b3eb617859f6189c1a2ec6f66566
R 4eacabb789e62917f709201f03eadd53
U dan
Z f60ed4f30cad7188918c7dd18fc1b985
P ad7063aa1a0db32cdbe71815545b2edca57d3bcc
R 8d9410cfb98bb3b10637c181b910724f
T *branch * user-auth
T *sym-user-auth *
T -sym-trunk *
U drh
Z 7af3a6ca660957a95167232843af8c9e

View File

@ -1 +1 @@
ad7063aa1a0db32cdbe71815545b2edca57d3bcc
8440f093bac19a41d44ee352744354eab897fe4e

View File

@ -271,6 +271,16 @@ void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
pParse->nested--;
}
#if SQLITE_USER_AUTHENTICATION
/*
** Return TRUE if zTable is the name of the system table that stores the
** list of users and their access credentials.
*/
int sqlite3UserAuthTable(const char *zTable){
return sqlite3_stricmp(zTable, "sqlite_user")==0;
}
#endif
/*
** Locate the in-memory structure that describes a particular database
** table given the name of that table and (optionally) the name of the
@ -289,6 +299,11 @@ Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){
assert( zName!=0 );
/* All mutexes are required for schema access. Make sure we hold them. */
assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) );
#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;
#endif
for(i=OMIT_TEMPDB; i<db->nDb; i++){
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue;
@ -2867,6 +2882,9 @@ Index *sqlite3CreateIndex(
assert( pTab!=0 );
assert( pParse->nErr==0 );
if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
#if SQLITE_USER_AUTHENTICATION
&& sqlite3UserAuthTable(pTab->zName)==0
#endif
&& sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0 ){
sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
goto exit_create_index;

View File

@ -985,6 +985,10 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
sqlite3Error(db, SQLITE_OK); /* Deallocates any cached error strings. */
sqlite3ValueFree(db->pErr);
sqlite3CloseExtensions(db);
#if SQLITE_USER_AUTHENTICATION
sqlite3_free(db->auth.zAuthUser);
sqlite3_free(db->auth.zAuthPW);
#endif
db->magic = SQLITE_MAGIC_ERROR;
@ -2566,6 +2570,9 @@ 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.

View File

@ -1397,6 +1397,12 @@ void sqlite3Pragma(
** in auto-commit mode. */
mask &= ~(SQLITE_ForeignKeys);
}
#if SQLITE_USER_AUTHENTICATION
if( !DbIsAdmin(db) ){
/* Do not allow non-admin users to modify the schema arbitrarily */
mask &= ~(SQLITE_WriteSchema);
}
#endif
if( sqlite3GetBoolean(zRight, 0) ){
db->flags |= mask;

View File

@ -206,6 +206,9 @@ 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
*/
@ -361,6 +364,14 @@ 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
@ -720,6 +731,17 @@ static int sqlite3LockAndPrepare(
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 );

View File

@ -988,6 +988,35 @@ struct FuncDefHash {
FuncDef *a[23]; /* Hash table for functions */
};
#ifdef SQLITE_USER_AUTHENTICATION
/*
** Information held in the "sqlite3" database connection object and used
** to manage user authentication.
*/
typedef struct sqlite3_userauth sqlite3_userauth;
struct sqlite3_userauth {
u8 authFlags; /* Status flags for user authentication */
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)
/* Functions used only by user authorization logic */
int sqlite3UserAuthTable(const char*);
#endif /* SQLITE_USER_AUTHENTICATION */
/*
** Each database connection is an instance of the following structure.
*/
@ -1082,7 +1111,6 @@ struct sqlite3 {
i64 nDeferredCons; /* Net deferred constraints this transaction. */
i64 nDeferredImmCons; /* Net deferred immediate constraints */
int *pnBytesFreed; /* If not NULL, increment this in DbFree() */
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
/* The following variables are all protected by the STATIC_MASTER
** mutex, not by sqlite3.mutex. They are used by code in notify.c.
@ -1100,6 +1128,9 @@ struct sqlite3 {
void (*xUnlockNotify)(void **, int); /* Unlock notify callback */
sqlite3 *pNextBlocked; /* Next in list of all blocked connections */
#endif
#ifdef SQLITE_USER_AUTHENTICATION
sqlite3_userauth auth; /* User authentication information */
#endif
};
/*