Hello, folks.

I abuse the Rhino shell on a regular basis and now I'm going for my
first earnest attempt at embedding. Getting the engine to nominally
work is a piece of cake, but security is another matter.

My two overlapping goals for implementing security are, first, to keep
the scripter's paws off Packages.*, java.*, and any other direct
exposure to Java not explicitly allowed by me, and second, to prevent
the scripter from accessing privileged system stuff like file and
socket I/O--except via interfaces provided by me.

The following is a sample embedding; its purpose is to load a
JavaScript function hook() provided in defineHook.js, then call the
function with parameters and display the result.

import java.util.*;
import java.io.*;
import java.net.*;

import org.mozilla.javascript.*;
import java.security.CodeSource;
import java.security.CodeSigner;

public class Might {
    public static void main(String[] args) {
        // Set up semi-bogus credentials for evaled script
        URL url = null;
        try {
            url = new URL("http://example.com/reader";);
        } catch(MalformedURLException e) {}
        CodeSigner[] codeSigners = new CodeSigner[] {};
        final CodeSource codeSource = new CodeSource(url,codeSigners);

        // Boot the engine, load defineHook.js, run hook(3,2), print
result.
        ContextFactory cf = new ContextFactory();
        cf.call(new ContextAction() {
            public Object run(Context cx) {
                cx.setSecurityController(new PolicySecurityController
());
                try {
                    Scriptable scope = cx.initStandardObjects();
                    Reader r = new BufferedReader(
                        new InputStreamReader(new FileInputStream
("defineHook.js"))
                    );
                    cx.evaluateReader(scope,r,"defineHook",
0,codeSource);
                    r.close();

                    Object hook = scope.get("hook",scope);
                    if(hook instanceof Function) {
                        Object s = ((Function)hook).call
(cx,scope,scope,new Object[] {3,2});
                        System.out.println("Got <" + s + ">");
                    } else {
                        System.err.println("hook is not a function");
                    }
                } catch(FileNotFoundException ex) {
                    System.err.println("File not found");
                } catch(IOException ex) {
                    ex.printStackTrace();
                }
                return null;
            }
        });
    }
}


As defineHook.js, the following works as is appropriate:

function hook(a,b) {
    return (a*b)+1;
}

The following also works, but it shouldn't; I want my program to
disallow the I/O operation as well as disallowing access to the
objects (java, java.lang, java.lang.System, ...) in the first place.

function hook(a,b) {
    java.lang.System.out.println("I disobey!");
    return (a*b)+1;
}

The idea of getting the PolicySecurityController involved was to
disable via policy access to certain functionality if the codebase was
"http://example.com/reader";. After futzing around with it for a while,
I found that any policy I wrote that allowed the file read also
allowed the pathological I/O access. Here's an example of what I've
been trying, but don't dwell on it because it's not even my idea of
correct:

// Where my classes live
grant codeBase "file:/home/dro/experiments/java/" {
        permission java.security.AllPermission;
};
// Where Rhino and a zillion other dist .jar files live
grant codeBase "file:/usr/share/java/*" {
        permission java.security.AllPermission;
};

I'd like to hear about how I should be going about this (as opposed to
how I *am* going about it) from someone more intimate with Rhino
security (or maybe Java security in general). Would someone do me the
honor?

Thanks
dro
_______________________________________________
dev-tech-js-engine-rhino mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-tech-js-engine-rhino

Reply via email to