Bind sqlite3_set_authorizer() to JNI.

FossilOrigin-Name: e0fa03135942cd2fe732a74510d380ba78ab230c452168e638f32b4aee04b3f7
This commit is contained in:
stephan
2023-08-05 22:41:36 +00:00
parent 28e95830ad
commit 153288dc89
7 changed files with 156 additions and 14 deletions
+67
View File
@@ -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);
+8
View File
@@ -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);
}
+8 -3
View File
@@ -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);
+26 -1
View File
@@ -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){
+10 -9
View File
@@ -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
View File
@@ -1 +1 @@
9dd8b78419e19e88bc3fbff9bf200390b146b2461af2bb6b93d8467036619e33
e0fa03135942cd2fe732a74510d380ba78ab230c452168e638f32b4aee04b3f7