veyron/runtimes/google/security/jni: Hookup Java security into main ipc flow.
Change-Id: I318f25c16dd6bd3a9433a18b7ad551b626ab62a9
diff --git a/runtimes/google/ipc/jni/dispatcher.go b/runtimes/google/ipc/jni/dispatcher.go
index 425a6fb..2e5174e 100644
--- a/runtimes/google/ipc/jni/dispatcher.go
+++ b/runtimes/google/ipc/jni/dispatcher.go
@@ -7,6 +7,7 @@
"runtime"
"veyron/runtimes/google/jni/util"
+ isecurity "veyron/runtimes/google/security/jni"
"veyron2/ipc"
"veyron2/security"
)
@@ -15,9 +16,15 @@
// #include "jni_wrapper.h"
// // CGO doesn't support variadic functions so we have to hard-code these
// // functions to match the invoking code. Ugh!
-// static jobject CallLookupMethod(JNIEnv* env, jobject obj, jmethodID id, jstring str) {
+// static jobject CallDispatcherLookupMethod(JNIEnv* env, jobject obj, jmethodID id, jstring str) {
// return (*env)->CallObjectMethod(env, obj, id, str);
// }
+// static jobject CallDispatcherGetObjectMethod(JNIEnv* env, jobject obj, jmethodID id) {
+// return (*env)->CallObjectMethod(env, obj, id);
+// }
+// static jobject CallDispatcherGetAuthorizerMethod(JNIEnv* env, jobject obj, jmethodID id) {
+// return (*env)->CallObjectMethod(env, obj, id);
+// }
import "C"
func newDispatcher(env *C.JNIEnv, jDispatcher C.jobject) (*dispatcher, error) {
@@ -58,21 +65,36 @@
defer C.DetachCurrentThread(d.jVM)
// Call Java dispatcher's lookup() method.
- lid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, d.jDispatcher), "lookup", fmt.Sprintf("(%s)%s", util.StringSign, util.ObjectSign)))
- jObj := C.CallLookupMethod(env, d.jDispatcher, lid, C.jstring(util.JStringPtr(env, suffix)))
+ serviceObjectWithAuthorizerSign := "Lcom/veyron2/ipc/ServiceObjectWithAuthorizer;"
+ lid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, d.jDispatcher), "lookup", fmt.Sprintf("(%s)%s", util.StringSign, serviceObjectWithAuthorizerSign)))
+ jServiceObjectWithAuthorizer := C.CallDispatcherLookupMethod(env, d.jDispatcher, lid, C.jstring(util.JStringPtr(env, suffix)))
if err := util.JExceptionMsg(env); err != nil {
return nil, nil, fmt.Errorf("error invoking Java dispatcher's lookup() method: %v", err)
}
- if jObj == nil {
- // Lookup returned null object, which means that the dispatcher isn't
- // handling the object - this is not an error.
+ if jServiceObjectWithAuthorizer == nil {
+ // Lookup returned null, which means that the dispatcher isn't handling the object -
+ // this is not an error.
return nil, nil, nil
}
+
+ // Extract the Java service object and Authorizer.
+ oid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, jServiceObjectWithAuthorizer), "getServiceObject", fmt.Sprintf("()%s", util.ObjectSign)))
+ jObj := C.CallDispatcherGetObjectMethod(env, jServiceObjectWithAuthorizer, oid)
+ if jObj == nil {
+ return nil, nil, fmt.Errorf("null service object returned by Java's ServiceObjectWithAuthorizer")
+ }
+ authSign := "Lcom/veyron2/security/Authorizer;"
+ aid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, jServiceObjectWithAuthorizer), "getAuthorizer", fmt.Sprintf("()%s", authSign)))
+ jAuth := C.CallDispatcherGetAuthorizerMethod(env, jServiceObjectWithAuthorizer, aid)
+
+ // Create Go Invoker and Authorizer.
i, err := newInvoker(env, d.jVM, jObj)
if err != nil {
return nil, nil, err
}
- // TODO(spetrovic): create JNI version of authorizer that invokes Java's
- // authorizer methods.
- return i, security.NewACLAuthorizer(security.ACL{security.AllPrincipals: security.LabelSet(security.AdminLabel)}), nil
+ var a security.Authorizer
+ if jAuth != nil {
+ a = isecurity.NewAuthorizer(env, jAuth)
+ }
+ return i, a, nil
}
diff --git a/runtimes/google/ipc/jni/invoker.go b/runtimes/google/ipc/jni/invoker.go
index 0cda728..90368a0 100644
--- a/runtimes/google/ipc/jni/invoker.go
+++ b/runtimes/google/ipc/jni/invoker.go
@@ -20,30 +20,33 @@
//
// // CGO doesn't support variadic functions so we have to hard-code these
// // functions to match the invoking code. Ugh!
-// static jobject CallInvokeMethod(JNIEnv* env, jobject obj, jmethodID id, jstring method, jobject call, jobjectArray inArgs) {
-// return (*env)->CallObjectMethod(env, obj, id, method, call, inArgs);
+// static jobject CallInvokerInvokeMethod(JNIEnv* env, jobject obj, jmethodID id, jstring method, jobject call, jobjectArray inArgs) {
+// return (*env)->CallObjectMethod(env, obj, id, method, call, inArgs);
// }
-// static jobject CallNewInvokerObject(JNIEnv* env, jclass class, jmethodID id, jobject obj) {
-// return (*env)->NewObject(env, class, id, obj);
+// static jobject CallInvokerNewInvokerObject(JNIEnv* env, jclass class, jmethodID id, jobject obj) {
+// return (*env)->NewObject(env, class, id, obj);
// }
-// static jobject CallGetInterfacePath(JNIEnv* env, jobject obj, jmethodID id) {
-// return (*env)->CallObjectMethod(env, obj, id);
+// static jobject CallInvokerGetInterfacePath(JNIEnv* env, jobject obj, jmethodID id) {
+// return (*env)->CallObjectMethod(env, obj, id);
// }
-// static jobject CallNewServerCallObject(JNIEnv* env, jclass class, jmethodID id, jlong ref) {
-// return (*env)->NewObject(env, class, id, ref);
+// static jobject CallInvokerGetSecurityLabelMethod(JNIEnv* env, jobject obj, jmethodID id, jstring method) {
+// return (*env)->CallObjectMethod(env, obj, id, method);
+// }
+// static jobject CallInvokerNewServerCallObject(JNIEnv* env, jclass class, jmethodID id, jlong ref) {
+// return (*env)->NewObject(env, class, id, ref);
// }
import "C"
func newInvoker(env *C.JNIEnv, jVM *C.JavaVM, jObj C.jobject) (*invoker, error) {
// Create a new Java VDLInvoker object.
cid := C.jmethodID(util.JMethodIDPtrOrDie(env, jVDLInvokerClass, "<init>", fmt.Sprintf("(%s)%s", util.ObjectSign, util.VoidSign)))
- jInvoker := C.CallNewInvokerObject(env, jVDLInvokerClass, cid, jObj)
+ jInvoker := C.CallInvokerNewInvokerObject(env, jVDLInvokerClass, cid, jObj)
if err := util.JExceptionMsg(env); err != nil {
return nil, fmt.Errorf("error creating Java VDLInvoker object: %v", err)
}
// Fetch the argGetter for the object.
pid := C.jmethodID(util.JMethodIDPtrOrDie(env, jVDLInvokerClass, "getImplementedServices", fmt.Sprintf("()%s", util.ArraySign(util.StringSign))))
- jPathArray := C.jobjectArray(C.CallGetInterfacePath(env, jInvoker, pid))
+ jPathArray := C.jobjectArray(C.CallInvokerGetInterfacePath(env, jInvoker, pid))
paths := util.GoStringArray(env, jPathArray)
getter, err := newArgGetter(paths)
if err != nil {
@@ -79,14 +82,28 @@
// arguments into vom.Value objects, which we shall then de-serialize into
// Java objects (see Invoke comments below). This approach is blocked on
// pending VOM encoder/decoder changes as well as Java (de)serializer.
+ var env *C.JNIEnv
+ C.AttachCurrentThread(i.jVM, &env, nil)
+ defer C.DetachCurrentThread(i.jVM)
+
mArgs := i.argGetter.FindMethod(method, numArgs)
if mArgs == nil {
err = fmt.Errorf("couldn't find VDL method %q with %d args", method, numArgs)
return
}
argptrs = mArgs.InPtrs()
- // TODO(spetrovic): ask the Java object to give us the label.
- label = security.AdminLabel
+
+ // Get the security label.
+ labelSign := "Lcom/veyron2/security/Label;"
+ mid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, i.jInvoker), "getSecurityLabel", fmt.Sprintf("(%s)%s", util.StringSign, labelSign)))
+ if err = util.JExceptionMsg(env); err != nil {
+ return
+ }
+ jLabel := C.CallInvokerGetSecurityLabelMethod(env, i.jInvoker, mid, C.jstring(util.JStringPtr(env, util.CamelCase(method))))
+ if err = util.JExceptionMsg(env); err != nil {
+ return
+ }
+ label = security.Label(util.JIntField(env, jLabel, "value"))
return
}
@@ -109,7 +126,7 @@
}
sCall := newServerCall(call, mArgs)
cid := C.jmethodID(util.JMethodIDPtrOrDie(env, jServerCallClass, "<init>", fmt.Sprintf("(%s)%s", util.LongSign, util.VoidSign)))
- jServerCall := C.CallNewServerCallObject(env, jServerCallClass, cid, C.jlong(util.PtrValue(sCall)))
+ jServerCall := C.CallInvokerNewServerCallObject(env, jServerCallClass, cid, C.jlong(util.PtrValue(sCall)))
util.GoRef(sCall) // unref-ed when jServerCall is garbage-collected
// Translate input args to JSON.
@@ -121,7 +138,7 @@
const callSign = "Lcom/veyron2/ipc/ServerCall;"
const replySign = "Lcom/veyron/runtimes/google/VDLInvoker$InvokeReply;"
mid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, i.jInvoker), "invoke", fmt.Sprintf("(%s%s[%s)%s", util.StringSign, callSign, util.StringSign, replySign)))
- jReply := C.CallInvokeMethod(env, i.jInvoker, mid, C.jstring(util.JStringPtr(env, util.CamelCase(method))), jServerCall, jArgs)
+ jReply := C.CallInvokerInvokeMethod(env, i.jInvoker, mid, C.jstring(util.JStringPtr(env, util.CamelCase(method))), jServerCall, jArgs)
if err := util.JExceptionMsg(env); err != nil {
return nil, fmt.Errorf("error invoking Java method %q: %v", method, err)
}
diff --git a/runtimes/google/ipc/jni/jni.go b/runtimes/google/ipc/jni/jni.go
index 36c5b90..e8bcb8e 100644
--- a/runtimes/google/ipc/jni/jni.go
+++ b/runtimes/google/ipc/jni/jni.go
@@ -159,8 +159,8 @@
}
}
-//export Java_com_veyron_runtimes_google_jni_Runtime_00024Server_nativeFinalize
-func Java_com_veyron_runtimes_google_jni_Runtime_00024Server_nativeFinalize(env *C.JNIEnv, server C.jobject, goServerPtr C.jlong) {
+//export Java_com_veyron_runtimes_google_Runtime_00024Server_nativeFinalize
+func Java_com_veyron_runtimes_google_Runtime_00024Server_nativeFinalize(env *C.JNIEnv, server C.jobject, goServerPtr C.jlong) {
util.GoUnref((*ipc.Server)(util.Ptr(goServerPtr)))
}
diff --git a/runtimes/google/jni/util/util.go b/runtimes/google/jni/util/util.go
index 767d62c..ce19623 100644
--- a/runtimes/google/jni/util/util.go
+++ b/runtimes/google/jni/util/util.go
@@ -43,6 +43,8 @@
StringSign = "Ljava/lang/String;"
// ObjectSign denotes a signature of a Java Object type.
ObjectSign = "Ljava/lang/Object;"
+ // ClassSign denotes a signature of a Java Class type.
+ ClassSign = "Ljava/lang/Class;"
)
// ArraySign returns the array signature, given the underlying array type.
diff --git a/runtimes/google/security/jni/authorizer.go b/runtimes/google/security/jni/authorizer.go
index e1bf576..7536894 100644
--- a/runtimes/google/security/jni/authorizer.go
+++ b/runtimes/google/security/jni/authorizer.go
@@ -70,10 +70,6 @@
// Run Java Authorizer.
contextSign := "Lcom/veyron2/security/Context;"
mid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, a.jAuth), "authorize", fmt.Sprintf("(%s)%s", contextSign, util.VoidSign)))
- if mid == nil {
- return fmt.Errorf("Srdjan's error")
- }
- return nil
C.CallAuthorizerAuthorizeMethod(env, a.jAuth, mid, jContext)
if err := util.JExceptionMsg(env); err != nil {
return err
diff --git a/runtimes/google/security/jni/caveat.go b/runtimes/google/security/jni/caveat.go
index b09885a..0b44f75 100644
--- a/runtimes/google/security/jni/caveat.go
+++ b/runtimes/google/security/jni/caveat.go
@@ -59,7 +59,7 @@
defer C.DetachCurrentThread(c.jVM)
util.GoRef(&context) // un-refed when the Java Context object is finalized.
cid := C.jmethodID(util.JMethodIDPtrOrDie(env, jContextImplClass, "<init>", fmt.Sprintf("(%s)%s", util.LongSign, util.VoidSign)))
- jContext := C.CallCaveatNewContextObject(env, jContextClass, cid, C.jlong(util.PtrValue(&context)))
+ jContext := C.CallCaveatNewContextObject(env, jContextImplClass, cid, C.jlong(util.PtrValue(&context)))
contextSign := "Lcom/veyron2/security/Context;"
mid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, c.jCaveat), "validate", fmt.Sprintf("(%s)%s", contextSign, util.VoidSign)))
C.CallCaveatValidateMethod(env, c.jCaveat, mid, jContext)
diff --git a/runtimes/google/security/jni/context.go b/runtimes/google/security/jni/context.go
index 533f2d9..8b63eec 100644
--- a/runtimes/google/security/jni/context.go
+++ b/runtimes/google/security/jni/context.go
@@ -26,6 +26,9 @@
// static jobject CallContextPublicIDMethod(JNIEnv* env, jobject obj, jmethodID id) {
// return (*env)->CallObjectMethod(env, obj, id);
// }
+// static jobject CallContextLabelMethod(JNIEnv* env, jobject obj, jmethodID id) {
+// return (*env)->CallObjectMethod(env, obj, id);
+// }
import "C"
func newContext(env *C.JNIEnv, jContext C.jobject) *context {
@@ -86,8 +89,10 @@
var env *C.JNIEnv
C.AttachCurrentThread(c.jVM, &env, nil)
defer C.DetachCurrentThread(c.jVM)
- mid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, c.jContext), "label", fmt.Sprintf("()%s", util.IntSign)))
- return security.Label(C.CallContextIntMethod(env, c.jContext, mid))
+ labelSign := "Lcom/veyron2/security/Label;"
+ mid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, c.jContext), "label", fmt.Sprintf("()%s", labelSign)))
+ jLabel := C.CallContextLabelMethod(env, c.jContext, mid)
+ return security.Label(util.JIntField(env, jLabel, "value"))
}
func (c *context) CaveatDischarges() security.CaveatDischargeMap {
diff --git a/runtimes/google/security/jni/jni.go b/runtimes/google/security/jni/jni.go
index 2e50950..458d414 100644
--- a/runtimes/google/security/jni/jni.go
+++ b/runtimes/google/security/jni/jni.go
@@ -5,6 +5,7 @@
import (
"encoding/asn1"
"fmt"
+ "reflect"
"time"
"unsafe"
@@ -38,8 +39,6 @@
jCaveatImplClass C.jclass
// Global reference for com.veyron.runtimes.google.security.Context class.
jContextImplClass C.jclass
- // Global reference for com.veyron2.security.Context class.
- jContextClass C.jclass
// Global reference for com.veyron2.security.Caveat class.
jCaveatClass C.jclass
// Global reference for com.veyron2.security.ServiceCaveat class.
@@ -59,7 +58,6 @@
jPublicIDImplClass = C.jclass(util.JFindClassPtrOrDie(env, "com/veyron/runtimes/google/security/PublicID"))
jECPublicKeyInfoClass = C.jclass(util.JFindClassPtrOrDie(env, "com/veyron/runtimes/google/security/PublicID$ECPublicKeyInfo"))
jCaveatImplClass = C.jclass(util.JFindClassPtrOrDie(env, "com/veyron/runtimes/google/security/Caveat"))
- jContextClass = C.jclass(util.JFindClassPtrOrDie(env, "com/veyron2/security/Context"))
jContextImplClass = C.jclass(util.JFindClassPtrOrDie(env, "com/veyron/runtimes/google/security/Context"))
jCaveatClass = C.jclass(util.JFindClassPtrOrDie(env, "com/veyron2/security/Caveat"))
jServiceCaveatClass = C.jclass(util.JFindClassPtrOrDie(env, "com/veyron2/security/ServiceCaveat"))
@@ -118,6 +116,16 @@
return jServiceCaveats
}
+//export Java_com_veyron_runtimes_google_security_PublicID_nativeEquals
+func Java_com_veyron_runtimes_google_security_PublicID_nativeEquals(env *C.JNIEnv, jPublicID C.jobject, goPublicIDPtr, goOtherPublicIDPtr C.jlong) C.jboolean {
+ id := *(*security.PublicID)(util.Ptr(goPublicIDPtr))
+ other := *(*security.PublicID)(util.Ptr(goOtherPublicIDPtr))
+ if reflect.DeepEqual(id, other) {
+ return C.JNI_TRUE
+ }
+ return C.JNI_FALSE
+}
+
//export Java_com_veyron_runtimes_google_security_PublicID_nativeFinalize
func Java_com_veyron_runtimes_google_security_PublicID_nativeFinalize(env *C.JNIEnv, jPublicID C.jobject, goPublicIDPtr C.jlong) {
util.GoUnref((*security.PublicID)(util.Ptr(goPublicIDPtr)))