mirror of https://github.com/sqlite/sqlite
Add the ".user" shell command and implement the sqlite3_user_add()
routine. Incremental check-in. The code compiles but does not work. FossilOrigin-Name: a0455f9deb603bf91684158d911269622720fc1a
This commit is contained in:
parent
e933b83f02
commit
f442e33e3a
|
@ -37,7 +37,7 @@ 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 *aPW /* Password or credentials */
|
||||
);
|
||||
|
||||
/*
|
||||
|
@ -55,7 +55,7 @@ int sqlite3_user_add(
|
|||
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 */
|
||||
);
|
||||
|
||||
/*
|
||||
|
@ -70,7 +70,7 @@ int sqlite3_user_change(
|
|||
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 */
|
||||
);
|
||||
|
||||
/*
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
#ifdef SQLITE_USER_AUTHENTICATION
|
||||
#include "sqliteInt.h"
|
||||
#include "sqlite3userauth.h"
|
||||
|
||||
/*
|
||||
** Prepare an SQL statement for use by the user authentication logic.
|
||||
|
@ -52,6 +53,19 @@ static sqlite3_stmt *sqlite3UserAuthPrepare(
|
|||
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
|
||||
|
@ -67,20 +81,8 @@ static int userAuthCheckLogin(
|
|||
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;
|
||||
|
@ -115,6 +117,42 @@ int sqlite3UserAuthCheckLogin(
|
|||
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
|
||||
|
@ -148,6 +186,7 @@ int sqlite3_user_authenticate(
|
|||
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. */
|
||||
}
|
||||
|
@ -172,9 +211,37 @@ int sqlite3_user_add(
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -190,11 +257,11 @@ int sqlite3_user_change(
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -209,7 +276,8 @@ int sqlite3_user_delete(
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
6
main.mk
6
main.mk
|
@ -46,7 +46,7 @@
|
|||
#
|
||||
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.
|
||||
#
|
||||
|
@ -216,7 +216,7 @@ SRC += \
|
|||
$(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
|
||||
#
|
||||
|
@ -380,7 +380,7 @@ EXTHDR += \
|
|||
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.
|
||||
|
|
26
manifest
26
manifest
|
@ -1,5 +1,5 @@
|
|||
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
|
||||
|
@ -144,13 +144,13 @@ 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/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
|
||||
|
@ -183,7 +183,7 @@ F src/delete.c fae81cc2eb14b75267d4f47d3cfc9ae02aae726f
|
|||
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
|
||||
|
@ -221,17 +221,17 @@ F src/pcache.c 2048affdb09a04478b5fc6e64cb1083078d369be
|
|||
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
|
||||
|
@ -1196,7 +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 8440f093bac19a41d44ee352744354eab897fe4e
|
||||
R 6f268f8f48a352ef36f94cb71204780d
|
||||
P c8171ecd0d6f097c9e95d5f6643bae8d67f44750
|
||||
R f252935e505dbc9ddcbfc78d0487cc51
|
||||
U drh
|
||||
Z 6484e1728dcc8ed1c2a7dbcf5e6f2393
|
||||
Z 5adba3159d6bf335715850631d1526a9
|
||||
|
|
|
@ -1 +1 @@
|
|||
c8171ecd0d6f097c9e95d5f6643bae8d67f44750
|
||||
a0455f9deb603bf91684158d911269622720fc1a
|
|
@ -1695,6 +1695,9 @@ void sqlite3RegisterGlobalFunctions(void){
|
|||
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 ),
|
||||
|
|
|
@ -722,7 +722,7 @@ static int sqlite3LockAndPrepare(
|
|||
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;
|
||||
}
|
||||
|
|
64
src/shell.c
64
src/shell.c
|
@ -33,6 +33,9 @@
|
|||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "sqlite3.h"
|
||||
#if SQLITE_USER_AUTHENTICATION
|
||||
# include "sqlite3userauth.h"
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
|
@ -3435,6 +3438,67 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||
#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());
|
||||
|
|
|
@ -492,6 +492,7 @@ int sqlite3_exec(
|
|||
#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
|
||||
|
|
|
@ -1010,6 +1010,8 @@ struct sqlite3_userauth {
|
|||
/* 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 */
|
||||
|
||||
|
|
Loading…
Reference in New Issue