Fix the sqlite3_user_change() interface so that it does allow a

non-admin user to change their own password.

FossilOrigin-Name: 52d440c7e1b07fc03f14ed5fa4cc4c89a75cd430
This commit is contained in:
drh
2014-09-11 14:40:27 +00:00
parent b2445d5ee8
commit 570f187f78
5 changed files with 82 additions and 31 deletions
+11 -12
View File
@@ -44,12 +44,11 @@ By default a database does not require authentication.
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.
@@ -133,12 +132,12 @@ new table:
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
+20 -10
View File
@@ -268,7 +268,11 @@ int sqlite3_user_change(
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;
}
@@ -277,21 +281,27 @@ int sqlite3_user_change(
/* 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;
}
/*