sqlite3 *db, /* The database connection */
const char *zUsername, /* Username */
int nPW, /* Number of bytes in aPW[] */
- const void *aPW /* Password or credentials */
+ const char *aPW /* Password or credentials */
);
/*
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 */
+ const char *aPW /* Password or credentials */
);
/*
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 */
+ const char *aPW /* Modified password or credentials */
);
/*
*/
#ifdef SQLITE_USER_AUTHENTICATION
#include "sqliteInt.h"
+#include "sqlite3userauth.h"
/*
** Prepare an SQL statement for use by the user authentication logic.
return pStmt;
}
+/*
+** Check to see if the sqlite_user table exists in database zDb.
+*/
+static int userTableExists(sqlite3 *db, const char *zDb){
+ int rc;
+ sqlite3_mutex_enter(db->mutex);
+ sqlite3BtreeEnterAll(db);
+ rc = sqlite3FindTable(db, "sqlite_user", zDb)!=0;
+ sqlite3BtreeLeaveAll(db);
+ sqlite3_mutex_leave(db->mutex);
+ return rc;
+}
+
/*
** Check to see if database zDb has a "sqlite_user" table and if it does
** whether that table can authenticate zUser with nPw,zPw. Write one of
int rc;
*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);
- sqlite3_finalize(pStmt);
- if( rc==SQLITE_DONE ){
+ if( !userTableExists(db, "main") ){
*peAuth = UAUTH_Admin; /* No sqlite_user table. Everybody is admin. */
- return SQLITE_OK;
- }
- if( rc!=SQLITE_ROW ){
- return rc;
}
if( db->auth.zAuthUser==0 ){
*peAuth = UAUTH_Fail;
return rc;
}
+/*
+** Implementation of the sqlite_crypt(X,Y) function.
+**
+** If Y is NULL then generate a new hash for password X and return that
+** hash. If Y is not null, then generate a hash for password X using the
+** same salt as the previous hash Y and return the new hash.
+*/
+void sqlite3CryptFunc(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **argv
+){
+ const char *zIn;
+ int nIn, ii;
+ u8 *zOut;
+ char zSalt[8];
+ zIn = sqlite3_value_blob(argv[0]);
+ nIn = sqlite3_value_bytes(argv[0]);
+ if( sqlite3_value_type(argv[1])==SQLITE_BLOB
+ && sqlite3_value_bytes(argv[1])==nIn+sizeof(zSalt)
+ ){
+ memcpy(zSalt, sqlite3_value_blob(argv[1]), sizeof(zSalt));
+ }else{
+ sqlite3_randomness(sizeof(zSalt), zSalt);
+ }
+ zOut = sqlite3_malloc( nIn+sizeof(zSalt) );
+ if( zOut==0 ){
+ sqlite3_result_error_nomem(context);
+ }else{
+ memcpy(zOut, zSalt, sizeof(zSalt));
+ for(ii=0; ii<nIn; ii++){
+ zOut[ii+sizeof(zSalt)] = zIn[ii]^zSalt[ii&0x7];
+ }
+ sqlite3_result_blob(context, zOut, nIn+sizeof(zSalt), sqlite3_free);
+ }
+}
/*
** If a database contains the SQLITE_USER table, then the
db->auth.nAuthPW = nPW;
rc = sqlite3UserAuthCheckLogin(db, "main", &authLevel);
db->auth.authLevel = authLevel;
+ sqlite3ExpirePreparedStatements(db);
if( rc ){
return rc; /* OOM error, I/O error, etc. */
}
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 */
+ const char *aPW /* Password or credentials */
){
- if( db->auth.authLevel<UAUTH_Admin ) return SQLITE_ERROR;
+ sqlite3_stmt *pStmt;
+ int rc;
+ if( db->auth.authLevel<UAUTH_Admin ) return SQLITE_AUTH;
+ if( !userTableExists(db, "main") ){
+ if( !isAdmin ) return SQLITE_AUTH;
+ pStmt = sqlite3UserAuthPrepare(db,
+ "CREATE TABLE sqlite_user(\n"
+ " uname TEXT PRIMARY KEY,\n"
+ " isAdmin BOOLEAN,\n"
+ " pw BLOB\n"
+ ") WITHOUT ROWID;");
+ if( pStmt==0 ) return SQLITE_NOMEM;
+ sqlite3_step(pStmt);
+ rc = sqlite3_finalize(pStmt);
+ if( rc ) return rc;
+ }
+ pStmt = sqlite3UserAuthPrepare(db,
+ "INSERT INTO sqlite_user(uname,isAdmin,sqlite_crypt(pw,NULL))"
+ " VALUES(%Q,%d,?1)",
+ zUsername, isAdmin!=0);
+ if( pStmt==0 ) return SQLITE_NOMEM;
+ sqlite3_bind_blob(pStmt, 1, aPW, nPW, SQLITE_STATIC);
+ sqlite3_step(pStmt);
+ rc = sqlite3_finalize(pStmt);
+ if( rc ) return rc;
+ if( db->auth.zAuthUser==0 ){
+ assert( isAdmin!=0 );
+ sqlite3_user_authenticate(db, zUsername, nPW, aPW);
+ }
return SQLITE_OK;
}
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 */
+ const char *aPW /* Modified password or credentials */
){
- if( db->auth.authLevel<UAUTH_User ) return SQLITE_ERROR;
+ if( db->auth.authLevel<UAUTH_User ) return SQLITE_AUTH;
if( strcmp(db->auth.zAuthUser, zUsername)!=0
- && db->auth.authLevel<UAUTH_Admin ) return SQLITE_ERROR;
+ && db->auth.authLevel<UAUTH_Admin ) return SQLITE_AUTH;
return SQLITE_OK;
}
sqlite3 *db, /* Database connection */
const char *zUsername /* Username to remove */
){
- if( db->auth.authLevel<UAUTH_Admin ) return SQLITE_ERROR;
+ if( db->auth.authLevel<UAUTH_Admin ) return SQLITE_AUTH;
+ if( strcmp(db->auth.zAuthUser, zUsername)==0 ) return SQLITE_AUTH;
return SQLITE_OK;
}
#
TCCX = $(TCC) $(OPTS) -I. -I$(TOP)/src -I$(TOP)
TCCX += -I$(TOP)/ext/rtree -I$(TOP)/ext/icu -I$(TOP)/ext/fts3
-TCCX += -I$(TOP)/ext/async
+TCCX += -I$(TOP)/ext/async -I$(TOP)/ext/userauth
# Object files for the SQLite library.
#
$(TOP)/ext/rtree/rtree.c
SRC += \
$(TOP)/ext/userauth/userauth.c \
- $(TOP)/ext/userauth/userauth.h
+ $(TOP)/ext/userauth/sqlite3userauth.h
# Generated source code files
#
EXTHDR += \
$(TOP)/ext/icu/sqliteicu.h
EXTHDR += \
- $(TOP)/ext/userauth/userauth.h
+ $(TOP)/ext/userauth/sqlite3userauth.h
# This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments.
-C Further\sideas\son\suser\sauthentication.\s\sNot\syet\sworking\scode.
-D 2014-09-10T17:34:28.937
+C Add\sthe\s".user"\sshell\scommand\sand\simplement\sthe\ssqlite3_user_add()\nroutine.\s\sIncremental\scheck-in.\s\sThe\scode\scompiles\sbut\sdoes\snot\swork.
+D 2014-09-10T19:01:14.206
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in cf57f673d77606ab0f2d9627ca52a9ba1464146a
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F ext/rtree/sqlite3rtree.h 83349d519fe5f518b3ea025d18dd1fe51b1684bd
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
+F ext/userauth/sqlite3userauth.h 6e15b0006e7b07b7b008c9f9297b3781a7514337 w ext/userauth/userauth.h
F ext/userauth/user-auth.txt f471c5a363ab0682b109d85982ea857f9a144ccc
-F ext/userauth/userauth.c 0d24bcd4a18b354797b9cc6f8e4ba152d385cebe
-F ext/userauth/userauth.h efbfb68ff083749ad63b12dcb5877b936c3458d6
+F ext/userauth/userauth.c 5a3f8a7ac79eb1315c7e0313ff87d8c30e33d837
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
-F main.mk ac53fd5d61941c0ff1f05e710999b64ffd03f069
+F main.mk bbc8b6000ed143a1a8d31d3b4995c359a3188fa1
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
F mkopcodeh.awk c6b3fa301db6ef7ac916b14c60868aeaec1337b5
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F src/expr.c 441a7e24e2f7bea9475778fa8acce9e8a69ca8f0
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c da985ae673efef2c712caef825a5d2edb087ead7
-F src/func.c 0517037766e18eff7dce298e6b3a8e6311df75ec
+F src/func.c 1b7ac915eb83255eba90906cc2e317b1f29ae5c9
F src/global.c 5110fa12e09729b84eee0191c984ec4008e21937
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
F src/pcache.h 9b559127b83f84ff76d735c8262f04853be0c59a
F src/pcache1.c dab8ab930d4a73b99768d881185994f34b80ecaa
F src/pragma.c 3b7b1a5e90804006f44c65464c7032ee6a1d24e3
-F src/prepare.c 51ca716a2f73364d8f57c69c89423a0831d17572
+F src/prepare.c 8c2f992a3b3949ab0bf9d4862f7a271f0af0bd5b
F src/printf.c e74925089a85e3c9f0e315595f41c139d3d118c2
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
F src/resolve.c 0d1621e45fffe4b4396477cf46e41a84b0145ffb
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
F src/select.c b4457526cee73c0b69fad42f799f619b1d5a8a8a
-F src/shell.c 713cef4d73c05fc8e12f4960072329d767a05d50
-F src/sqlite.h.in 64a77f2822f1325b12050972003184f99b655a0f
+F src/shell.c 4dac2ec625fb15a51b06ab998e7cec8c1e6a40eb
+F src/sqlite.h.in 577876beef2264a0b031c0d744c81855983088f9
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h 1f40357fb9b12a80c5a3b2b109fd249b009213d4
-F src/sqliteInt.h 10a1f056b6b40449a81cf5d708bc0d9fac053c53
+F src/sqliteInt.h fdc23ef0c5475888d0e532204a7451507ce17206
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
F src/table.c 4e28a53e66bad8d014a510ef0205f5497c712b08
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 8440f093bac19a41d44ee352744354eab897fe4e
-R 6f268f8f48a352ef36f94cb71204780d
+P c8171ecd0d6f097c9e95d5f6643bae8d67f44750
+R f252935e505dbc9ddcbfc78d0487cc51
U drh
-Z 6484e1728dcc8ed1c2a7dbcf5e6f2393
+Z 5adba3159d6bf335715850631d1526a9
-c8171ecd0d6f097c9e95d5f6643bae8d67f44750
\ No newline at end of file
+a0455f9deb603bf91684158d911269622720fc1a
\ No newline at end of file
FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
FUNCTION(sqlite_log, 2, 0, 0, errlogFunc ),
+#if SQLITE_USER_AUTHENTICATION
+ FUNCTION(sqlite_crypt, 2, 0, 0, sqlite3CryptFunc ),
+#endif
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
FUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ),
FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
db->auth.authLevel = authLevel;
}
if( db->auth.authLevel<UAUTH_User ){
- sqlite3ErrorWithMsg(db, SQLITE_ERROR, "user not authenticated");
+ sqlite3ErrorWithMsg(db, SQLITE_AUTH_USER, "user not authenticated");
sqlite3_mutex_leave(db->mutex);
return SQLITE_ERROR;
}
#include <stdio.h>
#include <assert.h>
#include "sqlite3.h"
+#if SQLITE_USER_AUTHENTICATION
+# include "sqlite3userauth.h"
+#endif
#include <ctype.h>
#include <stdarg.h>
#endif
}else
+#if SQLITE_USER_AUTHENTICATION
+ if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
+ if( nArg<2 ){
+ fprintf(stderr, "Usage: .user SUBCOMMAND ...\n");
+ rc = 1;
+ goto meta_command_exit;
+ }
+ if( strcmp(azArg[1],"login")==0 ){
+ if( nArg!=4 ){
+ fprintf(stderr, "Usage: .user login USER PASSWORD\n");
+ rc = 1;
+ goto meta_command_exit;
+ }
+ rc = sqlite3_user_authenticate(p->db, azArg[2], (int)strlen(azArg[3]), azArg[3]);
+ if( rc ){
+ fprintf(stderr, "Authentication failed for user %s\n", azArg[2]);
+ rc = 1;
+ }
+ }else if( strcmp(azArg[1],"add")==0 ){
+ if( nArg!=5 ){
+ fprintf(stderr, "Usage: .user add USER ISADMIN PASSWORD\n");
+ rc = 1;
+ goto meta_command_exit;
+ }
+ rc = sqlite3_user_add(p->db, azArg[2], booleanValue(azArg[3]),
+ (int)strlen(azArg[4]), azArg[4]);
+ if( rc ){
+ fprintf(stderr, "User-Add failed: %d\n", rc);
+ rc = 1;
+ }
+ }else if( strcmp(azArg[1],"edit")==0 ){
+ if( nArg!=5 ){
+ fprintf(stderr, "Usage: .user edit USER ISADMIN PASSWORD\n");
+ rc = 1;
+ goto meta_command_exit;
+ }
+ rc = sqlite3_user_change(p->db, azArg[2], booleanValue(azArg[3]),
+ (int)strlen(azArg[4]), azArg[4]);
+ if( rc ){
+ fprintf(stderr, "User-Edit failed: %d\n", rc);
+ rc = 1;
+ }
+ }else if( strcmp(azArg[1],"delete")==0 ){
+ if( nArg!=3 ){
+ fprintf(stderr, "Usage: .user delete USER\n");
+ rc = 1;
+ goto meta_command_exit;
+ }
+ rc = sqlite3_user_delete(p->db, azArg[2]);
+ if( rc ){
+ fprintf(stderr, "User-Delete failed: %d\n", rc);
+ rc = 1;
+ }
+ }else{
+ fprintf(stderr, "Usage: .user login|add|edit|delete ...\n");
+ rc = 1;
+ goto meta_command_exit;
+ }
+ }else
+#endif /* SQLITE_USER_AUTHENTICATION */
+
if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
fprintf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
sqlite3_libversion(), sqlite3_sourceid());
#define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8))
#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
#define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8))
+#define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8))
/*
** CAPI3REF: Flags For File Open Operations
/* Functions used only by user authorization logic */
int sqlite3UserAuthTable(const char*);
int sqlite3UserAuthCheckLogin(sqlite3*,const char*,u8*);
+void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**);
+
#endif /* SQLITE_USER_AUTHENTICATION */