Bind sqlite3_set_authorizer() to JNI.
FossilOrigin-Name: e0fa03135942cd2fe732a74510d380ba78ab230c452168e638f32b4aee04b3f7
This commit is contained in:
@@ -412,6 +412,7 @@ struct PerDbStateJni {
|
||||
JniHookState rollbackHook;
|
||||
JniHookState trace;
|
||||
JniHookState updateHook;
|
||||
JniHookState authHook;
|
||||
#ifdef SQLITE_ENABLE_FTS5
|
||||
jobject jFtsApi /* global ref to s3jni_fts5_api_from_db() */;
|
||||
#endif
|
||||
@@ -610,6 +611,7 @@ static void PerDbStateJni_set_aside(PerDbStateJni * const s){
|
||||
UNHOOK(commitHook, 0);
|
||||
UNHOOK(rollbackHook, 0);
|
||||
UNHOOK(updateHook, 0);
|
||||
UNHOOK(authHook, 0);
|
||||
UNHOOK(collation, 1);
|
||||
UNHOOK(collationNeeded, 1);
|
||||
UNHOOK(busyHandler, 1);
|
||||
@@ -2388,6 +2390,71 @@ JDECL(jobject,1rollback_1hook)(JENV_JSELF,jobject jDb, jobject jHook){
|
||||
return s3jni_commit_rollback_hook(0, env, jDb, jHook);
|
||||
}
|
||||
|
||||
/* sqlite3_set_authorizer() callback proxy. */
|
||||
static int s3jni_xAuth(void* pState, int op,const char*z0, const char*z1,
|
||||
const char*z2,const char*z3){
|
||||
PerDbStateJni * const ps = pState;
|
||||
JNIEnv * const env = ps->env;
|
||||
jstring const s0 = z0 ? (*env)->NewStringUTF(env, z0) : 0;
|
||||
jstring const s1 = z1 ? (*env)->NewStringUTF(env, z1) : 0;
|
||||
jstring const s2 = z2 ? (*env)->NewStringUTF(env, z2) : 0;
|
||||
jstring const s3 = z3 ? (*env)->NewStringUTF(env, z3) : 0;
|
||||
JniHookState const * const pHook = &ps->authHook;
|
||||
int rc;
|
||||
|
||||
assert( pHook->jObj );
|
||||
rc = (*env)->CallIntMethod(env, pHook->jObj, pHook->midCallback, (jint)op,
|
||||
s0, s1, s3, s3);
|
||||
IFTHREW{
|
||||
EXCEPTION_WARN_CALLBACK_THREW("sqlite3_set_authorizer() callback");
|
||||
EXCEPTION_CLEAR;
|
||||
}
|
||||
UNREF_L(s0);
|
||||
UNREF_L(s1);
|
||||
UNREF_L(s2);
|
||||
UNREF_L(s3);
|
||||
return rc;
|
||||
}
|
||||
|
||||
JDECL(jint,1set_1authorizer)(JENV_JSELF,jobject jDb, jobject jHook){
|
||||
PerDbStateJni * const ps = PerDbStateJni_for_db(env, jDb, 0, 0);
|
||||
JniHookState * const pHook = ps ? &ps->authHook : 0;
|
||||
|
||||
if( !ps ) return SQLITE_MISUSE;
|
||||
else if( !jHook ){
|
||||
JniHookState_unref(env, pHook, 0);
|
||||
return (jint)sqlite3_set_authorizer( ps->pDb, 0, 0 );
|
||||
}else{
|
||||
int rc = 0;
|
||||
if( pHook->jObj ){
|
||||
if( (*env)->IsSameObject(env, pHook->jObj, jHook) ){
|
||||
/* Same object - this is a no-op. */
|
||||
return 0;
|
||||
}
|
||||
JniHookState_unref(env, pHook, 0);
|
||||
}
|
||||
pHook->jObj = REF_G(jHook);
|
||||
pHook->klazz = REF_G((*env)->GetObjectClass(env, jHook));
|
||||
pHook->midCallback = (*env)->GetMethodID(env, pHook->klazz,
|
||||
"xAuth",
|
||||
"(I"
|
||||
"Ljava/lang/String;"
|
||||
"Ljava/lang/String;"
|
||||
"Ljava/lang/String;"
|
||||
"Ljava/lang/String;"
|
||||
")I");
|
||||
IFTHREW {
|
||||
JniHookState_unref(env, pHook, 0);
|
||||
return s3jni_db_error(ps->pDb, SQLITE_ERROR,
|
||||
"Error setting up Java parts of authorizer hook.");
|
||||
}
|
||||
rc = sqlite3_set_authorizer(ps->pDb, s3jni_xAuth, ps);
|
||||
if( rc ) JniHookState_unref(env, pHook, 0);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
JDECL(void,1set_1last_1insert_1rowid)(JENV_JSELF, jobject jpDb, jlong rowId){
|
||||
sqlite3_set_last_insert_rowid(PtrGet_sqlite3_context(jpDb),
|
||||
(sqlite3_int64)rowId);
|
||||
|
||||
@@ -1371,6 +1371,14 @@ JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1result_1text64
|
||||
JNIEXPORT jobject JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1rollback_1hook
|
||||
(JNIEnv *, jclass, jobject, jobject);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_SQLite3Jni
|
||||
* Method: sqlite3_set_authorizer
|
||||
* Signature: (Lorg/sqlite/jni/sqlite3;Lorg/sqlite/jni/Authorizer;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1set_1authorizer
|
||||
(JNIEnv *, jclass, jobject, jobject);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_SQLite3Jni
|
||||
* Method: sqlite3_set_last_insert_rowid
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
** 2023-08-05
|
||||
**
|
||||
** 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 is part of the JNI bindings for the sqlite3 C API.
|
||||
*/
|
||||
package org.sqlite.jni;
|
||||
|
||||
/**
|
||||
A wrapper for use with sqlite3_set_authorizer().
|
||||
*/
|
||||
public interface Authorizer {
|
||||
/**
|
||||
Must functions as described for the sqlite3_set_authorizer()
|
||||
callback, with one caveat: the string values passed here were
|
||||
initially (at the C level) encoded in standard UTF-8. If they
|
||||
contained any constructs which are not compatible with MUTF-8,
|
||||
these strings will not have the expected values. The strings
|
||||
passed through the authorizer would only be adversely affected by
|
||||
that if the database tables and columns use "highly exotic"
|
||||
names. Any names which contain no NUL bytes, nor characters
|
||||
outside of the Basic Multilingual Plane are unaffected by this
|
||||
discrepancy.
|
||||
|
||||
Must not throw.
|
||||
*/
|
||||
int xAuth(int opId, @Nullable String s1, @Nullable String s2,
|
||||
@Nullable String s3, @Nullable String s4);
|
||||
}
|
||||
@@ -103,12 +103,13 @@ public final class SQLite3Jni {
|
||||
primarily for testing of the JNI bindings and is not information
|
||||
which client-level code should use to make any informed
|
||||
decisions.
|
||||
*/
|
||||
*/
|
||||
public static synchronized native boolean uncacheJniEnv();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Maintenance reminder: please keep the functions alphabetized.
|
||||
// The SQLITE_... values. on the other hand, are grouped by category.
|
||||
// Maintenance reminder: please keep the sqlite3_.... functions
|
||||
// alphabetized. The SQLITE_... values. on the other hand, are
|
||||
// grouped by category.
|
||||
|
||||
public static int sqlite3_bind_blob(@NotNull sqlite3_stmt stmt, int ndx,
|
||||
@Nullable byte[] data){
|
||||
@@ -725,6 +726,10 @@ public final class SQLite3Jni {
|
||||
public static native RollbackHook sqlite3_rollback_hook(@NotNull sqlite3 db,
|
||||
@Nullable RollbackHook hook);
|
||||
|
||||
//! Sets or unsets (if auth is null) the current authorizer.
|
||||
public static native int sqlite3_set_authorizer(@NotNull sqlite3 db,
|
||||
@Nullable Authorizer auth);
|
||||
|
||||
public static native void sqlite3_set_last_insert_rowid(@NotNull sqlite3 db, long rowid);
|
||||
|
||||
public static native int sqlite3_sleep(int ms);
|
||||
|
||||
@@ -82,7 +82,8 @@ public class Tester1 {
|
||||
}
|
||||
if( 0==sqlChunk.length ) break;
|
||||
rc = sqlite3_prepare_v2(db, sqlChunk, stmt, oTail);
|
||||
affirm(0 == rc);
|
||||
if(throwOnError) affirm(0 == rc);
|
||||
else if( 0!=rc ) break;
|
||||
pos = oTail.getValue();
|
||||
affirm(0 != stmt.getNativePointer());
|
||||
while( SQLITE_ROW == (rc = sqlite3_step(stmt)) ){
|
||||
@@ -97,6 +98,7 @@ public class Tester1 {
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
if(SQLITE_ROW==rc || SQLITE_DONE==rc) rc = 0;
|
||||
return rc;
|
||||
}
|
||||
@@ -949,6 +951,28 @@ public class Tester1 {
|
||||
}
|
||||
}
|
||||
|
||||
private static void testAuthorizer(){
|
||||
final sqlite3 db = createNewDb();
|
||||
final ValueHolder<Integer> counter = new ValueHolder<>(0);
|
||||
final ValueHolder<Integer> authRc = new ValueHolder<>(0);
|
||||
final Authorizer auth = new Authorizer(){
|
||||
public int xAuth(int op, String s0, String s1, String s2, String s3){
|
||||
++counter.value;
|
||||
//outln("xAuth(): "+s0+" "+s1+" "+s2+" "+s3);
|
||||
return authRc.value;
|
||||
}
|
||||
};
|
||||
execSql(db, "CREATE TABLE t(a); INSERT INTO t(a) VALUES('a'),('b'),('c')");
|
||||
sqlite3_set_authorizer(db, auth);
|
||||
execSql(db, "UPDATE t SET a=1");
|
||||
affirm( 1 == counter.value );
|
||||
authRc.value = SQLITE_DENY;
|
||||
int rc = execSql(db, false, "UPDATE t SET a=2");
|
||||
affirm( SQLITE_AUTH==rc );
|
||||
// TODO: expand these tests considerably
|
||||
sqlite3_close(db);
|
||||
}
|
||||
|
||||
private static void testSleep(){
|
||||
out("Sleeping briefly... ");
|
||||
sqlite3_sleep(600);
|
||||
@@ -981,6 +1005,7 @@ public class Tester1 {
|
||||
testCommitHook();
|
||||
testRollbackHook();
|
||||
testUpdateHook();
|
||||
testAuthorizer();
|
||||
testFts5();
|
||||
//testSleep();
|
||||
if(liArgs.indexOf("-v")>0){
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
C Refactor\sthe\sper-JNIEnv\scache\sfrom\sa\sfixed-size\sstatic\sarray\sto\sa\slinked\slist\sof\sdynamically-allocated\sentries.\sUncache\sall\sper-db\sstate\s(which\sis\snecessarily\sJNIEnv-specific)\swhen\sthe\scorresponding\sJNIEnv\sis\suncached.
|
||||
D 2023-08-05T21:35:58.833
|
||||
C Bind\ssqlite3_set_authorizer()\sto\sJNI.
|
||||
D 2023-08-05T22:41:36.472
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@@ -232,8 +232,9 @@ F ext/icu/icu.c c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282
|
||||
F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
|
||||
F ext/jni/GNUmakefile bb4cd99bd8da534215cb6d278f05a626283eb5d2e8aebdb4d35e548637d35a9a
|
||||
F ext/jni/README.md 6ff7e1f4100dee980434a6ee37a199b653bceec62e233a6e2ccde6e7ae0c58bf
|
||||
F ext/jni/src/c/sqlite3-jni.c a894cb1b6a7479d376d98f7df0e29a713d2b6b6cbc0d4543505b90eb38593592
|
||||
F ext/jni/src/c/sqlite3-jni.h cd9b6367a260f55a14833861ceb1d87cb729c5414ba5d26fbb8854b0f22c7249
|
||||
F ext/jni/src/c/sqlite3-jni.c b81dcf92a1fbd7ada98dbc0f526b02e9e97e2be84cb331092e933c7d8feeafe2
|
||||
F ext/jni/src/c/sqlite3-jni.h 1db6075134d7efc71f634e4a212e41d0178346e68c7c615f220d753e4bd23382
|
||||
F ext/jni/src/org/sqlite/jni/Authorizer.java 189e7fa2155466ded5a52eed1ccb46581b5b45d70fcef49f538c0b93ea88e337
|
||||
F ext/jni/src/org/sqlite/jni/BusyHandler.java 1b1d3e5c86cd796a0580c81b6af6550ad943baa25e47ada0dcca3aff3ebe978c
|
||||
F ext/jni/src/org/sqlite/jni/Collation.java 8dffbb00938007ad0967b2ab424d3c908413af1bbd3d212b9c9899910f1218d1
|
||||
F ext/jni/src/org/sqlite/jni/CollationNeeded.java ebc7cd96d46a70daa76016a308e80f70a3f21d3282787c8d139aa840fdcb1bd7
|
||||
@@ -249,8 +250,8 @@ F ext/jni/src/org/sqlite/jni/OutputPointer.java 013f2b5fe569d0585a695f5cfa605a3b
|
||||
F ext/jni/src/org/sqlite/jni/ProgressHandler.java 5979450e996416d28543f1d42634d308439565a99332a8bd84e424af667116cc
|
||||
F ext/jni/src/org/sqlite/jni/RollbackHook.java b04c8abcc6ade44a8a57129e33765793f69df0ba909e49ba18d73f4268d92564
|
||||
F ext/jni/src/org/sqlite/jni/SQLFunction.java 09ce81c1c637e31c3a830d4c859cce95d65f5e02ff45f8bd1985b3479381bc46
|
||||
F ext/jni/src/org/sqlite/jni/SQLite3Jni.java f8fec24eea4ff9a62467648f377391506883eff4bedfc50d69d8cb3dc78d1ab9
|
||||
F ext/jni/src/org/sqlite/jni/Tester1.java 868b5ea60b788a43f8b15c1b642015341fed8856abb1bb74e2eb4845ade50a4e
|
||||
F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 850012ad011d5d60a8aaaf9b8db562c60277988982793135814892e82ac77b97
|
||||
F ext/jni/src/org/sqlite/jni/Tester1.java 214985f8a700ac56a174809c04196215fef5d7bb8b86e095d9d0abf436349ffb
|
||||
F ext/jni/src/org/sqlite/jni/TesterFts5.java cf2d687baafffdeba219b77cf611fd47a0556248820ea794ae3e8259bfbdc5ee
|
||||
F ext/jni/src/org/sqlite/jni/Tracer.java a5cece9f947b0af27669b8baec300b6dd7ff859c3e6a6e4a1bd8b50f9714775d
|
||||
F ext/jni/src/org/sqlite/jni/UpdateHook.java e58645a1727f8a9bbe72dc072ec5b40d9f9362cb0aa24acfe93f49ff56a9016d
|
||||
@@ -2081,8 +2082,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 7468f8761bece58f7ced3d112bbe2fb454432d9c54c9b96cedb5a15bc2926d0f
|
||||
R c28f39c95821b6209d9e0ded55b1b7ca
|
||||
P 9dd8b78419e19e88bc3fbff9bf200390b146b2461af2bb6b93d8467036619e33
|
||||
R bf3d1c30171f035a2002cb68468caf2a
|
||||
U stephan
|
||||
Z 6d5410b49d781e986fb3ebb97da80215
|
||||
Z a910bd2897a92249409319f7eba80e4a
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
9dd8b78419e19e88bc3fbff9bf200390b146b2461af2bb6b93d8467036619e33
|
||||
e0fa03135942cd2fe732a74510d380ba78ab230c452168e638f32b4aee04b3f7
|
||||
Reference in New Issue
Block a user