Subject: Some technical issues on Java binding

From: Michael Smith <[email-masked]>
Date: Fri, 26 Mar 1999 12:40:04 -0500

I've been going over Jack Kabat's Internet-Draft
and comparing it with the prototype Java binding
we did here in my atelier. (For Javadoc and some
observations, see <http://www.panix.com/~jlefevre/GSS>).
Modulo the interface/concrete class issue (I did 
interfaces, Jack did classes), there is a strong 
family resemblance between the two. There are some 
areas of divergence which seem to me to raise some 
interesting, if minor, technical issues:

1) Mapping things with output parameters is always
a little untidy in Java. Jack and I adopted slightly 
different approaches to the problem of multiple 
outputs from per-message calls (wrap/unwrap, 
get/verify MIC). His proposal requires the caller 
of these functions to get an instance of the class 
MessageProp, setting the QOP and the privacy-requested 
flag in the constructor, and then pass this as a 
parameter to the per-message calls. Inside these 
calls, other member values of the MessageProp object
are set (e.g. actual QOP, privacy, token-related
flags, etc.). When the call returns, the caller can 
then read these values from the MessageProp object. 

Our approach, on the other hand, is to have the 
per-message calls create and return an instance of 
a thing with the (admittedly unwieldy) name of 
GSSPerMessageCallResult, which has members with the 
actual QOP, privacy, token flags etc., as well as 
major and minor status and the actual output of the 
function (wrapped or unwrapped data, MIC, etc.). 
Our per-message calls take requested QOP and 
privacy as direct parameters (rather than as 
preset elements of the MessageProp object, as in 
Jack's scheme). 

It seems to me that our approach has the advantage of
being simpler for the application programmer. 

2) As far as I can tell, Jack's functions only 
return major and minor status when an exception is 
thrown; otherwise, "no news is good news". We took 
the approach of breaking out major and minor status, 
as well as token flags, and output byte arrays for 
tokens, into a separate interface, GSSStatus; our 
GSSException contains one of these, a good many 
functions have it as their return type, and the 
PerMessageCallResult (alluded to above) extends it. 

It seemed to us that "status" of the call is 
conceptually separate from exceptionality, and 
potentially useful even where there is nothing 
"exceptional"; hence the distinction. (Also, of 
course, our status carries output tokens too, and 
thus has significant freight even when all the
status lights are green.)  

3) We have two different classes, GSSMechName 
(corresponding to "name for mechanism") and GSSname
(corresponding to plain old name). The former
extends the latter, and adds the method export()
(which is only valid for a "name for mechanism"). 
GSSName has a method which takes a mechanism OID
as a parameter and disgorges a GSSMechName
(the method is canonicalize(), which of course
represents the mapping of GSS_Canonicalize_name).
Jack's approach is not to have different classes;
he has a single class, GSSName, an instance of 
which may either correspond to a "name for 
mechanism" or not. If so, then export() is 
valid; if not, not (and export() presumably 
throws an exception if called). A GSSName is 
a "name for mechanism," in Jack's mapping, if 
its constructor was called with a mechoid 
parameter, or if the method "canonicalize" was 
called subsequent to the object's creation; 
that is, canonicalize(), in Jack's approach, 
operates "in place". I presume the way one 
gets a "name for mechanism" and still retains
the non-mechanism-specific name is to call 
clone() on a non-mech-specific name, and then
canonicalize() on the clone. 

This seems a little roundabout to us; also, of 
course, it seems that objects with different 
sets of methods ought to be in different classes. 

4) GSS has two methods for adding mechanisms to 
credentials: add and add-in-place. Add creates a 
new credential with the added mechanism included; 
add in place doesn't create the new credential, but 
just folds the new mechanism into the existing 
credential. We replicated this arrangement in our 
implementation; our GSSCredential interface defines 
a method addCredential(), which returns a new instance
of GSSCredential, and another method 
addCredentialInPlace(), which returns void and operates
on the existing credential. Jack's approach, in 
effect, has only the add-in-place version; if you 
want a new credential, you add in place and then 
clone(), or vice-versa. 

5) Very minor: it isn't obvious to me why there are 
two versions of equals() in Jack's GSSName. One of them
takes a GSSName parameter and the other takes an
Object and throws an exception if the two can't 
be compared. I imagine there's some reason for this, 
but it would be useful to have that stated. 

6) Also minor: there's a method of GSSName called 
isAnonymous(), which doesn't, as far as I can see, 
correspond to anything in the GSS spec. What's this 
for? 

7) Similar to above: there's a method, getDefaultMech,
returning a mechoid, in GSSManager. Again this doesn't
seem to correspond to anything in GSS, as far as I can 
see.

8) Jack has a GSS-specific Channel Binding class and 
we don't; but I think this is a good idea and ought to 
be there. 

9) Similarly, his Oid class is richer in functionality
than ours, in ways that I think make good sense. 

10) As the result of an extended discussion some months 
ago, Jack's and my specifications both contain versions 
of the per-message and token-establishment calls that use
input and output streams rather than byte arrays for the 
tokens. This technique was originally devised as another 
way around the lack of output parameters in Java, but 
I'd like to hear some feedback from other people: 
is this a good idea, or not? If memory serves, Jack 
and I agreed in correspondence that the calls which take 
streams as parameters should not block on reading or 
writing these streams; this implies (inter alia) that the 
caller needs to ensure that at least an entire token is 
present in the input stream before calling the method. 
(And what does the method do if there isn't a complete 
token on the input stream, or it can't write the output 
stream -- rewind it and/or throw an exception? If the 
latter, with what major status? If not, with what output?) 

I wonder if this  "feature" isn't more trouble 
than it's worth, although Jack did convince me that it 
was kind of cool when we were exchanging e-mails about 
it. 

--Michael Smith
  [email-masked]

==========================================================================
This message was posted through the Stanford campus mailing list
server.  If you wish to unsubscribe from this mailing list, send the
message body of "unsubscribe ietf-cat-wg" to [email-masked]