On 6/8/13 12:20 PM, Xuelei Fan wrote:

The recommended way was

   while (!context.isEstablished()) {
      context.initSecContext(is, os);
      os.flush();
   }

When I say "easier", I mean it looks like there is no need to make any
application change and this method can just write KRB_ERROR into os and
*then* throw the exception.

But this is a behavior change and can be quite dangerous.
Can the scenarios look like:
1. need to reject the negotiation in this round to call initSecContext;
2. generate a reject message, and mark that the negotiation is
terminated, return as normal(no exception);
3. next round to call initSecContext(), as the negotiation has
terminated, throw exception accordingly.
>
> Is the InputStream a potential problem that we cannot do above scenarios?

On the contrary, this might work for inputstream method because we can just throw an exception right at the beginning of the next initSecContext call and needn't touch InputStream at all. But for the byte[] token method, the read is outside JGSS-API. Will there be an IOException? Or, will it read a token of another fallback protocol?

Also, everyone knows in Kerberos there is one AS-REQ and at most one AS-REP. Therefore I can imagine an acceptor application simply calls acceptSecContext once. If it does not throw an exception, everything is fine. This is not correct in strict JGSS-API, but it's quite possible.


I'd rather also write

   while (!context.isEstablished()) {
      try {
         context.initSecContext(is, os);
      } catch (GSSException e) {
         if (e.getOutputToken() != null) {
            os.write(e.getOutputToken());
            os.flush();  // in finally? not sure.
            throw e;
         }
      }
      os.flush();
   }

The coding style looks really strange to me.  If need to send something,
the initSecContext() should not throw exceptions.

Well, you can say the C function is also strange that it returns a token but also returns a failure status code at the same time.


Per RFC 2853, a common usage of initSecContext is as:

    do {
        byte[] outTok = context.initSecContext(inTok, 0, inTok.length);

        // send the token if present
        if (outTok != null)
            sendToken(outTok);


        // check if we should expect more tokens
        if (context.isEstablished())
            break;

        // another token expected from peer
        inTok = readToken();
    } while (true);


I would like another approach if there is strong motivation to make the
change.  That's, the initSecContext() does not throw exception when a
reject message is needed (it should not, because reject message is the
right message of a negotiation process). But we add a new method to
identify the statue, isTerminated() or something similar.  Then the code
is updated to:

    do {
        byte[] outTok = context.initSecContext(inTok, 0, inTok.length);

        // send the token if present
        if (outTok != null)
            sendToken(outTok);


        // check if we should expect more tokens
        if (context.isEstablished())
            break;

+      // check if we should expect more tokens
+      if (context.isTerminated())
+          break;  // fail break;

        // another token expected from peer
        inTok = readToken();
    } while (true);

This means every existing app needs to be rewritten. Otherwise, the result of that readToken() call will be unpredictable.

Also, I do believe many JGSS applications out there already have their own application-level error handling codes. If they switch to the GSSException::getOutputToken() method, that's good. Otherwise, no harm is made.

Thanks
Max


Xuelei

and add a clarification to the method saying no bytes will be written to
os if there is a GSSException.

Thanks
Max


--Sean


Thanks
Max

[1] http://tools.ietf.org/html/rfc2743#page-46


Reply via email to