Interfacing PTMK with Jigsaw and HotJava
This document describes the environment where the kernel (PTMK) is run in my
project. In short, PTMK is implemented as an "IngoingFilter" under
Jigsaw HTTP Client package, and Jigsaw Client package is run under
HotJava web browser.
HotJava
----------------------------
Jigsaw Client package
----------------------------
PICS Trust Mgt Kernel (PTMK)
----------------------------
Profile-0.9 Interpreter
HotJava
Sun's HotJava is a
full-blown web browser written entirely in Java language. It is now in
its 1.0-prebata release. HotJava is chosen because it interfaces nicely
with Jigsaw Client API.
To use Jigsaw Client package under HotJava, all you need to do is to change
java.protocol.handler.pkgs
property to w3c.www.protocol
before launching HotJava.
Jigsaw HTTP Client Package
Jigsaw is originally designed as a web server, whose purpose is to provide
a basis for experimenting new server-side features. Recently it is extended
to provide a HTTP Client API.
The API is very simple: it takes in a Request (generally a URL) and
returns a Reply (the content of the URL). In general, this HTTP
Client API serves similar function as the standard java.net.URLConnect
class, but this API is much more robust and modular.
A typical loop inside the Jigsaw Client looks like the following:
| Request from Caller ^ Reply to Caller
\ / |
--------------------------------------
| HttpManager |
--------------------------------------
| Request ^
\ / |
------------------ Reply |
| IngoingFilters |---------------> |
------------------ |
| Request |
\ / |
------------------- |
| HttpConnection | |
------------------- |
| Request, Reply |
\ / |
------------------- Reply |
| OutgoingFilters |--------------> |
------------------- |
| |
-----------------------------
- HttpManager:
runs the request. In particular, it determines which filters to run for a
given Request, and calls them sequentially. It also examines each Reply from
the filters and determines if further processing is necessary.
- IngoingFilters:
a set of filters running sequentially. Each IngoingFilter takes a Request as
input, and outputs a Reply. If the Reply is null, the Request flows through
the next IngoingFilter. If not, HttpManager simply returns the Reply and
exits early. You can imagine a CacheFilter, whose Reply is the
complete document when cache hits, null when cache misses.
- HTTPConnection:
go in the net and fetch the document.
- OutgoingFilters:
each OutgoingFilter takes both a Request and a Reply as
input, and outputs another Reply. If the OutgoingFilter outputs null,
HttpManager continues to the next filter, otherwise, it will simply forward
the Reply and exit. You can imagine a Authentication Filter that looks at
the input Reply (generated by the HttpConnection), and if it says
"authentication required", will prompt user for password and then call
HttpManager again.
PTMK (the kernel) as an IngoingFilter
Under this architecture, the kernel can be implemented as a filter. It will
be an IngoingFilter for both performance reason and security reason; you
don't want to fetch the document and later realize you don't need it, and
you don't want cache filter to return the document before PTMK has a chance
to speak.
To be a valid instance of a Jigsaw filter, you need to implement three
methods: Initialization
, ingoingFilter
, and
outgoingFilter
. In PTMKFilter, Initialization
defines the default interpreter and script to run, as well
as various callback. IngoingFilter
sets the statement list,
invoke the interpreter and examine the returned statement list.
OutgoingFilter
does nothing in this case.
Here are some pseudo-codes for class PTMKFilter .
Fetch Callback
It is trickier to define a proper fetch callback when PTMK is treated as
a filter in Jigsaw Client package. So I devote the rest of the document on
this. Below are my observations:
- Need to fetch the actual document during interpretation?
yes, it is required if you need to check the message digest (check-md5). It
would be nice if you can cache that document to avoid retrieving twice.
- What is Fetch Callback?
fetch callback takes in a URL and returns the document, which is identical to
this API we are nested in. So there seems to be no reason to create a
new different fetch mechanism below another fetch mechanism.
- More Than One Type of Fetch Callback?
It was proposed that we should use a "simpler" mechanism to fetch PICS labels
or some other simple documents (such as certificates) for the interpreter.
I disagree. You can imagine some label bureaus requiring some
authentication information and cookies to retrieve a PICS label, just as
a web server for a regular document.
Based on these observations, fetch callback should simply calls the HttpManager
recursively, but with one difference: it will not call the PTMKFilter to
prevent infinite loop. And now you get all the features such as caching,
and cookie handling for free.
Here are some pseudo-codes for Fetch Callback .
Other Concerns
- No Explicit Caching:
caching the document (in the interpreter) is not explicitly specified in
the fetch_callback method, given a method has no state. You may (kindly)
ask the interpreters to return the document back to the kernel, if it
happens to fetch it during the interpretation. This may solve the problem
but will make the interface between the kernel and the interpreter more ugly.
In Jigsaw, caching is transparent if you register a cache filter in the
HttpManager, which I believe how caching should work anyway.
- "Timeout" PtmkFilter:
The request (with reply) flows through each filter sequentially. It works
only if all filters behaves properly. Since PTMKFilter may create infinite
loop or may make an impatient user cries, it would be nice if HttpManager can
"timeout" PTMKFilter. I need to investigate this further.
- "Jigsaw" Independent:
The underlying trust management engine should be application independent, and
I don't think I have violated this rule yet. What I described up till now is
only the kernel and the callbacks, which are supposed to be architecture
dependent. I have yet described the interface between the PTMK and
the Interpreter, which would be Jigsaw independent. Detail to come.
- Filter Priority:
it seems appropriate to set PTMKfilter as the highest priority (first to
run) for the sake of enforcing the policy. However, you can imagine a user
may want to run a filter that logs all requests. In this case,
the filter will work properly only if that filter's priority is higher than
PTMKFilter. So I believe the priority rule should be
"PTMKFilter should be placed before any IngoingFilter that may return the
actual document (such as caching filter)".
Next Step
- specify the API for the interpreter
- parse Profile-0.9 scripts
- enjoy my (and your) Columbus weekend ...!?
public class PTMKFilter implements PropRequestFilter {
public void initialize(HttpManager manager) {
// set default profile interpreter
// set default script (policy) for the interpreter
// set the fetch callback
// set the default ptmk_cb
// install as a global filter
this.manager = manager;
manager.setFilter(this);
manager.setAllowUserInteraction(true);
}
// the kernel
public Reply ingoingFilter(Request request) {
return null;
// generate the initial two statements and the statement list.
Statement userRequest = new Statement("USER",
"("+Request.getMethod()+" "+ Request.getURL()",
"http://actions-v1");
Statement userProfile = new Statement("application",
this.defaultScript,
"http://labels");
StatementList stmtList = new StatementList();
// put both statements in the statement list. UR and UP are the IDs
// of the statement in the statement list.
int UR = stmtList.add(userRequest);
int UP = stmtList.add(userProfile);
// provides pointer to the user request and the script for the
// interpreter
stmtList.ptrUserRequest = UR;
stmtList.ptrUserProfile = UP;
// invoke the interpreter
StatementList replyStmtList = this.defaultInterpreter.eval(stmtList);
// generateReply looks at the statement list, returns null
// if the request is granted, or returns a "sorry, viewing URL is
// not allowed" Reply if not.
return(generateReply(replyStmtList));
}
// do nothing
public Reply outgoingFilter(Request request, Reply reply)
throws HttpException
{
return(null);
}
}
public InputStream fetch_callback(String url) {
// Get the manager
HttpManager manager = HttpManager.getManager();
// exclude PTMKFilter
RequestFilter filter = getGlobalFilter(PTMKFilter);
manager.setFilter(null, *, filter);
// create the request
Request request = manager.createRequest();
request.setURL(new URL(args[0]));
request.setMethod("GET");
// run the request and return the reply
Reply reply = manager.runRequest(request);
return(reply.getInputStream());
}